登录 |

LOAD DATA INFILE 宽字节导致字段错位

2009年05月9日 下午 59:22 | 作者:hemon

流程: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就万无一失了,不会出现字段对齐问题。

MySQL获取汉字拼音首字母函数

2008年03月14日 下午 16:58 | 作者:hemon

做价格数据库(http://cms.xxty.cn/price),农产品搜索提示需要支持字母,网上的mysql函数只支持单个汉字,另外SQL也写得不规范,重写:支持多个汉字。
用法:
SELECT pinyin(’精神鸦片’);
=> JSYP

  1. DROP TABLE IF EXISTS `pinyin`;
  2.  
  3. CREATE TABLE `pinyin` (
  4.   `letter` char(1) NOT NULL,
  5.   `chinese` char(1) NOT NULL,
  6.   PRIMARY KEY  (`letter`)
  7. ) ENGINE=MyISAM DEFAULT CHARSET=gbk;
  8.  
  9. insert  into `pinyin`(`letter`,`chinese`) values 
  10. ('A',''),
  11. ('B','簿'),
  12. ('C',''),
  13. ('D',''),
  14. ('E',''),
  15. ('F',''),
  16. ('G',''),
  17. ('H',''),
  18. ('J',''),
  19. ('K',''),
  20. ('L',''),
  21. ('M',''),
  22. ('N',''),
  23. ('O',''),
  24. ('P',''),
  25. ('Q',''),
  26. ('R',''),
  27. ('S',''),
  28. ('T',''),
  29. ('W',''),
  30. ('X',''),
  31. ('Y',''),
  32. ('Z','');
  33.  
  34. DELIMITER $$
  35.  
  36. DROP FUNCTION IF EXISTS `PINYIN`$$
  37.  
  38. CREATE FUNCTION `PINYIN`(str CHAR(255)) RETURNS char(255)
  39. BEGIN
  40. DECLARE hexCode char(4);
  41. DECLARE pinyin varchar(255);
  42. DECLARE firstChar char(1);
  43. DECLARE aChar char(1);
  44. DECLARE pos int;
  45. DECLARE strLength int;
  46.  
  47. SET pinyin    = '';
  48. SET strLength = CHAR_LENGTH(LTRIM(RTRIM(str)));
  49. SET pos       = 1;
  50. SET @str      = (CONVERT(str USING gbk));
  51. WHILE pos <= strLength DO
  52.         SET @aChar = SUBSTRING(@str,pos,1);
  53.         SET hexCode = HEX(@aChar);
  54.  
  55.     IF hexCode >= "8140" AND hexCode <= "FEA0" THEN  
  56.         SELECT letter into firstChar
  57.         FROM   pinyin  
  58.         WHERE  chinese >= @aChar
  59.         LIMIT  1;
  60.         END IF;
  61.  
  62.     SET pinyin = CONCAT(pinyin,firstChar);
  63.     SET pos = pos + 1;
  64. END WHILE
  65.     
  66. RETURN UPPER(pinyin);
  67. END$$
  68.  
  69. DELIMITER ;

mysql5.1简体中文参考手册

2006年07月27日 下午 15:49 | 作者:hemon

下载:MySQL 5.1参考手册.chm

查看全文 »