PlayStation · Report #1350653
Remote kernel heap overflow
Summary
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:
- Send a PADI packet.
- Expect to receive a PADO packet.
- Send a PADR packet.
- 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:
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 sizeMCLBYTES=2048. - It returns that mbuf cluster.
- If the length is larger than
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
- The PS sends a PADI.
- The attacker sends a PADO, with a
ACCOOKIEtag whose size is 1400 bytes. - The PS sends a PADR. This one is fine, there is no overflow here.
- The PS waits for a PADS packet.
- The PS times out, and resends a PADI.
- The attacker sends a PADO, with a
RELAYSIDtag whose size is 1400 bytes. - 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 -Wallsudo ifconfig eth0 mtu 8000sudo ./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.
How it was found
The write-up for this report has not been downloaded yet, or the program disclosed it without one. Read it on HackerOne.