Exploring the New World : Remote Exploitation of SQLite and Curl
简述
这是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月修复。
下载地址:
- 历史版本:https://www.sqlite.org/src/timeline?t=release
- 旧版本 3.25.2:https://www.sqlite.org/src/info/fb90e7189ae6d62e
基础知识
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函数(如下图所示):
- 通过nodeReaderNext可以控制reader中的数据,aDoclist、nDoclist。(其实需要修改 shadow table中的内容)
- reader可控,fts3TruncateNode函数中的check可以bypass
- 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的过程如下:
- 首先攻击者开发CAST APP,发布时,需要指定CAST RECIEVER URL,这个URL可以是一个恶意的URL,只要是HTTPS就行,google没有check。
- 攻击
- 攻击受害者的手机等设备:让受害者通过chrome/或者时移动设备访问CAST_SEND_URL,访问了之后,就会触发。
- 或直接攻击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时,堆上会分配这个结构体。
整体的利用思路:
- 通过堆溢出,修改simple_tokenizer(分配在堆上)中的pModule
- pModule指向fake的struct,修改其中的callback
- 如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(如下图):
- Curl --ntlm http: //aaa:[email protected]:8080
- git clone http://aaa:[email protected]:8080/1.git (git支持NTLM协议,基于curl)
- 基于libcurl实现的各种软件,比如php
其实分析到这里会发现利用条件很苛刻:
- 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的漏洞造成的危害大。
参考:
- Sqlite:https://blade.tencent.com/magellan/index.html
- Curl:https://security.tencent.com/index.php/blog/msg/129
- Black Hat USA 2019 paper & PPT also.