WEB中隐藏攻击面的寻找挖掘

前言:WEB中隐藏攻击面的寻找,这边就学习记录分享三个隐藏攻击面

参考文章:https://portswigger.net/research/cracking-the-lens-targeting-https-hidden-attack-surface
参考文章:https://www.yuque.com/pmiaowu/bomi9w/fgg2vg
参考文章:https://datatracker.ietf.org/doc/html/rfc7234
参考文章:https://github.com/No4l/Burp4SSRF
参考文章:https://issues.apache.org/jira/browse/HTTPCLIENT-1803
参考文章:https://www.cnblogs.com/zpchcbd/p/12654984.html
参考文章:https://www.agarri.fr/blog/archives/2011/11/12/traceroute-like_http_scanner/index.html
参考文章:https://www.rfc-editor.org/rfc/rfc3261
参考文章:https://www.rfc-editor.org/rfc/rfc2616

host碰撞

这个方法帮助了我挖掘了到许多的src漏洞,效果也很比较好

请求一个域名的流程是怎么样的?首先看本机缓存,再看HOSTS记录,如果都没有则请求本地DNS服务器,本地DNS服务器中没有,则本地DNS服务器迭代去请求根DNS服务器,上面的图中在本机的HOSTS写上两个模拟的地址,因为条件有限啊,模拟不了DNS服务器,所以这里就模拟HOSTS作为DNS服务器

挖掘zpchcbd.com的域名的漏洞,发现收集的域名其中DNS解析的一个IP为192.168.4.136(假设外网IP),直接访问192.168.4.136却是回显为nginx 403拒绝访问的界面

但是此时该nginx为反向代理的服务器,且配置情况如下所示

这时候就可以通过该ip来匹配不同的host字段来进行访问,比如访问hosts字段头为admin.zpchcbd.com

实战中的host碰撞的总结和利用如下

  • 内网的管理系统和业务系统都用同一台nginx服务器进行反向代理

  • 扫外网的时候扫到解析ip为内网的域名(如何大量的搜集内部的域名才是最重要的)

  • 通过hosts碰撞,来遍历域名绑定外网的这个Nginx的ip,如果正好如何这个nginx的配置项的server_name则hosts碰撞成功

实战中的利用效果也很好,这里推荐的碰撞工具:https://github.com/pmiaowu/HostCollision

如何有效的发现反向代理的服务器

想要进行host碰撞首先肯定需要先知道哪些服务器是存在反向代理的,这里给出几个方法

trace方法

通过默认的trace方法可以判断Max-Forwards为0的时候的第一台代理服务器或者是非代理服务器(最终的web容器)

即使现在的trace方法都已经被禁止了,但是响应包中还是会通过via字段来进行显示,所以可以通过判断Via字段或者是X-Via来判断是否是代理服务器,比如下面就是通过slb负载均衡来进行反向代理的服务器

如果用trace访问不存在反向代理,一般显示如下不存在Via字段

如果默认的trace方法配合上Max-Forwards的时候,此时Max-Forwards小于中间要跳转的次数,那么最终响应包中返回的状态码是483

一些别人整理的查找反向代理的时候响应包中的特征

# Heuristics :
# - Status Codes :
#	- HTTP Status Code == 502
#	- HTTP Status Code == 483
# - Specific data in body or headers :
#	- X-Forwarded-For in body when using TRACE
#	- Via or X-Via in headers
# - Differences between hops :
#	- HTTP Status Codes
#	- Server headers
#	- Content-Type headers
#	- Via headers
#	- HTML titles
#	- HTML <address> tags
#	- X-Forwarded-For values when using TRACE 

代码实现,已经集成到myscan的模块中了

# coding=utf-8
# @Author   : zpchcbd HG team
# @Time     : 2021-09-09 13:37

from core.data import gLogger
from exploit.scripts import BaseScript
from core.myenums import BugLevel, BugType
from core.request.asynchttp import *

# fofa: "nginx" && country="CN"
# python3 batch.py -m exploit.scripts.Info.reverseproxy.get_web_reverse_proxy -fs "\"nginx\" && country=\"CN\"" -cs

class Script(BaseScript):
    name = 'Get Web Reverse Proxy'

    def __init__(self, target):
        super().__init__()
        # 漏洞目标
        self.target = target
        # 漏洞等级
        self.bug_level = BugLevel.HIGH
        # 类型
        self.bug_type = BugType.MISCONFIGURATION
        # 编号
        self.bug_number = ''
        # 来源
        self.bug_refer = 'https://www.agarri.fr/blog/archives/2011/11/12/traceroute-like_http_scanner/index.html'
        # 特定路径判断
        self.detect_path_list = ['/']
        # exec
        self.exec_path_list = []
        # 相关信息
        self.info = '''
        配合host碰撞使用,作为隐藏资产面的挖掘方式,判断特征用了下面几个情况
        - A 483 status code is returned (RFC 3261, section 8.1.1.6)
        - 'Via' or 'X-Via' headers are detected
        - 'Server' headers
        - 'Via' headers
        '''

    async def detect(self):
        score, all_http_info = 0, {'Server': {}, 'Via': {}}
        for detect_path in self.detect_path_list:
            connector = aiohttp.connector.TCPConnector(verify_ssl=False)
            headers = self.headers.copy()
            url = f'http://{self.target}{detect_path}' if self.target.startswith(('http:', 'https:')) is False else f'{self.target}{detect_path}'
            for _ in range(3):
                headers.update({'Max-Forwards': str(_)})
                async with aiohttp.request(method='TRACE', url=url, connector=connector, headers=headers) as response:
                    if response is not None:
                        for h in all_http_info.keys():
                            if h == 'Via':
                                h_via = response.headers.get('Via', '')
                                h_x_via = response.headers.get('X-Via', '')
                                all_http_info[h][_] = h_via if h_via else h_x_via if h_x_via else ''
                            elif h == 'Server':
                                all_http_info[h][_] = response.headers.get('Server', '')
                        if response.status == 483:
                            score += 1
            await connector.close()
            # analysis
            print(all_http_info)
            for _ in all_http_info.keys():
                previous = 'undefine'
                for i in range(3):
                    try:
                        current = all_http_info[_][i]
                    except KeyError:
                        current = 'undefine'
                    if previous != current and i > 0:
                        score += 1
                    previous = current
            # summary
            if score > 1:
                self.flag = True
                gLogger.myscan_info('[{} {}] {}'.format(self.name, BugType.MISCONFIGURATION, url))
                return {'name': '{} {}'.format(self.name, BugType.MISCONFIGURATION), 'url': url, 'software': self.name}

pingback模糊测试ssrf

这种还没有遇到过,也是这几天刚看到的一个2017年的议题才在这里进行的记录,之后如果有找到这种情况的话会在这边进行记录更新

  • 不正确的HTTP主机头,修改host字段导致的ssrf的情况,可能是配置问题,也可能是代码问题,或者是后端的日志分析系统发起的请求

  • 请求行覆盖host字段,下面的图中已经知道了www.icefilms.info真实ip地址

  • @转发问题,bp中请求host指定为incap-client:80@internal.net,可能在后端转发处理的时候处理为http://user:pass@hostname/,导致后端进行@重定向

  • Apache HttpComponents库的安全问题,允许请求行可以不以/开头,导致指定url为@burp-collaborator.net,最终后端转发被重定向,请求的地址为http://public-backend@burp-collaborator.net/

参考文章:https://issues.apache.org/jira/browse/HTTPCLIENT-1803

Url backendURL = "http://public-backend/";
String uri = ctx.getRequest().getRawUri();
        
URI proxyUri;
try {
proxyUri = new URIBuilder(uri) // uri -> @burp-collaborator.net
        .setHost(backendURL.getHost()) -> public-backend@burp-collaborator.net
        .setPort(backendURL.getPort()) -> 80
        .setScheme(backendURL.getScheme())
        .build();
} catch (URISyntaxException e) {
    Util.sendError(ctx, 400, INVALID_REQUEST_URL);
    return;
}
  • headers字段头fuzz
X-Forwarded-For: a.burpcollaborator.net
True-Client-IP: b.burpcollaborator.net
Referer: http://c.burpcollaborator.net/

登陆口的跳转

这里分享两种情况,一个是我自己的 一个是pmiaowu师傅的

pmiaowu师傅的分享

设计统一登录链接各种站点的时候,判断是否登录,不会去真的获取登录信息,为了减少请求压力,都是判断数据包某个值是否存在,值可能就是下面的某个字段

header头加:
    Authorization: JWT 1
    ticket: 1
    token: 1
Cookie添加:
    ticket=1;
    Authorization=JWT 1;
    token=1;
    user=1;
    userId=1;
    UserId=1;
    admin=1;
    adminId=1;
    adminid=1;
    AdminId=1;
    Adminid=1;
    xh=1;
    xuehao=1;
    gh=1;
    gonghao=1;
    username=1;
header头加:
    X-Forwarded-For: 10.10.10.10
    x-originating-ip: 127.0.0.1
    x-remote-ip: 127.0.0.1
    x-remote-addr: 127.0.0.1
    X-Real-IP: 192.168.1.1
    X-Original-URL: /admin

自我分享

相关src平台的报告有期间查看时间,所以这边看不了就没有图了,主要就是对于一些统一的单点登录验证的接口的跳转302,有时候你会看到在跳转之前还会有相关的登录显示,这种情况下可以尝试去观察下js的代码,去发现相关的登录接口构造账号密码的参数进行登陆,如果成功获取token的话那么就可以绕过单点登录,构造token来进行登陆单系统

posted @ 2023-01-28 19:46  zpchcbd  阅读(427)  评论(0)    收藏  举报