MySql 防注入及SQL语句安全检测

1 function CheckSql($db_string,$querytype='select')

2 {

3 global $cfg_cookie_encode;

4 $clean = '';

5 $error='';

6 $old_pos = 0;

7 $pos = -1;

8 $log_file = DEDEINC.'/../data/'.md5($cfg_cookie_encode).'_safe.txt';

9 $userIP = GetIP();

10 $getUrl = GetCurUrl();

11

12 //如果是普通查询语句,直接过滤一些特殊语法

13 if($querytype=='select')

14 {

15 $notallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}";

16

17 //$notallow2 = "--|/\*";

18 if(eregi($notallow1,$db_string))

19 {

20 fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n");

21 exit("<font size='5' color='red'>Safe Alert: Request Error step 1 !</font>");

22 }

23 }

24

25 //完整的SQL检查

26 while (true)

27 {

28 $pos = strpos($db_string, '\'', $pos + 1);

29 if ($pos === false)

30 {

31 break;

32 }

33 $clean .= substr($db_string, $old_pos, $pos - $old_pos);

34 while (true)

35 {

36 $pos1 = strpos($db_string, '\'', $pos + 1);

37 $pos2 = strpos($db_string, '\\', $pos + 1);

38 if ($pos1 === false)

39 {

40 break;

41 }

42 elseif ($pos2 == false || $pos2 > $pos1)

43 {

44 $pos = $pos1;

45 break;

46 }

47 $pos = $pos2 + 1;

48 }

49 $clean .= '$s$';

50 $old_pos = $pos + 1;

51 }

52 $clean .= substr($db_string, $old_pos);

53 $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean)));

54

55 //老版本的Mysql并不支持union,常用的程序里也不使用union,但是一些黑客使用它,所以检查它

56 if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0)

57 {

58 $fail = true;

59 $error="union detect";

60 }

61

62 //发布版本的程序可能比较少包括--,#这样的注释,但是黑客经常使用它们

63 elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, '#') !== false)

64 {

65 $fail = true;

66 $error="comment detect";

67 }

68

69 //这些函数不会被使用,但是黑客会用它来操作文件,down掉数据库

70 elseif (strpos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0)

71 {

72 $fail = true;

73 $error="slown down detect";

74 }

75 elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0)

76 {

77 $fail = true;

78 $error="slown down detect";

79 }

80 elseif (strpos($clean, 'load_file') !== false && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0)

81 {

82 $fail = true;

83 $error="file fun detect";

84 }

85 elseif (strpos($clean, 'into outfile') !== false && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0)

86 {

87 $fail = true;

88 $error="file fun detect";

89 }

90

91 //老版本的MYSQL不支持子查询,我们的程序里可能也用得少,但是黑客可以使用它来查询数据库敏感信息

92 elseif (preg_match('~\([^)]*?select~s', $clean) != 0)

93 {

94 $fail = true;

95 $error="sub select detect";

96 }

97 if (!empty($fail))

98 {

99 fputs(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||$error\r\n");

100 exit("<font size='5' color='red'>Safe Alert: Request Error step 2!</font>");

101 }

102 else

103 {

104 return $db_string;

105 }

106 }