Redis CVE-2015-4335分析

栏目: Lua · 发布时间: 6年前

内容简介:利用到的漏洞分别为OP_FORPREP/OP_FORLOOP、OP_CLOSURE中的类型混淆,这里以Redis 2.8.20版本进行分析。1) OP_FORPREP/OP_FORLOOPlua中对for循环生成的字节码如下:

1. 漏洞分析

利用到的漏洞分别为OP_FORPREP/OP_FORLOOP、OP_CLOSURE中的类型混淆,这里以 Redis 2.8.20版本进行分析。

1) OP_FORPREP/OP_FORLOOP

lua中对for循环生成的字节码如下:

Redis CVE-2015-4335分析

可以看到for循环是由FORPREP、FORLOOP两条指令组合而来,对应的源码是deps/lua/src/lvm.c line 654-680:

Redis CVE-2015-4335分析

在OP_FORPREP中,lua对参数进行类型检查,判断是否为number类型,不是则触发错误;然而在OP_FORLOOP中,因已做过类型检查,便假定参数为number类型,并对其执行idx = idx + step操作,这导致任意类型到number类型的混淆。

如下修改字节码中的FORPREP指令("\96%z%z\128")为JMP指令("\22\0\0\128"),跳过OP_FORPREP中的类型检查,直接进入OP_FORLOOP:

Redis CVE-2015-4335分析

测试如下:

Redis CVE-2015-4335分析

2) OP_CLOSURE

对CLOSURE指令的处理位于deps/lua/src/lvm.c line 723-742:

Redis CVE-2015-4335分析

line 731-737是对闭包的处理,具体为在CLOSURE指令后后生成对应的MOVE指令,MOVE指令的第二个参数为闭包变量引用。正常情况下引用只能指向当前栈桢中的局部变量,但通过修改字节码,可以将其指向至任意位置。

Redis CVE-2015-4335分析

如上,通过修改"(\100%z%z%z)...."(MOVE 0 0)为"%1\0\0\0\1"(MOVE 0 2),将middle函数中的magic引用指向middle函数自身(R2),所以输出的结果为middle函数。

对函数调用的处理位于deps/lua/src/lvm.c line 586-606:

Redis CVE-2015-4335分析

对函数返回的处理位于deps/lua/src/lvm.c line 382-390:

Redis CVE-2015-4335分析

line385将L->ci->func(当前函数指针)转换为Closure指针,由上文可知,通过修改字节码可以将闭包变量引用指向当前函数指针,导致任意类型到Closure类型的混淆。

基于此,结合number类型混淆,可以做任意地址读/写:

Redis CVE-2015-4335分析

结尾处修改字节码,将middle/inner函数中的magic引用指向middle函数;inner函数中将magic赋值为字符串,这使得middle函数中的当前函数指针将被混淆为该字符串,函数返回; middle函数中读取闭包变量magic,读取闭包变量对应的源码为deps/lua/src/lvm.c line 427-431:

Redis CVE-2015-4335分析

其实际上是去当前函数指针的upvals字段中获取相应引用,而当前函数指针已被混淆为字符串,对应的upvals字段可控。

TString类型与Closure类型的结构如下:

TString

CommonHeader

reversed

align

hash

len

str

8

1

1

1

1

4

8

char[len]

Closure

CommonHeader

isC

nupvalues

align

gclist

env

p

upvals

8

1

1

1

1

4

8

8

8

UpVal* [n]

变量upval为字符串,as_double(upval)获取其TString指针,偏移24获取到upval->str地址,也就是说cl->p、cl->upvals[0]都指向输入的字符串"commonhead16bits" .. p32(lo) .. p32(hi)。

UpVal结构如下:

UpVal

CommonHeader

align

v

u

8

1

1

6

8

所以cl->upvals[0]->v指向构造的指针p32(lo) .. p32(hi),也即为addr。

以上,便将任意地址的前8字节读取出来,写操作也是同理,只需要在middle函数中对magic赋值,需注意的是写操作实际会写入8字节数值及4字节tt类型:

deps/lua/src/lvm.c line 451-456:

Redis CVE-2015-4335分析

deps/lua/src/lobject.h line 161-164:

Redis CVE-2015-4335分析

测试如下:

Redis CVE-2015-4335分析

2. 漏洞利用

具备任意地址读/写能力后是一定可以做代码执行的,目前想到如下两种方案。

1) 覆写CClosure->f

lua 中可以使用coroutine.wrap创建C函数闭包对象CClosure,其结构如下:

CClosure

CommonHeader

isC

nupvalues

align

gclist

env

f

upvals

8

1

1

1

1

4

8

8

8

UpVal* [n]

CClosure->f指向函数指针,调用其对应的源码为deps/lua/src/ldo.c 307-326:

Redis CVE-2015-4335分析

2) 覆写got

Linux PWN常规思路,通过DynELF解析Binary,进一步解析libc,获取system地址并覆写至fputs.got;在lua中调用print("id")即可执行命令。

Redis CVE-2015-4335分析

3.漏洞修复

两个漏洞都是因为加载字节码导致的,Redis中的修复简单粗暴,直接干掉了字节码加载:

https://github.com/antirez/redis/commit/49efe300af258e83f377cd8142d2c67d66fc2e3a

Redis CVE-2015-4335分析

4. 参考

  • https://gist.github.com/corsix/6575486

  • https://apocrypha.numin.it/talks/lua_bytecode_exploitation.pdf


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

引爆用户增长

引爆用户增长

黄天文 / 机械工业出版社 / 2017-11-1 / 79.00

本书是用户增长领域的开创性著作,是作者在去哪儿、360、百度等知名企业多年用户增长工作的经验总结。宏观层面,从战略高度构建了一套系统的、科学的用户增长方法论;微观层面,从战术执行细节上针对用户增长体系搭建、用户全生命周期运营等总结了大量能引爆用户增长的实操方法和技巧。 不仅有方法论和技巧,而且非常注重实操。对电商、团购、共享经济、互联网金融等4大行业的50余家企业(360、美团、滴滴等)的1......一起来看看 《引爆用户增长》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具