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.
In short, the PlayStation (PS) will:
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()
:
pppoe_get_mbuf()
.pppoe_get_mbuf()
:
MHLEN
, it allocates an mbuf cluster, of size MCLBYTES
=2048.pppoe_send_padr()
:
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.
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.
ACCOOKIE
tag whose size is 1400 bytes.RELAYSID
tag whose size is 1400 bytes.Settings
-> Network
-> Set Up Internet Connection
-> Use a LAN Cable
-> Custom
PPPoE
Next
Automatic
1500
Do Not Use
cc -o poc poc.c -Wall
sudo ifconfig eth0 mtu 8000
sudo ./poc eth0
Test Internet Connection
. This will initiate the PPPoE connection.To see what happens:
Possible RCE. I did my tests only on a friend’s PS4, but I suspect that the PS5 is affected as well.