PHP代码审计笔记:条件内初始化SQL变量造成SQL注入
概述
总结来自于Metinfo最新版本的两个SQL注入漏洞,两个漏洞都因为在php代码内在条件语句中初始化或直接用.=
拼接SQL语句,导致可以构造条件,控制变量进行SQL注入。
详细
漏洞代码其一:
/include/global/listmod.php 文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23if($imgproduct){
$ipcom = $imgproduct=='product'?$productcom:$imgcom;
$serch_sql .=" where lang='$lang' {$mobilesql} and (recycle='0' or recycle='-1')";
if($ipcom=='com')$serch_sql .= " and com_ok=1";
if($class1 && $class_list[$class1]['module']<>$ipmd&&$class1!=10001){
$serch_sql .= ' and (('.$class1sql;
}else{
$serch_sql .= ' and ((1=1';
}
}else{
$serch_sql=" where lang='$lang' {$mobilesql} and (recycle='0' or recycle='-1') and (( $class1sql ";
}
这行代码位于源码的第72行,可以发现这里使用$serch_sql .=" where lang='$lang' {$mobilesql} and (recycle='0' or recycle='-1')";
的方式定义并初始化serch_sql变量,然而却是在if($imgproduct)
的判断条件中。在这代码之前,并未对serch_sql进行初始化,所以只要我们达成if条件,就可以控制SQL语句进行SQL注入。
漏洞代码其二:
/search/search.php文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32}else{
$module=intval($module);
if($class1)$module=0;
if(intval($module)){
$serch_sql.=" where lang='$lang' and (recycle='0' or recycle='-1') and displaytype='1' ";
}else{
$class1_info=$class_list[$class1];
if(!$class1_info)okinfo('../',$pagelang[noid]);
$class1sql=" class1='$class1' ";
$class2sql=" class2='$class2' ";
$class3sql=" class3='$class3' ";
$class1re = '';
if($class1&&!$class2&&!$class3){
foreach($module_list2[$class_list[$class1]['module']] as $key=>$val){
if($val['releclass']==$class1){
$class1re.=" or class1='$val[id]' ";
}
}
if($class1re){
$class1sql='('.$class1sql.$class1re.')';
}
}
if($class_list[$class2]['releclass']){
$class1sql=" class1='$class2' ";
$class2sql=" class2='$class3' ";
$class3sql="";
}
$serch_sql=" where lang='$lang' and (recycle='0' or recycle='-1') and displaytype='1' and $class1sql ";
if($class2&&$class2sql)$serch_sql .= " and $class2sql ";
if($class3&&$class3sql)$serch_sql .= " and $class3sql ";
$order_sql=" order by top_ok desc,com_ok desc,no_order desc,updatetime desc,id desc";
}
可以发现$order_sql=" order by top_ok desc,com_ok desc,no_order desc,updatetime desc,id desc"
这样的定义及初始化语句在else条件体中,只要我们不进入else条件就可以控制变量导致注入。
然后又有非else语句的代码:1
2
3if(intval($module)){
$serch_sql.=" where lang='$lang' and (recycle='0' or recycle='-1') and displaytype='1' ";
}
又是.=
,可以拼接sql语句。
总结
修复方案:
Metinfo官方的修复方案是: 在条件外把变量定义为空字符串。
作为临时的修复方法是可行的。但是其实总归来说,还是直接使用.+
拼接SQL字符串变量的错,再加上动态语言的变量无需声明直接使用和PHP的变量get传入,在方便开发者的同事,也会出现很多安全隐患,开发的时候还是得小心坑为好啊。
参考:
https://www.wooyun.org/bugs/wooyun-2015-0125648
https://www.wooyun.org/bugs/wooyun-2015-0121480