审计项目:https://github.com/HurryBy/probe
在找IP探针的时候碰到的开源项目,遂审计之

提交的ISSUES:https://github.com/HurryBy/probe/issues/2

/modules/getInformation/gps.php文件中第26行,在获取gps_longitude和gps_location值后直接使用了SQL语句将获得的两个值写入到数据库中,而这两个参数值通过自己构建POST包是可控的,当然可控的变量也包括"key"的值,并且程序没有做任何过滤

    // 根据timestamp & key写数据
    $conn = new mysqli($db_host.":".$db_port, $db_user, $db_password, $db_name);
    $sql = "UPDATE `tanzhen_information` SET `gpsaddress` = '$gps_location', `gpsjing` = '$gps_longitude', `gpswei` = '$gps_latitude' WHERE `tanzhen_information`.`timestamp` = '$time' AND `tanzhen_information`.`keyvalue` = '$key';";

过滤方式

后来发现开发更新了项目代码,那就来简单看看(水一下文)。
开发在各处都加上了过滤代码,使用了两个替换函数。
str_replace函数:替换字符
preg_replace函数:正则匹配替换字符
可以看到,str_replace函数将&、尖括号替换成了实体符号,于sql注入无碍
下面将select等字符替换为空值,很明显双写绕过。

//防xss mysql等注入

$checkdata = $key;
function clean($data){
// Fix &entity\n;
$data=str_replace(array('&','<','>'),array('&amp;','&lt;','&gt;'),$data);
$data=preg_replace('/(&#*\w+)[\x00-\x20]+;/u','$1;',$data);
$data=preg_replace('/(&#x*[0-9A-F]+);*/iu','$1;',$data);
$data=html_entity_decode($data,ENT_COMPAT,'UTF-8');
$data=preg_replace('#</*\w+:\w[^>]*+>#i','',$data);
do{// Remove really unwanted tags
$old_data=$data;
$data=preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i','',$data);
}while($old_data!==$data);
//remove javascript tag
$data=preg_replace("/<script[^>]*?>.*?<\/script>/si",' ',$data);
$data=preg_replace('/select|insert|update|delete|\'|\\*|\*|\.\.\/|\.\/|union|into|load_file|outfile/i','',$data);

// we are done...

return $data;

无效过滤

生成探针链接,会自动请求gps.php存储获取到的经纬度,更新前的漏洞也是交的这个issues

但是仔细一看代码发现,这个gps.php文件压根儿没有被过滤函数覆盖到,依旧直接注入:



修复方案

按照原程序中的方式,给gps.php文件里输入的经纬度值进行处理,key和time先不表,只是学习;
如果只是使用preg_replace()将匹配到的威胁字符替换为空,还是可以双写绕过,这里借用碰到的其他项目中的防御手段,在后面使用判断语句,通过判断输入的内容和处理过的内容是否一致来中断恶意行为,从而达到过滤效果。