| 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: | |