This one is tricky, and there are a number of vectors; mdimport will
automatically attempt to parse and index PDFs, for instance.
-landonf
Steven
Read the advisory carefully. The next step after memory corruption is
often execution of arbitrary code.
-Matt
It also seems mdimport runs in the current user's context.
No need to worry about Acrobat Reader, since the issue has already
been fixed in version 8. That, and I venture to say that most mac
users don't use Adobe Acrobat reader to read PDFs. It's just too dang
slow and not fat.
I don't think this one is exploitable (even in theory) in the
CGPDFReaderGetPageDictionary() case. One method is to put some kinda
of static var in there that counts the number of times
CGPDFDictionaryGetCount() is called with the same object and the same
key (type). If you then return 0 from is_page_tree_node(), then the
PDF reader will correctly log: "Some pages of this PDF are corrupt
and will be ignored." Then all is well with the world.
--
Sincerely,
Rosyna Keller
Technical Support/Carbon troll/Always needs a hug
Unsanity: Unsane Tools for Insanely Great People
It's either this, or imagining Phil Schiller in a thong.
The advisory seems to only state that Linux implementations crash.
--
> So far, it seems like it is just an infinite loop of
> CGPDFReaderGetPageDictionary(). mdimport automatically kills itself
> after spending too much time on it. Safari just sits there eating
> CPU. For the latter it's just a classic denial of service attack.
>
> It also seems mdimport runs in the current user's context.
>
> No need to worry about Acrobat Reader, since the issue has already
> been fixed in version 8. That, and I venture to say that most mac
> users don't use Adobe Acrobat reader to read PDFs. It's just too
> dang slow and not fat.
>
> I don't think this one is exploitable (even in theory) in the
> CGPDFReaderGetPageDictionary() case. One method is to put some
> kinda of static var in there that counts the number of times
> CGPDFDictionaryGetCount() is called with the same object and the
> same key (type). If you then return 0 from is_page_tree_node(),
> then the PDF reader will correctly log: "Some pages of this PDF are
> corrupt and will be ignored." Then all is well with the world.
In this particular case, the page node is self-referential -- from my
reproduction:
7 0 obj
<< /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 7 0 R ] >>
endobj
I've briefly played around with other potential error conditions, and
haven't been able to trigger any other bugs in CG's PDF handler --
not that my search was exhaustive.
-landonf
On Jan 7, 2:17 am, Matt Beaumont <m...@cs.ucla.edu> wrote:
> On Sat, Jan 06, 2007 at 17:10:18 -0800, missileboat wrote:
> > Ok, so, aside from having to Force Quit apps affected by a malicious
> > PDF, what else will this cause?Read the advisory carefully. The next step after memory corruption is
> often execution of arbitrary code.
>
> -Matt
not often, rarely.
this is not a MOAB, this is a MOB.
there are thousands of bugs like this.
the next one will be:
when i modify the code of application X it crashes !
> In this particular case, the page node is self-referential -- from
> my reproduction:
> 7 0 obj
> << /Type /Pages /MediaBox [0 0 612 792] /Count 1 /Kids [ 7 0 R ] >>
> endobj
Attached is a patch against trunk that implements PDF loop detection.
I kept banging on this one late into the night just because the Proof-
of-Concept DoS is such a pain in the neck -- *everything* renders
PDFs, from Safari to Mail.app.
The bug itself is in the CGPDFReaderGetPageDictionary() function --
it doesn't implement any loop detection, such that a self-referential
PDF page node object can refer back to itself infinitely.
The fix works by maintaining a per-thread key for the length of the
CGPDFReaderGetPageDictionary() call. A counter is assigned to the key
upon entry to CGPDFReaderGetPageDictionary(), and the key is cleared
upon exit from CGPDFReaderGetPageDictionary().
pdf_xref_resolve() is called within the loop, and I use our
guard_pdf_xref_resolve() to acquire a reference to the pthread key
and increment the counter. When the counter hits MAX_LOOP (500000),
guard_pdf_xref_resolve() returns NULL, which the caller
(CGPDFReaderGetPageDictionary ) then handles correctly, breaking out
of the loop.
I'd appreciate a code review, and more sets of eyes on
CGPDFReaderGetPageDictionary and pdf_xref_resolve, to make sure I
didn't bungle anything. You can find my proof-of-concept PDF here:
http://landonf.bikemonkey.org/static/moab-tests/autopdf.html
Thanks,
landonf
> pdf_xref_resolve() is called within the loop, and I use our
> guard_pdf_xref_resolve() to acquire a reference to the pthread key
> and increment the counter. When the counter hits MAX_LOOP (500000),
> guard_pdf_xref_resolve() returns NULL, which the caller
> (CGPDFReaderGetPageDictionary ) then handles correctly, breaking
> out of the loop.
I should also note that the guard_pdf_xref_resolve() function skips
all loop detection if the pthread key is not set (ie, it is called
outside of CGPDFReaderGetPageDictionary())
-landonf