RELRO



0.Introduction

linux下的有两个著名的函数表Or姐妹花,plt表,got表,他们分别称位进程连接表与全局描述表

其中,GOT表在lazy binding后储存的是函数的真实地址,Got.plt中存放的全局变量的偏移地址
在Attacker的攻击过程中,经常能够获得任意地址写的权限,很多情况下都会选择修改got表中内容来hijack control flow,这种相关类似的攻击手段被称之为hijack Got或者GOT overwrite attack
由于Got表中存放的是非常关键的信息,所以如何能够保护好Got表,成为了一个重要问题
RELRO保护为此而生,它是一种比较古老的技术,至少2008年之前就已经进入了upstream
其全称为RELocation Read-Only,重定位表只读技术

1.Linux’s RELRO

在linux中,存在两种RELRO模式,一种是Partial RELRO,一种是Full RELRO,其中linux默认开启的是Partial RELRO
Partial RELRO

compiler command line: gcc -Wl,-z,relro
the ELF sections are reordered so that the ELF internal data sections (.got, .dtors, etc.) precede the program’s data sections (.data and .bss)
non-PLT GOT is read-only
GOT is still writeable

Full RELRO

compiler command line: gcc -Wl,-z,relro,-z,now supports all the
features of partial RELRO bonus: the entire GOT is also (re)mapped as
read-only

一般来说,FULL RELRO的保护效果更好,但是开销相对更大

Source code

Relocation Read Only的大概实现就是由linker指定binary的一块经过dynamic linker处理过 relocation之后的区域为只读.
<1>首先gcc需要判断哪一些常量需要放到linker指定的只读储存区中
gcc在遇到这种变量的时候就会相应将其置于SECTION .data.rel.ro或者 .data.rel.ro.local 里.评判的关键就是初始化数据是不是external linkage.

<2>指定程序绑定的方式,lazy binding或者是now binding,linux下默认时lazy binding
-z now的程序

-z lazy的程序

lazy binding的程序需要通过dl_resolve重新寻找到函数的真实地址,所以在plt.got开始存放的时dl动态链接函数的地址,而不使用lazy binding的程序plt.got中存放的直接就是真实地址,在程序加载后统一binding上初始值
ld 在处理这两种方式生成的代码不同

<3>处理.data.rel.ro/.data.rel.ro.local
这部分的处理在ld里面其实非常隐晦

对上述程序解释如下:
.rel.dyn是生成的binary的section,’{/}’扩住的部分是输入文件的section.也就是后面的 section进入前面的section.
而根据linker script的处理规则,.rel.dyn也要进入类型为PT_GNU_RELRO的segment的

<4>glibc/dynamic-linker
最后的使得GOT表可能的代码在glibc的动态链接的代码中
dynamic-linker会解析executable的segment table当遇到PT_GNU_RELRO的时候记录其起点 地址和长度.

最后将这段的内存利用mproctect设置权限为不可写

经过GNU toolchiains的这些工作之后executable将会得到一个最大范围的不可写的存储区,并将我们想要不可写的区域放置到该内存中

Testcase

我们的example程序如下:

我们用3种方式对程序进行编译:
<1>gcc -Wl,-z,norelro fsb.c -o fsb1

可见在0x8049000-0x804a000都是可写的部分,其中包含了

说明在RELRO没开启的情况下,全局变量与全局函数表都是可以被篡改的
<2>gcc -Wl,-z,relro,-z,lazy fsb.c -o fsb2

启用lazy-banding的方式,RELRO 部分开启
在0804a000-0804b000 rw-p 时可写的段,而对应到程序中,发现

Got表只读,而got.plt全局函数偏移表可写
我们称这种方式为Parital RELRO
<3>gcc -Wl,-z,relro,-z,now fsb.c -o fsb3

RELRO开启,并采用now binding方式
可见此时程序只有data与bss段可写,其余部分都是不可写的
由于不是采用lazy-binding的方式,所以没有.plt.got,全部被写入到got表中
将符号表设置为只读,很大程序上防止了篡改函数表的攻击手段
这种禁用lazy-binding采用RELRO的方式成为FULL RELRO

2.Bypassing FULL_RELRO

Bypass FULL RELRO
首先强调,遇到FULL RELRO,因为重定位段不可写,想要再Hijcak GOT Table的方式十分困难(并非不可能)
所以一般的思路都不在Hijack Got Table,转换思路在其他地方寻找突破口
在寻找资料的过程中,也找到了真正”绕过”Full RELRO的方式

CVE-2012-0809

该CVE是一个关于linux中sudo命令的格式化字符串漏洞 ,其中由于sudo 的binary开启了Full RELRO,所以CVE的作者提供了一种Bypass的方式值得我们借鉴

We can now use “%n” primitive to write anywhere with any value, but where to write to? sudo binary is compiled with Full RELRO, this means we cannot write to GOT entry or dynamic->.fini to redirect the execution as they are read-only. The idea here is simple: we try to overwrite function pointer in libc or ld-linux and hope it will be called later in program to trigger redirection. This works smoothly with sudo case.

首先,FULL_RELRO开启,GOT表与GOT.PLT表只读
当我们拥有任意地址写的权限之后,我们无法写GOT表,控制函数指针
看到上述的描述,我们可以去写一些地方的函数指针,比如libc或者ld-linux的中,期待他们在后续的程序中被调用,这样就执行了我们的攻击代码
这种看似根本不是绕过的Bypass,是目前唯一能够找到的FULL_RELRO的方式,可见,这种保护机制的引进还是给漏洞利用造成了巨大的困难

索性,FULL_RELRO开启时需要now binding,而不是现在主流的lazy-binding,所以运行的速度上大打折扣
所以大多追求效率的应用程序时不会开启FULL,只会开启Partial RELRO
那么我们Hijack GOT 依然时能够发挥作用的

3.Exploitations

利用上面的fsb.c,开启FULL RELRO

程序开启了Canary,NX,FULL_RELRO
我们知道在开启FULL_RELRO后,GOT表只能读,所以我们无法利用格式化字符串漏洞篡改GOT表
虽然限制了我们无法做栈溢出,也无法利用printf函数篡改GOT表,但是我们依旧能够利用它修改返回地址,修改参数,从而实现Ret2libc(栈总是可写的吧!!)

思路如下:

1.确定格式化字符串的偏移
2.确定libc的基地址,从而确定system函数与”/bin/sh”字符串的地址
3.利用printf格式化字符串漏洞修改返回地址与第一个参数
4.实现system(“/bin/sh”)

4.Afterword

RELRO 是很早进入linux的一种保护技术,它的保护目标是相对脆弱但是关键的全局偏移量GOT表
它能够将GOT表设置位只读,从而避免Attacker恶意修改GOT表达到目的的攻击企图

在牺牲一部分运行效率的基础上,RELRO能够几乎完美(目前没有成型的bypaas 技术)保护GOT表
关于RELRO,我们一定需要深入理解linux中的GOT,PLT表以及lazy-binding的机制才能够真正理解它的内涵

5.Reference

RELRO – A (not so well known) Memory Corruption Mitigation Technique
Dongliang Mu de Blog
RELROとformat string attackによるリターンアドレス書き換え
Exploiting Sudo format string vunerability

发表评论