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.

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.

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.

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

Vulnerable file: ppp-2.4.4_008_get_acname_sessionid.patch

  1. A 256 byte stack buffer cmd is allocated to build the shell command that stores the extracted acname for the firmwares environment.
  2. data contains the acname of the attacker controlled PADO packet
  3. sysevent set wan_pppoe_acname and is concatenated and stored in the 256 byte buffer.
  4. 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)
  5. 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.

Step 2: run pppoe-discovery # shell injection

Step 3: poc.py – shows details on the received packet as well as the forged packet with the command injection

Buffer Overwrite
Step 1: run poc.py with an acname of ‘A’*1420 see poc.py::ex.start()

Step 2: run pppoe-discovery

The stack is looking sane so far, lets step over the sprintf:

Because we changed the stack, we overwrite the return ptrs.

Step 3: run poc.py output

PoC.py

https://blogs.securiteam.com/index.php/feed