在本漏洞Writeup中,作者利用Kindle的电子书邮件发送途径,通过研究电子书文档注入、电子书JPEG XR解析漏洞和Kindle提权漏洞,经综合利用,可成功以假冒邮件方式,向受害者Kindle邮箱发送恶意电子书文档,只要受害者点击其中的恶意链接,就能以root级别在受害者Kindle设备中执行任意代码。漏洞危害在于,可以此获取受害者Kindle设备中的credit card等个人信息,变卖受害者电子书并把所获钱款转到自己账户等。漏洞最终收获了亚马逊官方奖励的18K$。
前言说明
在早前,我从Realmode Labs博文发现Amazon Kindle发布了一个名为“发送至Kindle”(Send to Kindle)的功能,利用该功能用户可以直接将电子书文档以附件方式发送至自己Kindle中的图书内容库,当时我就对该功能的安全性有所思考,能不能利用其向其他用户发送恶意文档以此实现攻击或信息获取呢?
说干就干,经过一段时间的研究分析,我综合利用其存在的三个漏洞,可以实现对其他用户Kindle设备的root层远程代码执行攻击。攻击者只需知道受害者的Kindle邮箱即可,攻击之后可以获取受害者的密码凭据,能利用受害者绑定的credit card在Kindle商店购买东西,还能把受害者的电子书变卖并把卖后所得钱款转到自己的账户下。在Kindle商店的购买过程中,受害者只会收到Kindle发来的确认邮件,有安全意识的用户也许才会从确认邮件中发现不对劲。
漏洞介绍
在第一个漏洞中,攻击者可以向受害者Kindle设备发送捆绑了恶意程序的电子书文档;第二个漏洞中,受害者Kindle设备在解析恶意电子书文档时会触发任意代码执行;第三个漏洞中,攻击者可以提权为root级别完全控制受害者Kindle设备。目前,亚马逊已经针对该问题发布了软件更新包,用户在接入互联网后就会自动更新升级。以下是三个漏洞的综合利用流程:
电子书文档恶意注入
在“发送至Kindle”的功能中,Amazon会为每个Kindle生成一个特别的kindle.com后缀邮箱,用户可以将MOBI电子书文档以附件方式发送至该邮箱,之后,即可从Kindle设备中看到该电子书。
在此要说明的是,Amazon未做严格的身份验证,我用了在线邮件伪造服务https://emkei.cz/即能假冒一个正常用户,成功向受害者的kindle.com后缀邮箱发送电子书文档,之后,假冒发送的电子书文档还能以并以文档封面形式正常显示在受害者Kindle设备中,这里还可以用作钓鱼攻击。这里的邮箱格式是,有些用户是像gmail那样的正常邮箱地址,只是把[email protected] 换作 [email protected],而有些是无规律的,如name_<random_string>@kindle.com。
逆向Kindle Firmware固件
现在有了向任意Kindle设备发送电子书文档的方法,接下来就需要研究如何在受害者打开电子书文档时触发执行代码。为此,我在最新的Kindle firmware version 5.13.2环境下,逆向分析了Kindle电子书解析代码。我先用KindleTool提取了固件更新中的文件系统,并用gdb和Ghidra对手上还有的一个越狱过的Kindle PaperWhite 3,进行了电子书解析相关代码的逆向测试。后经分析发现,有一个名为libjpegXR.so的库负责了对jpegXR图片的解析,这或许是一个不错的攻击点。
JPEG XR 图片格式漏洞
JPEG XR是微软发布的一种图片处理格式, Kindle最新的文件格式KFX也支持JPEG XR,而又由于只有MOBI电子书文档才存在上述漏洞,初看起来好像是无关的。之后,我尝试分析Kindle中是否还有其它方式可以支持JPEG XR,发现集成WEB浏览器是支持JPEG XR格式的,如果MOBI电子书文档中包含了WEB嵌入式链接(在视觉上等同于目录链接),点击了其中了WEB嵌入链接,就会在终端设备中打开WEB浏览器。
量化参数缓冲区溢出(Buffer-Overflow)
接下来,我就着手研究JPEG XR标准,通过查看其官方参考引用代码,发现其中的jxr_priv.h文件定义了以下包含“量化参数”的jxr_image处理方法:
unsigned char dc_quant_ch[MAX_CHANNELS];
unsigned char lp_quant_ch[MAX_CHANNELS][MAX_LP_QPS];
unsigned char hp_quant_ch[MAX_CHANNELS][MAX_HP_QPS];
在图片解析文件r_parse.c中,若图片中包含了相关数据,则hp_quant_ch会被配合方法_jxr_r_TILE_HEADER_HIGHPASS执行解析操作,另外,image->num_channels方法为解析图片文件中的数据长度。其中的缓冲区大小始终不变为MAX_CHANNELS=16,所以这里可以尝试做缓冲区溢出测试。
在JPEG XR的参考引用代码中,会执行num_channels小于MAX_CHANNELS的检查,那Kindle开发人员会不会把这点忘记了呢?前面已经说过,ibjpegXR.so的库负责了对jpegXR图片的解析,于是我立即用Ghidra查看libjpegXR.so的解析机制。一番分析发现,Kindle电子文档的JPEG XR图片解析很多都和官方一致,但是上述num_channels小于MAX_CHANNELS的检查却是没有的!可能是Kindle开发人员已经把该检查方法删除了,或是以其它方式来简单代替,但无论哪种方式,在Kindle解析JPEG XR文件时,精心构造其中的图片数据就能实现缓冲区溢出攻击。
漏洞利用
在上述涉及的jxr_image方法后,存在一个指针struct jxr_tile_qp *tile_quant,方法_jxr_r_TILE_HEADER_HIGHPASS负责把hp_quant_ch中的量化参数复制到该指针中:
memcpy(image->tile_quant[ty*(image->tile_columns) + tx].hp_quant_ch, image->hp_quant_ch, MAX_CHANNELS*MAX_HP_QPS);
因此,使用上述我们分析的缓冲区溢出,攻击者只要在相应地址中写入操控数据就能覆盖tile_quant,这下就好办了。image->tile_columns和image->tile_row中定义了_jxr_r_TILE_HEADER_HIGHPASS的调用次数,这样的话,攻击者就能以此用同一张图片多次进行数据调用。
接下来,我们在WEB浏览器进程mesquite中看看解析过程中其内存映射情况:
00008000–000a0000 r-xp 00000000 b3:01 1939 /usr/bin/mesquite
000a0000–000a2000 rwxp 00098000 b3:01 1939 /usr/bin/mesquite
000a2000–002b8000 rwxp 00000000 00:00 0 [heap]…
二进制数据会被加载到一个定量地址中,其中具备了一个可执行可写的区域,这样的话,攻击就变得相对简单了。使用一些构造填充数据,可以往可写区域中放入shellcode,通过全局偏移表(Global Offset Table)有效实现缓冲区溢出。上述mesquite进程是多线程的,其中的某个线程在调用偏移表中的函数时,就会导致shellcode执行。
漏洞提权
WEB浏览器进程mesquite是在chroot的有限权限下运行的,要使得漏洞攻击成功,必须进行提权。因此,我对root进程中的本地socket接口进行了分析:
[root@kindle root]# netstat -ntpl | tail -n +3 | awk '{ print $7 }' | awk -F / '{ print $1 }' | xargs -I {} ps -o uname=,cmd= -p {}
9000 /app/bin/AaMenuApplication
9000 webreader
root stackdumpd
9000 kfxreader -l
9000 /usr/java/bin/cvm -Xmx49m -Xms49m ...
root fastmetrics
9000 kfxview
9000 /usr/java/bin/cvm -Xmx49m -Xms49m ...
其中的stackdumpd看似可以利用,我在Ghidra下进行了分析,发现它是用来负责崩溃进程的堆栈转储,它会接收崩溃进程id、线程id,并把相关信息传递给/usr/bin/dump-stack。在gdb调试环境下,该过程中涉及连接崩溃进程的一个shell脚本执行,顾名思义,堆栈转储,从以下shell脚本中可以看到大致流程:
${GDB} --quiet \
--se "${PROCESS_EXE}" \
--pid ${CURRENT_TID} \
--batch \
-ex "bt" \
-ex detach
其中的CURRENT_TID未被引用占用,所以可用它来注入一些参数。由于gdb环境下command变量可以执行任意命令,因此,可以利用它来实现root层级的任意代码执行。但是,Kindle开发人员可能对此有所意识,所以在声明中明确了CURRENT_TID是一个数字。其首次检查,会在dumpstackd进程中检查atoi函数的返回值不为0:
第二次在dump-stack进程的检查则是正则表达式方式:
“$(echo “$CURRENT_TID” | grep ‘^[0–9]*$’)” != “”
首次的atoi检查可简单用字符串加数字的方式绕过,第二次的正则表达式可在数字后加换行符进行绕过,比如构造“1\nsome string”形式的内容就可绕过上述两种检查,即能实现在root级别下的任意代码执行。综合利用前述的两个漏洞,最终可在Kindle设备上成型一个root级别的远程代码执行漏洞(RCE)。
验证过程
验证过程(POC)执行环境为Kindle 固件版本 5.13.2:
1、攻击者以前述提到的https://emkei.cz/邮件假冒方式,向受害者Kindle邮箱发送一份恶意电子书文档;
2、受害者打开Kindle邮箱并查看了其中发来的恶意电子书文档,若不小心点击了其中的一个目录链接;
3、目录链接即会调用WEB浏览器打开一个包含恶意JPEG XR图片的HTML页面;
4、在JPEG XR图片解析过程中,其中的恶意代码就会在Kindle系统中以root权限执行,漏洞Payload会更换启动背景内容执行设备重启;
5、之后,攻击者即能从受害者Kindle设备中获取到一些个人隐私信息和凭据,并成功登录到受害者亚马逊账户。
POC视频:https://youtu.be/S6dPM1KHyYA
漏洞修复
在电子书恶意注入漏洞中,亚马逊通过执行了邮件身份验证进行了修复:
JPEG XR图片缓冲区溢出漏洞中,亚马逊加入了一个不超过MAX_CHANNELS的校验检查,实现了漏洞修复;在提权漏洞中,亚马逊在dumpstackd进程中做了如下修改:
其中加入了只包含数字的特殊检查函数,替换了原先了atoi调用。在/usr/bin/dump-stack中,其正则表达式校验也更加强健安全:
< PROCESS_PID=$1
< PROCESS=$2
< CURRENT_TID=$3
---
> PROCESS_PID=$(echo $1 | head -n 1 | grep '^[[:digit:]]*$')
> PROCESS=$(echo $2 | head -n 1 | grep '^[[:alnum:]_]*$')
> CURRENT_TID=$(echo $3 | head -n 1 | grep '^[[:digit:]]*$')
漏洞上报和处理进程
2020.10.17 通过亚马逊漏洞项目上报漏洞
2020.10.19 亚马逊承认漏洞有效
2020.11.04 亚马逊奖励12K$
2020.11.11 亚马逊再次给出额外的6K$
2020.12.10 亚马逊发布5.13.4版本固件修复JPEG XR溢出和提权漏洞
2020.12.29 验证漏洞修复
2021.1.19 漏洞公开
410 主题数 |
6 帖子数 |
0 精华数 |