0x05 清楚地知道系统参数过滤情况
0x05.1 原生 GET,POST,REQUEST
使用原生GET,POST,REQUEST变量是完全不过滤的
测试方法:
最简单的就是这样了
顺便找处系统中可外部访问的地方
如图:

根据结果就可以确定当使用了原生GET,POST,REQUEST变量带入数据库之类,是有可能产生注入,存储型xss之类的
0x05.2 系统外部变量获取函数 get(),post(),request()
路径:PbootCMS-V1.2.1\core\function\helper.php
函数_1:function get(
函数_2:function post(
函数_3:function request(
这3个函数 get(), post(), request()
函数:filter(
最后都会调用 filter函数
这个函数没有用所以直接看 filter 里面调用的方法 escape_string函数进行最终过滤
因为filter无用的内容太多所以我们忽略掉直接看escape_string 函数
路径:PbootCMS-V1.2.1\core\function\handle.php
函数:function escape_string(
// 获取转义数据,支持字符串、数组、对象function escape_string($string, $dropStr = true){if (! $string)return $string;if (is_array($string)) { // 数组处理foreach ($string as $key => $value) {$string[$key] = escape_string($value);}} elseif (is_object($string)) { // 对象处理foreach ($string as $key => $value) {$string->$key = escape_string($value);}} else { // 字符串处理if ($dropStr) {$string = preg_replace('/(0x7e)|(0x27)|(0x22)|(updatexml)|(extractvalue)|(name_const)|(concat)/i', '', $string);}$string = htmlspecialchars(trim($string), ENT_QUOTES, 'UTF-8');$string = addslashes($string);}return $string;}
可以看得到所有传过来的内容都会先过一个正则匹配过滤
会将 0x7e,0x27,0x22,updatexml,extractvalue,name_const,concat 将其替换为’’
然后在进行
htmlspecialchars 函数的html实体编码
addslashes 函数转义。
注意点:1. 过滤只针对 value2. key 完全无不过滤3. 那个正则绕过很简单只需要 updatupdatexmlexml 经过过滤以后就可以转为 updatexml
那么看到这里对于系统的初步情况其实就已经很明确了
0x06 查看系统DB类,了解数据库底层运行方式
在挖sql注入的时候,我最喜欢的就是先看这个系统的底层了。
会对挖洞有很大的帮助,看的时候并不需要全看懂,只需要对一些关键的地方看个大概即可
路径:PbootCMS-V1.2.1\core\basic\Model.php
看了一下以后发现,这里没什么好讲的,因为里面全是字符串拼接。
例如: where方法
/*** 连贯操作:设置查询条件** @param mixed $where* 设置条件,可以为字符串、数组,* 字符串模式:如"id<1","name like %1",* 数组模式:array('username'=>'xie',"realname like '%谢%'")* @param string $inConnect* 调用本方法时$where参数数组内部的条件默认使用AND连接* @param string $outConnect* 调用本方法时与前面条件使用AND连接* @param boolean $fuzzy* 条件是否为模糊匹配,即in匹配* @return \core\basic\Model*/final public function where($where, $inConnect = 'AND', $outConnect = 'AND', $fuzzy = false){if (! $where) {return $this;}if (isset($this->sql['where']) && $this->sql['where']) {$this->sql['where'] .= ' ' . $outConnect . '(';} else {$this->sql['where'] = 'WHERE(';}if (is_array($where)) {$where_string = '';$flag = false;foreach ($where as $key => $value) {if ($flag) { // 条件之间内部AND连接$where_string .= ' ' . $inConnect . ' ';} else {$flag = true;}if (! is_int($key)) {if ($fuzzy) {$where_string .= $key . " like '%" . $value . "%' ";} else {$where_string .= $key . "='" . $value . "' ";}} else {$where_string .= $value;}}$this->sql['where'] .= $where_string . ')';} else {$this->sql['where'] .= $where . ')';}return $this;}
初步结论:整个db 类的底层都是类似的字符串拼接,所以(≧∇≦)ノ 只要能够带入 '或是\ 那么就可以确定是有注入的了
注意点:在查看的时候发现了 insert 方法的注释,也是需要注意的,这里我把代码贴一下
/*** 数据插入模型** @param array $data* 可以为一维或二维数组,* 一维数组:array('username'=>"xsh",'sex'=>'男'),* 二维数组:array(* array('username'=>"xsh",'sex'=>'男'),* array('username'=>"gmx",'sex'=>'女')* )* @param boolean $batch* 是否启用批量一次插入功能,默认true* @return boolean|boolean|array*/final public function insert(array $data = array(), $batch = true){// 未传递数据时,使用data函数插入数据if (! $data && isset($this->sql['data'])) {return $this->insert($this->sql['data']);}if (is_array($data)) {if (! $data)return;if (count($data) == count($data, 1)) { // 单条数据$keys = '';$values = '';foreach ($data as $key => $value) {if (! is_numeric($key)) {$keys .= "`" . $key . "`,";$values .= "'" . $value . "',";}}if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {$keys .= "`" . $this->createTimeField . "`,`" . $this->updateTimeField . "`,";if ($this->intTimeFormat) {$values .= "'" . time() . "','" . time() . "',";} else {$values .= "'" . date('Y-m-d H:i:s') . "','" . date('Y-m-d H:i:s') . "',";}}if ($keys) { // 如果插入数据关联字段,则字段以关联数据为准,否则以设置字段为准$this->sql['field'] = '(' . substr($keys, 0, - 1) . ')';} elseif (isset($this->sql['field']) && $this->sql['field']) {$this->sql['field'] = "({$this->sql['field']})";}$this->sql['value'] = "(" . substr($values, 0, - 1) . ")";$sql = $this->buildSql($this->insertSql);} else { // 多条数据if ($batch) { // 批量一次性插入$key_string = '';$value_string = '';$flag = false;foreach ($data as $keys => $value) {if (! $flag) {$value_string .= ' SELECT ';} else {$value_string .= ' UNION All SELECT ';}foreach ($value as $key2 => $value2) {// 字段获取只执行一次if (! $flag && ! is_numeric($key2)) {$key_string .= "`" . $key2 . "`,";}$value_string .= "'" . $value2 . "',";}$flag = true;if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {if ($this->intTimeFormat) {$value_string .= "'" . time() . "','" . time() . "',";} else {$value_string .= "'" . date('Y-m-d H:i:s') . "','" . date('Y-m-d H:i:s') . "',";}}$value_string = substr($value_string, 0, - 1);}if ($this->autoTimestamp || (isset($this->sql['auto_time']) && $this->sql['auto_time'] == true)) {$key_string .= "`" . $this->createTimeField . "`,`" . $this->updateTimeField . "`,";}if ($key_string) { // 如果插入数据关联字段,则字段以关联数据为准,否则以设置字段为准$this->sql['field'] = '(' . substr($key_string, 0, - 1) . ')';} elseif (isset($this->sql['field']) && $this->sql['field']) {$this->sql['field'] = "({$this->sql['field']})";}$this->sql['value'] = $value_string;$sql = $this->buildSql($this->insertMultSql);// 判断SQL语句是否超过数据库设置if (get_db_type() == 'mysql') {$max_allowed_packet = $this->getDb()->one('SELECT @@global.max_allowed_packet', 2);} else {$max_allowed_packet = 1 * 1024 * 1024; // 其他类型数据库按照1M限制}if (strlen($sql) > $max_allowed_packet) { // 如果要插入的数据过大,则转换为一条条插入return $this->insert($data, false);}} else { // 批量一条条插入foreach ($data as $keys => $value) {$result = $this->insert($value);}return $result;}}} elseif ($this->sql['from']) {if (isset($this->sql['field']) && $this->sql['field']) { // 表指定字段复制$this->sql['field'] = "({$this->sql['field']})";}$sql = $this->buildSql($this->insertFromSql);} else {return;}return $this->getDb()->amd($sql);}
简单的说,就是insert 方法支持二维数组,当使用二维数组时表示批量插入。
所以如果我们可以插入二维数组并且可以控制key那么我们就可以注入了。
下图为触发点查看:
0x07 系统情况初步集合
经过0x05.1与0x05.2 还有0x06组合下来我们其实可以确定了一些基本漏洞了
5.1 反应给我的情况首先是xss漏洞存储型xss如果是使用了 5.1 的外部变量并且入库的时候没有转义的话,那么就会产生xss反射xss反不动 只要 GET 请求中出现了 A-Z a-z 0-9 之外的数,就会直接报错然后是sql注入漏洞如果是使用了 5.1 的外部变量并且入库的时候没有转义的话,那么就会产生sql注入
5.2 反应给我的情况首先是xss漏洞存储型xss如果是使用了 5.2 的外部变量入库的,想找xss 那么就要看使用了 htmlspecialchars_decode 函数的地方,否则的话就只能查看类似这种点 <img src=# {{variate}}> variate 可控的情况反射xss射不动 只要 GET 请求中出现了 A-Z a-z 0-9 之外的数,就会直接报错然后是sql注入漏洞key 没有过滤所以如果我能够控制 key 进入sql的话,那么就基本上百分之90有sql注入了
6.0 给我的情况底层全是字符串拼接,只要能够引入 ' 或是 \ 就可以造成注入5.1 只要我们可以控制就有注入5.2 因为所有的 value 都会进行 htmlspecialchars 函数的html实体编码 addslashes 函数转义所以利用value 注入不现实,那么我们找注入的关键点就是查看key了
嗯,可以看到这就很明了了,我的审计收集工作也正式算是做完了。
接下来就是正式审计了。
不过其实到这一步,基本上在看两眼搜索一下打打 debug 就可以确定漏洞了。
