命令执行漏洞发生的根本原因是"用户可控的"、”未经净化“的数据直接作为可执行命令函数的参数,造成攻击者直接实施攻击。
1、参数是否用户可控,如用户输入的外部数据是否拼接到可执行命令函数的参数内?
2、是否配置了全局过滤器?检查过滤器的配置,是否所有命令的执行都经过过滤器处理,过滤器的过滤规则是否符合安全要求?
Java
String btype = request.getParameter("inputparam");
String cmds[] = {"cmd.exe","/K","\"C: &&del C:\\r2.txt"+btype+" &&del C:\\r1.txt \""};
System.Runtime.getRuntime().exec(cmds);
此时cmd.exe使用了/K参数,将后续传入的参数用户命令执行,这里拼接的参数从前段中获取,对参数未作任何过滤,导致命令注入。
PHP
$arr = explode("&",$_COOKIE["USER"]);
//--验证cookie。
for($i=0;$i<count($arr);$i++)
{
if(ereg("^SKIN=(.*)$",$arr[$i],$reg))
{
$skin = trim($reg[1]);
}
if(ereg("^UID=(.*)$",$arr[$i],$reg))
{
$uid = trim($reg[1]);
}
if(ereg("^DOMAIN=(.*)$",$arr[$i],$reg))
{
$domain = trim($reg[1]);
}
if(ereg("^TOKEN=(.*)$",$arr[$i],$reg))
{
$token = trim($reg[1]);
}
}
$part = $_GET['s'];
//$uid = "support";
//$domain = "**.**.**.**";
$users = readAddress($uid, $domain);
从上述代码看到代码直接从cookie中获取参数USER,然后赋值给uid和domain,接着看看函数readAddress($uid, $domain)究竟做了什么
function readAddress($uid,$domain){
$binary = array();
$userDir = getUserDir($uid,$domain);
$addressDir = trim($userDir, "\n\r ")."/Profile/alias.individual";
if(!is_file($addressDir)) return false;
$fp = fopen($addressDir, "r");
if(!$fp){
echo "打开地址薄失败";
exit;
}
while(false != ($content = fgets($fp, 568))){
$binary[] =unpack("a20nick_name/a40email/a40name/a60h_street_address/a30h_city/a30h_province/a8h_zip/a20h_country/a16h_phone/a30c_company/a60c_street_address/a30c_city/a30c_province/a8c_zip/a20c_country/a16c_phone/a16pager/a16cellular/a16fax/a20icq/a30other/a5b_year/a3b_month/a3b_day",$content);
}
//var_dump($binary);
return $binary;
}
看到函数内,uid和domain又进入了函数getUserDir( u i d , uid, uid,domain),这边继续跟进getUserDir
function getUserDir($uid, $domain) {
$handle = popen("/var/eyou/sbin/hashid $uid $domain", 'r');
$read = fread($handle, 2096);
pclose($handle);
return $read;
}
观察到最后uid和domain进入了popen $handle = popen(“/var/eyou/sbin/hashid $uid $domain”, ‘r’);这里uid和domain没有经过任何过滤直接进入了命令,导致任意命令执行。
针对代码中编写的命令执行语句,那么可通过搜索“Runtime.getRuntime().exec”直接定位漏洞代码,然后根据数据流的过程,逐步向上回溯,定位到用户可控参数。
String btype = request.getParameter("inputparam");
String cmds[] = {"cmd.exe","/K","\"C: &&del C:\\r2.txt"+btype+" &&del C:\\r1.txt \""};
System.Runtime.getRuntime().exec(cmds);
当服务器后端调用Runtime.getRuntime().exec的过程为以上逻辑时,存在系统命令注入漏洞,漏洞验证举例如下
2、执行代码的参数或文件名,禁止和用户输入相关,只能由开发人员定义代码内容,用户只能提交“1、2、3”参数,代表相应代码。