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: public function &query($sql, $limit = 0, $start = 0)
169: {
170: $sql4check = substr($sql, 7);
171: foreach ($this->doubtful_needles as $needle) {
172: if (false !== stripos($sql4check, $needle)) {
173: $this->checkSql($sql);
174: break;
175: }
176: }
177:
178: if (!defined('XOOPS_DB_PROXY')) {
179: $ret = parent::queryF($sql, $limit, $start);
180: } else {
181: $ret = parent::query($sql, $limit, $start);
182: }
183:
184: return $ret;
185: }
186: }
187: