流程:Apache日志分析,解析GET的URL参数,生成CSV后,使用LOAD INFILE导入数据库;

问题:字段错位

一行数据(1,2,3),导入后成了(1,23,NULL);

原因:分隔符和字段值中的宽字节字符组合成了新字符;

相当于命中了宽字节编码漏洞:

高字节范围129-254的ASCII编码可以和基础字符编码组成一个非法宽字节字符。

造成漏洞的高字节编码范围:0xC0-0xFE

安全的生成CSV文件的方法:

  • 过滤宽字节
  • 转义分隔符,引号

过滤宽字符函数:

function safe_string($string){
if( strlen($string) > 2 &&
//攻击发生在字符串的最后两个字节,倒数第二个字节ASCII码大于129,倒数第一个字节ASCII码小于127.
(ord(substr($string,-2,1)) >= 129 &&  ord(substr($string,-1,1))<127) ){
$string = substr($string, 0, -1);
return safe_string($string);
}
return $string;
}

示例代码:

$value =  mysql_real_escape_string(safe_string($value));

“$value”,”$value”

倒入这样的CSV就万无一失了,不会出现字段对齐问题。