1: | <?php
|
2: |
|
3: | if (file_exists(XOOPS_ROOT_PATH . '/class/database/drivers/' . XOOPS_DB_TYPE . '/database.php')) {
|
4: | require_once XOOPS_ROOT_PATH . '/class/database/drivers/' . XOOPS_DB_TYPE . '/database.php';
|
5: | } else {
|
6: | require_once XOOPS_ROOT_PATH . '/class/database/' . XOOPS_DB_TYPE . 'database.php';
|
7: | }
|
8: |
|
9: | require_once XOOPS_ROOT_PATH . '/class/database/database.php';
|
10: |
|
11: | |
12: | |
13: |
|
14: | class ProtectorMySQLDatabase extends XoopsMySQLDatabaseProxy
|
15: | {
|
16: | public $doubtful_requests = array();
|
17: | public $doubtful_needles = array(
|
18: |
|
19: | 'concat',
|
20: | 'information_schema',
|
21: | 'select',
|
22: | 'union',
|
23: | '/*',
|
24: | '--',
|
25: | '#');
|
26: |
|
27: | |
28: | |
29: |
|
30: | public function __construct()
|
31: | {
|
32: | $protector = Protector::getInstance();
|
33: | $this->doubtful_requests = $protector->getDblayertrapDoubtfuls();
|
34: | $this->doubtful_needles = array_merge($this->doubtful_needles, $this->doubtful_requests);
|
35: | }
|
36: |
|
37: | |
38: | |
39: |
|
40: | public function injectionFound($sql)
|
41: | {
|
42: | $protector = Protector::getInstance();
|
43: |
|
44: | $protector->last_error_type = 'SQL Injection';
|
45: | $protector->message .= $sql;
|
46: | $protector->output_log($protector->last_error_type);
|
47: | die('SQL Injection found');
|
48: | }
|
49: |
|
50: | |
51: | |
52: | |
53: | |
54: |
|
55: | public function separateStringsInSQL($sql)
|
56: | {
|
57: | $sql = trim($sql);
|
58: | $sql_len = strlen($sql);
|
59: | $char = '';
|
60: | $string_start = '';
|
61: | $in_string = false;
|
62: | $sql_wo_string = '';
|
63: | $strings = array();
|
64: | $current_string = '';
|
65: |
|
66: | for ($i = 0; $i < $sql_len; ++$i) {
|
67: | $char = $sql[$i];
|
68: | if ($in_string) {
|
69: | while (1) {
|
70: | $new_i = strpos($sql, $string_start, $i);
|
71: | $current_string .= substr($sql, $i, $new_i - $i + 1);
|
72: | $i = $new_i;
|
73: | if ($i === false) {
|
74: | break 2;
|
75: | } elseif (
|
76: | $sql[$i - 1] !== '\\'
|
77: | ) {
|
78: | $string_start = '';
|
79: | $in_string = false;
|
80: | $strings[] = $current_string;
|
81: | break;
|
82: | } else {
|
83: | $j = 2;
|
84: | $escaped_backslash = false;
|
85: | while ($i - $j > 0 && $sql[$i - $j] === '\\') {
|
86: | $escaped_backslash = !$escaped_backslash;
|
87: | ++$j;
|
88: | }
|
89: | if ($escaped_backslash) {
|
90: | $string_start = '';
|
91: | $in_string = false;
|
92: | $strings[] = $current_string;
|
93: | break;
|
94: | } else {
|
95: | ++$i;
|
96: | }
|
97: | }
|
98: | }
|
99: | } elseif ($char === '"' || $char === "'") {
|
100: | $in_string = true;
|
101: | $string_start = $char;
|
102: | $current_string = $char;
|
103: | } else {
|
104: | $sql_wo_string .= $char;
|
105: | }
|
106: |
|
107: |
|
108: | }
|
109: |
|
110: | return array($sql_wo_string, $strings);
|
111: | }
|
112: |
|
113: | |
114: | |
115: |
|
116: | public function checkSql($sql)
|
117: | {
|
118: | list($sql_wo_strings, $strings) = $this->separateStringsInSQL($sql);
|
119: |
|
120: |
|
121: | foreach ($this->doubtful_requests as $request) {
|
122: | if (addslashes($request) != $request) {
|
123: | if (false !== stripos($sql, trim($request))) {
|
124: |
|
125: | $ok_flag = false;
|
126: | foreach ($strings as $string) {
|
127: | if (false !== strpos($string, $request)) {
|
128: | $ok_flag = true;
|
129: | break;
|
130: | }
|
131: | }
|
132: | if (!$ok_flag) {
|
133: | $this->injectionFound($sql);
|
134: | }
|
135: | }
|
136: | }
|
137: | }
|
138: |
|
139: |
|
140: |
|
141: |
|
142: |
|
143: |
|
144: |
|
145: | foreach ($this->doubtful_requests as $request) {
|
146: | if (false !== strpos($sql_wo_strings, trim($request))) {
|
147: | $this->injectionFound($sql);
|
148: | }
|
149: | }
|
150: |
|
151: |
|
152: | if (preg_match('/(\/\*|\-\-|\#)/', $sql_wo_strings, $regs)) {
|
153: | foreach ($this->doubtful_requests as $request) {
|
154: | if (false !== strpos($request, $regs[1])) {
|
155: | $this->injectionFound($sql);
|
156: | }
|
157: | }
|
158: | }
|
159: | }
|
160: |
|
161: | |
162: | |
163: | |
164: | |
165: | |
166: | |
167: | |
168: |
|
169: | public function query($sql, $limit = 0, $start = 0)
|
170: | {
|
171: | $sql4check = substr($sql, 7);
|
172: | foreach ($this->doubtful_needles as $needle) {
|
173: | if (false !== stripos($sql4check, $needle)) {
|
174: | $this->checkSql($sql);
|
175: | break;
|
176: | }
|
177: | }
|
178: |
|
179: | if (!defined('XOOPS_DB_PROXY')) {
|
180: | $ret = parent::queryF($sql, $limit, $start);
|
181: | } else {
|
182: | $ret = parent::query($sql, $limit, $start);
|
183: | }
|
184: |
|
185: | return $ret;
|
186: | }
|
187: | }
|
188: | |