0x01 前言

这款网关的HTTP系统使用的是BOA服务文件,在此基础上进行的二次开发。在这款网关里面存在几个RCE漏洞点和未授权访问点,在厂商修复漏洞过程中发生了一些有趣的事,所以拿出来分享下。按照惯例和当前国情,为了不必要的麻烦,已隐去相关敏感信息,看官权当普通漏洞分析思路文章来看就好。

0x02 漏洞分析

首先来看REC漏洞,由于设备没有做游客访问控制,所以可以直接结合未授权访问进行远程直接利用,未授权访问没有什么分析价值,我们放到后文。

打开HTTP主程序boa,在我们调用请求web_ping_exe_cgi文件时,会来到这个地方,进入loc_BCAD8函数

loc_BCAD8函数是获取我们提交过来的数据包,用boaGetVar()函数接收处理数据并保存

然后接下来取出了静态变量数据“/usr/bin/diag ping ”,把数据参数传入diag文件里面的ping函数

在进行了一些操作后调用了execv()函数来执行/bin/sh,这里就是RCE漏洞触发点。
目前整个流程就很清晰了,一路走来,我们没有看到任何的参数处理函数来对我们传入的数据进行清洗,所以我们传入的攻击字符串会被拼接传入diag文件。最终执行格式为
/bin/sh -c “/usr/bin/diag ping” +data

在成功执行后会利用boaWrite()函数输出字符串“SUCCESS”。
好了,我们来看下diag文件里面的处理过程。

在diag文件里面,首先会判断我们选择的是哪个命令,这里我们选择的是“ping”命令,所以会直接调用ping()函数,我们跟进看下

.......
case "$diag_command"
 in "ping" ) Ping $diag_dst $diag_wan $diag_ipversion $ping_repeat;;
"traceroute" ) Traceroute $diag_dst $diag_wan $diag_ipversion ;;
"tracerouteu" ) Tracerouteu $diag_dst $diag_wan $diag_ipversion ;;
*) show_usage ;;
......

很明显了,在这个文件里面也没有对我们传入的参数进行过滤处理,直接就带入了执行,执行结果保存在了"/tmp/diag-result”文件里面。
因为这个bash脚本里面用的变量拼接,所以我们直接用多语句分割就行了

RESULT_FILE="/tmp/diag-result"
Ping()
{
    local destination="${1}" traceroutewan="$2
    local ipversion="${3}"
    local repeatnum="${4}"
    if [ "$ipversion" = "ipv4" ]; then
     [ -n "$traceroutewan" ] && {
     ping -c ${repeatnum} ${destination} -I ${traceroutewan} > ${RESULT_FILE} 2>&
     }
    else
     [ -n "$traceroutewan" ] && {
     ping6 -c ${repeatnum} ${destination} -I ${traceroutewan} > ${RESULT_FILE} 2>&1
     }
    fi}

本地监听执行结果

0x03 二次复核

在厂家修复漏洞后,复查了一下漏洞的修复结果。
咋看下相关漏洞被修复了,未授权访问不存在,但是在认真看了修复代码后发现,修复结果可以被绕过。

未授权修复不当
在最新的版本中,修复了上一版本的未授权问题,其中存在未授权访问的页面已经无法访问,但是厂家在此基础上修复不当,无意之间引入了一个后门,我们来了解一下。
其中禁止访问的一部分敏感页面如下,添加了访问判断规则

但是,在往下分析时发现,发现厂商为这些页面添加了一个账号密码(这种修复方法闻所未闻,活久见),要访问这些页面需要这个账号密码,游客和管理员访问这些限制页面都会先判断帐号密码,不过访问的帐号密码却被硬编码到固件中,在这种情况下造成了很明显的后门帐号,如图

所以,我们只需要在访问页面时加上帐号密码参数就行了

RCE漏洞修复不当
在RCE漏洞接收参数这个地方,添加了一个strtok_r()函数来处理分隔符“;”问题

但是可以执行多行命令的分隔符却不止这一个,所以还是存在绕过的可能,我们只需要将“;”号换成“||”或“&&”或者其他的可执行的分割语法就行了,这里换成"||"进行尝试,最后成功执行。

0x04 三次复核

未授权修复不当
在厂家进一步修复后,之前的明文后门帐号变成了编码后门,md5加base64的混合加密。

后门还是存在,只不过加密了而已,只要解开了hash值,那么就可以利用明文密码访问敏感页面了

RCE漏洞修复不当
还是之前的那个RCE漏洞,厂家这次不在HTTP主程序中进行数据判断,转向Web源码函数判断。现在在网页源码中添加了一个回调函数来判断命令分隔符,这个已经很不错了,提高了利用难度,不过现实是还是可以绕过.......
我们来看下这个回调函数
在源代码中有两个函数,inValidIPAddr()和isValidUrlName(),这两个函数是过滤IP和域名的,IP我们无法绕过,正则写的很死,但是对于域名过滤,我们却是可以绕过的,由于判断是先判断是否为IP地址再判断是否为域名,那么这两个回调函数结合起来等于没起作用。源码太长,这里取主要函数。下面我们来看下过滤源码

function inValidIPAddr(Address)
{
    var address = Address.match("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$");
    var digits;
    var i;
    if(address == null) {
    return false;
    }
    digits = address[0].split(".");
    for(i=0; i < 4; i++)
    {
        if((Number(digits[i]) > 255 ) || (Number(digits[i]) < 0 ) || (Number(digits[0]) > 223) || (digits[i] == null))
        {
        return false;
        }
    }
    return true;
}
function isValidUrlName(url)
{
    var i=0;
    var invalidArray = new Array();
    invalidArray[i++] = "www";
    invalidArray[i++] = "com";
    invalidArray[i++] = "org";
    invalidArray[i++] = "net";
    invalidArray[i++] = "edu";
    invalidArray[i++] = "www.";
    invalidArray[i++] = ".com";
    invalidArray[i++] = ".org";
    invalidArray[i++] = ".net";
    invalidArray[i++] = ".edu";
    if (isValidAscii(url) != ''")
    {
        return false;
    }
    for (i = 0; i < url.length; i++)
    {
        if (url.charAt(i) == '\\')
        {
        return false;
        }
        if (url.charAt(i) == '&')
        {
        return false;
        }
        if (url.charAt(i) == '|')
        {
        return false;
        }
        if (url.charAt(i) == ';')
        {
        return false;
        }
        }
        if (url == "")
        {
        return false;
        }
        if (url.length < 3)
        {
        return false;
    }
    for(j=0; j< invalidArray.length; j++)
    {
        if (url == invalidArray[j])
        {
        return false;
        }
    }
    return true;
}

这次比之前都要厉害一些,这次过滤了 “&”,“|”,";“这三个很常见的命令分割符。不过在linux系统中,执行命令的分割符有多种情况除了 “&”,“|”,";“这三种外,还有“`"、"$()"等,所以结果是,修复结果又绕过了。如图

0x05 最后

经过几次的修复和绕过,我们可以发现,如果一个系统没有考虑到对输入、输出、数据流进行严格检查控制的话,都有可能造成一定的安全风险。厂商由于安全开发知识缺乏,导致修复结果令人哭笑不得。最后,由于攻击的难度已加大,安全性也有所提高,厂商尽力了,那么作者也尽力了。

源链接

Hacking more

...