简述

这是Tencent Blade Team在Black Hat USA 2019上的其中一个议题,讲述了他们发现的Sqlite FTS3中的3个漏洞,并利用其中一个结合CAST协议攻破Google Home(Chrome浏览器sandbox内RCE)。也介绍了他们在curl NTLM认证协议中发现的两个整数溢出漏洞,并在实际环境中做了演示(git、php等)。

客户端的漏洞触发起来没有服务端那么容易,但是利用和挖掘的思路还是值得学习的。
本文做一个简单的记录,更多的细节请参考PPT和Paper,如有错误还请评论区指正。

Magellan(Sqlite3 vulns)

Malgellan是三个漏洞的集合:CVE-2018-20346 CVE-2018-20505 CVE-2018-20506,均于2018年11月修复。

下载地址:

基础知识

FTS3

简而言之,FTS3在Sqlite中的vtable模块,是用来做全文搜索的。参考官方文档中的说明:

FTS3 and FTS4 are SQLite virtual table modules that allows users to perform full-text searches on a set of documents. [... ]Users input a term, or series of terms, perhaps connected by a binary operator or grouped together into a phrase, and the full-text query system finds the set of documents that best matches those terms considering the operators and groupings the user has specified. [...]
REF https://www.sqlite.org/fts3.html

Shadow Tables

在创建vtable(fts3)时,会创建2-5个table,这些table是用来存储数据为了加速搜索的。

  • for each virtual table,2-5 tables(not virtual)are created to store underlying data
  • "%_content", "%_segdir", "%_segments", "%_stat", and "%_docsize" (% virtual table name)(%_stat %_docsize for FTS4)

例如执行sql语句: create virtual table x using fts3( a int);时,发现3个table被创建。(注意这3个table不是vtable)

看一下官方文档中对这些table的描述:

shadow tables中存储了很多结构化的数据,重点关注一下上图中的BLOB(B-Tree这个数据结构多用于文件系统、数据库中),其中存储的数据很复杂。因此作者思考在序列化/反序列化时可能会存在问题。

于是作者重点关注从shadow table中解析、反序列化数据的函数、操作BTREE节点的函数、调用危险API的函数:

发现了如下三个漏洞,其中利用CVE-2018-20346来攻破Google Home。接下来看一下这个漏洞。

CVE-2018-20346

Sqlite中通过INSET 语句触发merge操作时,底层回调用fts3AppendToNode函数。经过分析后发现memcpy的参数可控,分析见下文。

fts3TruncateNode函数调用链:

fts3TruncateNode
    nodeReaderNext
    fts3AppendToNode
        memcpy(&pNode->a[pNode->n], aDoclist, nDoclist); (overflow/info leak)

漏洞的关键在于fts3TruncateNode函数(如下图所示):

  1. 通过nodeReaderNext可以控制reader中的数据,aDoclist、nDoclist。(其实需要修改 shadow table中的内容)
  2. reader可控,fts3TruncateNode函数中的check可以bypass
  3. assert在release版本中是失效的。

因此,fts3AppendToNode函数中的memcpy,参数aDocList nDoclist可控。可造成:堆溢出、OOB Read。

具体在利用时通过update _segdir这个表来控制memcpy的参数(这张图摘自后面里用的时候):

CVE-2018-20506、CVE-2018-20505 也是类似的思路。其中CVE-2018-20506网上的有利用视频(非Blade Team写的),感兴趣可以看一下。地址:https://blog.exodusintel.com/2019/01/22/exploiting-the-magellan-bug-on-64-bit-chrome-desktop/

如何攻破Google Home?

Google Home是Goole的智能音箱。每次启动时,根据APPID pull 不同的firmware(Google Home, Chrome Cast and so on)。Blade Team根据固件分析发现Google Home用的是Chrome OS。因此“如何攻破Google Home?”这个问题就转变成了:如何让Google Home去访问一个攻击者的URL?

CAST Protocol

CAST协议,用来和Google的智能设备通信的协议。在CAST协议中涉及到Sender和Receiver。Sender根据CAST协议和Receiver通信,Receiver可以获取CAST APP或者访问Google官网等等。通信过程如下:

CAST Protocol Attack Surface

CAST协议默认监听在8009端口,通过CAST 协议发送CAST APPID,可以让Google Home去启动CAST APP。利用CAST协议让Google Home访问URL的过程如下:

  1. 首先攻击者开发CAST APP,发布时,需要指定CAST RECIEVER URL,这个URL可以是一个恶意的URL,只要是HTTPS就行,google没有check。
  2. 攻击
    1. 攻击受害者的手机等设备:让受害者通过chrome/或者时移动设备访问CAST_SEND_URL,访问了之后,就会触发。
    2. 或直接攻击Google Home:通过构造castv2 protocol,在局域网内直接发给8009 的Google Home,可以让Google Home去访问CAST RECEIVER URL。

漏洞利用

CVE-2018-20346既可以info leak也可以heap overflow。

前面提到,通过SQL:update x_segdir 来控制这memcpy的参数:

为了控制PC,还需要:

  • 信息泄漏bypass ASLR
  • 通过堆溢出,溢出相应的指针来劫持

漏洞利用1: bypass ASLR

这是在google chrome上针对info leak的尝试。通过修改%_segdir中root的值,之后用INSERT来触发漏洞。通过不断修改nDoclist的值,尝试info leak泄漏堆地址。
如下图所示泄漏了堆地址,bypass ASLR:

漏洞利用2: control PC

simple_tokenizer

控制PC的过程涉及到这个结构体:simple_tokenizer。create fts3 vtable时,堆上会分配这个结构体。

整体的利用思路:

  1. 通过堆溢出,修改simple_tokenizer(分配在堆上)中的pModule
  2. pModule指向fake的struct,修改其中的callback
  3. 如xOpen的callback(调用callback时arg1时在堆上,也可控)

注:xOpen的callback会在执行insert的操作时触发(来自paper)


(注意看代码会发现:pModule在内存中实际上是simple_tokenizer结构体中的一个成员,这张图可能会让人误解)

代码如下:

这个callback如何触发呢?很简单,执行SQL语句就行。比如执行了INSERT语句时,会触发xOpen callback。

因此,为了调用callback控制PC,需要找堆溢出之后,free内存之前,会执行SQL语句的地方。如下图所示找到了SQL_CHOMP_SSEGDIR这个位置,通过写SQL TRIGGER,可以让触发这条语句时,先执行INSERT SQL语句,即也就会执行callback xOpen。

如何堆溢出simple_tokenizer?

create multiple fts3 tables再drop这个操作,目的是是为了溢出simple_tokenizer结构体,具体的细节则需要调试了。按照作者的说法,堆溢出之后可以直接覆盖simple_tokenizer结构体。

漏洞利用3: payload如何放置?

Blade Team通过dump内存分析:如果payload size很大,在堆喷射后,payload的地址可以结合bypass ASLR时泄漏的地址来预测。

如下图所示,左边是堆喷射的payload,右边是溢出了simple_tokenizer的第一个成语成员,让其指向payload。payload中修改callback为stack pivot,在堆上做ROP就可以执行shellcode了。

最后attack的效果:

Dias (CURL NTLM协议相关漏洞)

Dias:

  • CVE-2018-16890 CVE-2019-3822。
  • 影响版本:curl 7.36.0~7.63.0。
  • 上报时间:2018年12月31日,修复时间2019年1月,二月发布release 7.64.0。

CURL的NTLM协议中的漏洞是怎么发现的呢?由于目标是RCE、因此重点关注大的函数、协议(NTLM)是其中之一。

这两个漏洞都存在于curl的NTLM协议认证过程中,NTLM的认证过程,分为6步(如下图所示)。

先简单介绍下漏洞类型和原因,具体见后文分析。

漏洞类型分别是:
- type2 NTLM 整数溢出导致堆溢出
- type3 NTLM 栈溢出
漏洞原因:
- unsigned int,unsigned short相加整数溢出导致bypass check,在memcpy中可以info leak(由target_info_len决定,16byte所以可以泄漏 64KB)。
- 有符号数 无符号数参与判断时,发生的溢出。
- 溢出后,根据不同的编译器溢出栈中的变量。
- 根据这些变量,进一步导致堆溢出。

CVE-2018-16890(NTLM Type-2 Message Information Leak)

在curl的ntlm_decode_type2_target函数中,红框的if分支中,target_info_offset和target_info_len都是无符号数(unsigned)。在memcpy之前,有一个if的check。check中如果offset+len > SIZE,那么就会失败。但是16byte的len和32byte的offset相加,可能溢出。例如0xffff+0xffff0001 = 0x1。0xffff0001肯定也>48。因此可以bypass check,后面memcpy时可以泄漏64KB数据。

注意,这个内存泄漏时curl的内存泄漏,即在服务器上远程获取客户端内存至多64KB的原始内存信息。

CVE-2019-3822 (NTLM Type-3 Message Stack Buffer Overflow)

漏洞发生在Curl_auth_create_ntlm_type3_message函数中。memcpy之前有一处check,注意符号:

  • size是 ssize_t类型,无符号数。
  • NTLM_BUFSIZE是 别的头文件中定义的,最大为1024。(测试了一下会当作有符号数)
  • ntresplen是无符号数。

因此,在有符号和无符号数参与的运算中,有符号数会被转换成有符号数。
那么如果ntresplen为1025,那么判断条件会变为:size<0xffffffff,即可进入memcpy,造成栈溢出(ntlmbuf位于栈上)。

补充一下 unsigned & signed 参与的运算效果:

发生栈溢出之后,在gcc编译后的代码中,可以溢出后面的变量。(注意,调试时可能需要关注与喜爱gcc变量重排)比如控制domoff,hsotlen。这两个变量后续都会被用到,导致堆溢出或者是信息泄漏。

domoff可控导致堆溢出,hsotlen可控导致栈溢出或信息泄漏:

利用场景

利用的本质:攻击的是使用NTLM协议的curl(客户端)。假设127.0.0.1(可当成是attacker的ip)被攻击者控制,下面的场景中客户端可能会被attack(如下图):

其实分析到这里会发现利用条件很苛刻:

  • vulnerable curl + NTLM认证
  • 且要和一个攻击者的server通信 或 流量被劫持

新闻上说的“破解apache+php”是如何做到的?其实本质上就是php中调用了libcurl,因此可以上传一个没有特征的webshell,利用其来信息泄漏。这样做可以在leak memory时不会被IDS检测到。

总结&收获

sqlite3的漏洞的本质是:user可以修改shadow tables来控制memcpy的参数。要触发首先需要可以执行sql语句创建FTS3 vtable。

curl漏洞的本质:

  • unsigned short和unsigned int相加导致整数溢出,导致memcpy参数可控。
  • signed 和unsigned 运算时会被转成unsigned,可能造成整数溢出bypass if的判断。

client的漏洞即使被披露,现实场景中还是会存在大量未修复的版本,但是相对没有server的漏洞造成的危害大。

参考: