Loading HuntDB...

Remote kernel heap overflow

High
P
PlayStation
Submitted None

Team Summary

Official summary from PlayStation

# Summary The PlayStation has a kernel PPPoE driver, that originates from NetBSD. This driver has a kernel heap overflow vulnerability, that an attacker can remotely trigger over the LAN, with the ability to control both the contents that are overflown and their sizes. # Technical Details ## PPPoE Protocol In short, the PlayStation (PS) will: 1. Send a PADI packet. 2. Expect to receive a PADO packet. 3. Send a PADR packet. 4. Expect to receive a PADS packet. ## The Vulnerability I determined that the PS' PPPoE driver originates from NetBSD. In that PPPoE driver, there is a vulnerability in the way PADR packets are allocated: ```c static int pppoe_send_padr(struct pppoe_softc *sc) { [...] /* Compute packet length. */ len = sizeof(struct pppoetag); if (sc->sc_service_name != NULL) { l1 = strlen(sc->sc_service_name); len += l1; } if (sc->sc_ac_cookie_len > 0) { len += sizeof(struct pppoetag) + sc->sc_ac_cookie_len; } if (sc->sc_relay_sid_len > 0) { len += sizeof(struct pppoetag) + sc->sc_relay_sid_len; } len += sizeof(struct pppoetag) + sizeof(sc->sc_id); if (sc->sc_sppp.pp_if.if_mtu > PPPOE_MAXMTU) { len += sizeof(struct pppoetag) + 2; } /* Allocate packet. */ m0 = pppoe_get_mbuf(len + PPPOE_HEADERLEN); if (m0 == NULL) return ENOBUFS; /* Fill in packet. */ [...] } static struct mbuf * pppoe_get_mbuf(size_t len) { struct mbuf *m; MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return NULL; if (len + sizeof(struct ether_header) > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); return NULL; } } m->m_data += sizeof(struct ether_header); m->m_len = len; m->m_pkthdr.len = len; m_reset_rcvif(m); return m; } ``` The flow is: - `pppoe_send_padr()`: - It wants to send a PADR packet. - It computes the packet length, and calls `pppoe_get_mbuf()`. - `pppoe_get_mbuf()`: - If the length is larger than `MHLEN`, it allocates an mbuf cluster, of size `MCLBYTES`=2048. - It returns that mbuf cluster. - `pppoe_send_padr()`: - It fills in the mbuf cluster. The vulnerability here is that the packet length could actually be bigger than `MCLBYTES`, in which case the filling of the packet will overflow the mbuf cluster. ## Constraints To have a length that is larger than `MCLBYTES`, the `sc_ac_cookie_len` and `sc_relay_sid_len` values need to be large enough. Both of these values are actually extracted from PADO packets that the PS previously received: they are the lengths of the `ACCOOKIE` and `RELAYSID` tags that were embedded in the PADO packets. The attacker can control these lengths. There is a constraint on the MTU: given that the PS' maximum MTU is 1500, the attacker cannot directly send just one PADO packet with sizes larger than `MCLBYTES`. To work around that constraint, the attacker just has to send two PADO packets, one with a big `ACCOOKIE` tag, and another with a big `RELAYSID` tag. After the second packet, the PS will send a PADR packet combining both big tags, which will overflow the mbuf cluster with the contents of the second tag. ## Attack Scenario 1. The PS sends a PADI. 2. The attacker sends a PADO, with a `ACCOOKIE` tag whose size is 1400 bytes. 3. The PS sends a PADR. This one is fine, there is no overflow here. 4. The PS waits for a PADS packet. 5. The PS times out, and resends a PADI. 6. The attacker sends a PADO, with a `RELAYSID` tag whose size is 1400 bytes. 7. The PS Sends a PADR. The overflow occurs here: the PS tries to embed the two tags (1400x2=2800 bytes) into a 2048-byte mbuf cluster. ## Setup / PoC / Discussion - Enable PPPoE on the PS: - `Settings` -> `Network` -> `Set Up Internet Connection` -> `Use a LAN Cable` -> `Custom` - IP Address Settings: `PPPoE` - Enter whatever in the two User/Password fields, click `Next` - DNS Settings: `Automatic` - MTU Settings: set `1500` - Proxy Server: `Do Not Use` - Connect a Linux laptop to the PS with an Ethernet cable. - On the Linux laptop: - `cc -o poc poc.c -Wall` - `sudo ifconfig eth0 mtu 8000` - `sudo ./poc eth0` - On the PS: click `Test Internet Connection`. This will initiate the PPPoE connection. To see what happens: - Open WireShark on the Linux laptop, and look at the packets that are being exchanged with the PS. You can see that the PS sends 2844-byte PADR packets. - Actual exploitation/introspection will require a debugger, which I do not have. :'( - ███████ ## Impact Possible RCE. I did my tests only on a friend's PS4, but I suspect that the PS5 is affected as well.

Reported by m00nbsd

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Submitted

Weakness

Heap Overflow