OpenBSD ownage party !
Hello world,
Since erratas and patches for the vulnerability have been released, I can publish my exploit with some explanations.
Explanations are quite light, I have no time. Maybe xorl will do a better analysis and in a better english. :-)
* Vulnerability
The vulnerability is very easy to understand. OpenBSD developpers have just forgotten to allocate a new mbuf in a getsockopt() kernel case. Indeed, when kernel handles getsockopt() call, it creates a new mbuf which is filled with the information requested and returned back to userland. For instance, here is the code case handling a getsockopt() with IP_PORTRANGE level:
*mp = NULL;
(...)
case IP_PORTRANGE:
*mp = m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = sizeof(int);
if (inp->inp_flags & INP_HIGHPORT)
optval = IP_PORTRANGE_HIGH;
else if (inp->inp_flags & INP_LOWPORT)
optval = IP_PORTRANGE_LOW;
else
optval = 0;
*mtod(m, int *) = optval;
break;
As you can see on line 2, there is a call to m_get() to request a new mbuf.
Problem is located in levels IP_AUTH_LEVEL, IP_ESP_TRANS_LEVEL, IP_ESP_NETWORK_LEVEL, IP_IPCOMP_LEVEL where developpers use the mbuf m directly whereas it has not been allocated, it equals to NULL.
case IP_AUTH_LEVEL:
case IP_ESP_TRANS_LEVEL:
case IP_ESP_NETWORK_LEVEL:
case IP_IPCOMP_LEVEL:
(...)
m->m_len = sizeof(int); [1]
switch (optname) {
case IP_AUTH_LEVEL:
optval = inp->inp_seclevel[SL_AUTH];
break;
(...)
*mtod(m, int *) = optval; [2]
(...)
At [1] kernel try to write sizeof(int) at NULL->m_len. If page at address NULL is not mapped, a kernel panic occurs.
This vulnerability affects OpenBSD version 3.9 (I've not checked previous versions) through 4.6, the lastest.
* The sploit
At first, in order to exploit this vulnerability to gain root priv, we have to be able to map page at adresse NULL. Since OpenBSD 4.4, this has been disabled for all architectures. I haven't found any way of bypassing this protection. Thus, this exploit works only on versions prior to OpenBSD 4.4.
In the vulnerable code showed above, we can see that the instruction at [2] is very interesting because it will allow us to write optval where we want in memory. Indeed, mtod() is just a C macro which returns (int*)m->data.
So let's root it ?
To exploit this, we just have to map (rw access) at address NULL a fake mbuf with an evil data field. We just have one consideration to take into account, default value for optval in these cases is always 0x00000001 and only root can modify it with a setsockopt() call. So, we can write a 0x00000001 where we want in memory. :-)
Are you ready to rumble the kernel ?
Like perl, there is more than one way to do it. At first I was thinking of erasing creds in the proc structure but it is no so simple and I chose to simply override an entry in the syscall table.
Yes, address of sysent in OpenBSD is static. We just have to override one of the entries (SYS_fpathconf for example) with an 0x00000001 value by mapping a fake mbuf at NULL with m->data = addr of sysent[SYS_fpathconf]. Then we call our evil getsockopt(). When sysent entry is overriden, we remap at NULL a NOP+shellcode which updates the creds of our current process and then call fpathconf() to exec our shellcode and rulez !
Please, let me know if you have other tricks.
For more information, I let you see source of the exploit, for educationnal purpose only of course.
$ id
uid=1000(clem1) gid=1000(clem1) groups=1000(clem1), 0(wheel)
$ ./openbaize
\o/ OpenBSD IP_FUCKING_LEVEL getsockopt() local root
\o/ Found and badcoded by clem1
\o/ Trying to own this 4.0 OpenBSD OS... 0h0h0h
\o/ Patching sysent (0xd0715fc4) for syscall number 192 with 0x1... h0h0h0
\o/ Mapping shellcode at 0x1... calling our new fake evil syscall number 192
\o/ Hoooooooorray r00t.
# id
uid=0(root) gid=1000(clem1) groups=1000(clem1), 0(wheel)
* FAQ:
Why two different shellcodes ?
Just because proc and p_cred structures have changed (new level of dereference, new offset).
Since erratas and patches for the vulnerability have been released, I can publish my exploit with some explanations.
Explanations are quite light, I have no time. Maybe xorl will do a better analysis and in a better english. :-)
* Vulnerability
The vulnerability is very easy to understand. OpenBSD developpers have just forgotten to allocate a new mbuf in a getsockopt() kernel case. Indeed, when kernel handles getsockopt() call, it creates a new mbuf which is filled with the information requested and returned back to userland. For instance, here is the code case handling a getsockopt() with IP_PORTRANGE level:
*mp = NULL;
(...)
case IP_PORTRANGE:
*mp = m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = sizeof(int);
if (inp->inp_flags & INP_HIGHPORT)
optval = IP_PORTRANGE_HIGH;
else if (inp->inp_flags & INP_LOWPORT)
optval = IP_PORTRANGE_LOW;
else
optval = 0;
*mtod(m, int *) = optval;
break;
As you can see on line 2, there is a call to m_get() to request a new mbuf.
Problem is located in levels IP_AUTH_LEVEL, IP_ESP_TRANS_LEVEL, IP_ESP_NETWORK_LEVEL, IP_IPCOMP_LEVEL where developpers use the mbuf m directly whereas it has not been allocated, it equals to NULL.
case IP_AUTH_LEVEL:
case IP_ESP_TRANS_LEVEL:
case IP_ESP_NETWORK_LEVEL:
case IP_IPCOMP_LEVEL:
(...)
m->m_len = sizeof(int); [1]
switch (optname) {
case IP_AUTH_LEVEL:
optval = inp->inp_seclevel[SL_AUTH];
break;
(...)
*mtod(m, int *) = optval; [2]
(...)
At [1] kernel try to write sizeof(int) at NULL->m_len. If page at address NULL is not mapped, a kernel panic occurs.
This vulnerability affects OpenBSD version 3.9 (I've not checked previous versions) through 4.6, the lastest.
* The sploit
At first, in order to exploit this vulnerability to gain root priv, we have to be able to map page at adresse NULL. Since OpenBSD 4.4, this has been disabled for all architectures. I haven't found any way of bypassing this protection. Thus, this exploit works only on versions prior to OpenBSD 4.4.
In the vulnerable code showed above, we can see that the instruction at [2] is very interesting because it will allow us to write optval where we want in memory. Indeed, mtod() is just a C macro which returns (int*)m->data.
So let's root it ?
To exploit this, we just have to map (rw access) at address NULL a fake mbuf with an evil data field. We just have one consideration to take into account, default value for optval in these cases is always 0x00000001 and only root can modify it with a setsockopt() call. So, we can write a 0x00000001 where we want in memory. :-)
Are you ready to rumble the kernel ?
Like perl, there is more than one way to do it. At first I was thinking of erasing creds in the proc structure but it is no so simple and I chose to simply override an entry in the syscall table.
Yes, address of sysent in OpenBSD is static. We just have to override one of the entries (SYS_fpathconf for example) with an 0x00000001 value by mapping a fake mbuf at NULL with m->data = addr of sysent[SYS_fpathconf]. Then we call our evil getsockopt(). When sysent entry is overriden, we remap at NULL a NOP+shellcode which updates the creds of our current process and then call fpathconf() to exec our shellcode and rulez !
Please, let me know if you have other tricks.
For more information, I let you see source of the exploit, for educationnal purpose only of course.
$ id
uid=1000(clem1) gid=1000(clem1) groups=1000(clem1), 0(wheel)
$ ./openbaize
\o/ OpenBSD IP_FUCKING_LEVEL getsockopt() local root
\o/ Found and badcoded by clem1
\o/ Trying to own this 4.0 OpenBSD OS... 0h0h0h
\o/ Patching sysent (0xd0715fc4) for syscall number 192 with 0x1... h0h0h0
\o/ Mapping shellcode at 0x1... calling our new fake evil syscall number 192
\o/ Hoooooooorray r00t.
# id
uid=0(root) gid=1000(clem1) groups=1000(clem1), 0(wheel)
* FAQ:
Why two different shellcodes ?
Just because proc and p_cred structures have changed (new level of dereference, new offset).
8 Comments:
"remote root", w0t? :D
oups s/remote/local/g :)
Congrats! Well done :)
Another neat way is to overwrite some IDT entry in order to control the exception handler of that interrupt.
In addition, you could dynamically retrieve the addresses of the syscalls you're overwriting through the syscall table retrieved using SIDT or something else. This way you won't have to care about any kernel memory randomization crap.
Finally, bypassing that VM mapping is feasible. Just check out the Linux techniques prior the overhyped 'pulseaudio' shit.
have fun.
compile error!!
how to compile ??
ThankS
Just need a little correction to the last changes.
sizeof(ob->sc) == 4
Nice work! ;)
This comment has been removed by a blog administrator.
This comment has been removed by a blog administrator.
[url=http://www.realcazinoz.com]Online casinos[/url], also known as efficient casinos or Internet casinos, are online versions of commonplace ("buddy and mortar") casinos. Online casinos approve gamblers to hand-picked up and wager on casino games with the save the Internet.
Online casinos typically enter upon aside on the reciprocate odds and payback percentages that are comparable to land-based casinos. Some online casinos home in on higher payback percentages in the design of travail automobile games, and some prevail upon ended known payout speck audits on their websites. Assuming that the online casino is using an correctly programmed indefinitely innumerable generator, catalogue games like blackjack suffer with an established congress edge. The payout piece after these games are established erstwhile the rules of the game.
Heterogeneous online casinos limit not at people's home or produce their software from companies like Microgaming, Realtime Gaming, Playtech, Intercontinental Ploy Technology and CryptoLogic Inc.
Post a Comment
<< Home