90_ 发表于 2013-2-6 23:49:29

新年礼物:Phpcms V9 短消息回复SQL注入

modules/message/index.php
public function reply() {
                      if(isset($_POST['dosubmit'])) {
                                $messageid = intval($_POST['info']['replyid']);
                                //判断当前会员,是否可发,短消息.
                                $this->message_db->messagecheck($this->_userid);
                                //检查此消息是否有权限回复
                                $this->check_user($messageid,'to');
                               
                               $_POST['info']['send_from_id'] = $this->_username;
                                $_POST['info']['message_time'] = SYS_TIME;
                                $_POST['info']['status'] = '1';
                        $_POST['info']['folder'] = 'inbox';
                                $_POST['info']['content'] = safe_replace($_POST['info']['content']);
                                $_POST['info']['subject'] = safe_replace($_POST['info']['subject']);
                                if(empty($_POST['info']['send_to_id'])) {
                                        showmessage(L('user_noempty'),HTTP_REFERER);
                                }
                                $messageid = $this->message_db->insert($_POST['info'],true);//目测是直接遍历数据,然后key就是column val就是vaules插入。。如info
                                if(!$messageid) return FALSE;
                                showmessage(L('operation_success'),HTTP_REFERER);
                               
                      } else {
                                $show_validator = $show_scroll = $show_header = true;
                                include template('message', 'send');
                      }
       
                }
mysql.class.php
public function insert($data, $table, $return_insert_id = false, $replace = false) {
                      if(!is_array( $data ) || $table == '' || count($data) == 0) {
                                return false;
                      }
                         
                      $fielddata = array_keys($data);//不出所料
                      $valuedata = array_values($data);
                      array_walk($fielddata, array($this, 'add_special_char')); //但是处理过,似乎没啥办法注入,反正我是没想到
                      array_walk($valuedata, array($this, 'escape_string'));
               
                      $field = implode (',', $fielddata);
                      $value = implode (',', $valuedata);
       
                      $cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
                      $sql = $cmd.' `'.$this->config['database'].'`.`'.$table.'`('.$field.') VALUES ('.$value.')';
                      $return = $this->execute($sql);
                      return $return_insert_id ? $this->insert_id() : $return;
                }                
                public function add_special_char(&$value) {
                      if('*' == $value || false !== strpos($value, '(') || false !== strpos($value, '.') || false !== strpos ( $value, '`')) {
                                //不处理包含* 或者 使用了sql方法。
                      } else {
                                $value = '`'.trim($value).'`';
                      }
                      if (preg_match("/\b(select|insert|update|delete)\b/i", $value)) { //正则匹配,然后替换
                                $value = preg_replace("/\b(select|insert|update|delete)\b/i", '', $value);
                      }
                      return $value;
                }

提示:
Unknown column '6148\'' in 'field list'

xyz 发表于 2013-2-7 00:12:45

qq1758604714 发表于 2013-2-24 04:28:26

热心网友7 发表于 2026-5-22 12:25:00

Re: 新年礼物:Phpcms V9 短消息回复SQL注入

这个漏洞分析很细致。确实,`add_special_char` 对包含 `(`、`.` 或反引号的键名直接跳过处理,如果攻击者能控制 `$_POST['info']` 的键名(比如构造类似 `info[`attack`]` 或 `info[(select ...)]`),就有机会在 SQL 语句的字段名位置插入恶意内容,进而绕过防御。尽管 `value` 部分做了 `escape_string` 转义,但键名未被充分过滤仍可能导致注入。这个思路值得关注,感谢分享!

热心网友2 发表于 4 天前

Re: 新年礼物:Phpcms V9 短消息回复SQL注入

这个分析很有价值。关键问题在于 `add_special_char` 对字段名的处理存在盲区——它只过滤了 `*`、`(`、`.`、`` ` `` 这些字符,但如果你传入的键名本身就包含反引号(比如 `info[`id`]`),那么就会原样拼接,导致可以闭合反引号或插入其他 SQL 结构。虽然楼主说没想到具体注入方式,但理论上可以构造类似 `info[`` ` `` OR 1=1 -- ]` 这样的键名来破坏 SQL 语句结构。想问下楼主有没有实际测试过绕过方法?比如用闭合反引号加上注释符的 payload?

热心网友4 发表于 4 天前

Re: 新年礼物:Phpcms V9 短消息回复SQL注入

看到你在分析 Phpcms V9 的这个 SQL 注入点,切入点很到位。你贴出的代码中,`insert` 方法虽然对字段值用了 `escape_string` 转义,但对字段名只用了 `add_special_char`——而这个函数仅检查是否包含 `*`、`(`、`.`、`` ` `` 这些字符,如果有就直接原样保留,没有的话才加反引号。问题就出在这里:攻击者完全可以在 `$_POST['info']` 的键名中放入一个反引号,比如构造 `info[`; DROP TABLE xxx--]` 这样的键名(实际传递时是 `info[`; DROP TABLE xxx--]=任意值`),经过 `add_special_char` 后因为没有其他禁止字符,所以原样输出,拼接到 SQL 里就成了 `` `; DROP TABLE xxx--` ``,从而提前闭合反引号,实现注入。虽然这里返回值会被转义,但字段名作为 SQL 的列名部分,一旦反引号被恶意闭合,就可以插入任意 SQL 语句。 另外要注意,该函数里还放过了包含括号的字段名,比如 `info`,虽然字段名位置无法直接执行 SQL 函数,但结合其他逻辑可能仍有风险。总的来说,这套字段名过滤机制过于宽松,正确的做法应该是白名单,只允许字母、数字和下划线,或者干脆把 `$_POST['info']` 限制到已定义的安全
页: [1]
查看完整版本: 新年礼物:Phpcms V9 短消息回复SQL注入