红队技巧:基于反向代理的水坑攻击

倾旋
倾旋
技术分享|2021-2-16|最后更新: 2023-6-22|
type
status
date
slug
summary
tags
category
icon
password
URL

0x00 前言

在红队行动中,一般使用邮件钓鱼会携带诱饵附件,但常被邮件网关拦截,如果想要去收集更多的有效信息,可以在邮件中埋入水坑链接。而埋入的水坑的制作,对于红队来说又有些繁琐,因此本文记录一下我实现自动化这块的工作。

0x01 实现目标

先明确一下实现目标:
  • 支持快速部署
  • 完美克隆任意网站
  • 可扩展的模块(受害者执行)
  • 收集所有凭证(除了Cookie还有POST数据)

0x02 Nginx实现 - 快速部署与完美克隆

互联网上有许多网页克隆的工具,大多都是将网页的前端文件(html、js、图片等)下载到本地,这个方式即使自动化也很难与网站真实后端无缝对接。于是我采用Nginx的反向代理功能来实现完美克隆,让我的Web服务器充当一个真实的客户端。但Nginx本身默认情况下,没办法做到很灵活的逻辑操作,因此需要采用OpenResty内置的Lua脚本Block。
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
根据它的官方文档和开源仓库我找到了Docker环境,使用Docker镜像就能解决快速部署的问题了。
首先拉取镜像到本地,方便后续的操作:

OpenResty配置文件

OpenResty Docker环境共有两块需要关注的配置文件:
  • /etc/nginx/conf.d
其中主配置文件是最精简的,我根据OpenResty的文档优化了一个,后续Dockerfile的编写也是替换的主配置文件。

OpenResty - Lua Ngx API

若想要在Nginx配置中执行Lua代码,需要遵循Lua Ngx API,文档中提供了*_by_lua*_by_lua_block*_by_lua_file来引入Lua代码。
nginx.conf简单实例:
当OpenResty环境以nginx.conf作为配置文件启动的话,访问网站会输出Hello,Rvn0xsy

Lua Ngx API - Block

《OpenResty 最佳实践》中提供了一个流程图:
notion image
根据这个流程图,可以将Lua代码放入不同的流程中对数据进行修改、删除、添加等。
如上面的Hello,Rvn0xsy例子,就是通过content_by_lua_block这个环节对响应内容进行修改。
本文用到的Block有:
  • header_filter_by_lua_block 用于修改响应头
  • body_filter_by_lua_block 用于修改响应内容,注入JS
  • log_by_lua_block 用于记录请求日志或凭证

Nginx 反向代理配置

Nginx反向代理配置起来非常简单。
location用于做URI匹配,当访问到/some/path/这个路径时,Nginx就代表客户端去访问http://www.example.com/link/,整个过程对客户端是完全透明的。
根据这个实例,可以直接写下第一部分,反向代理的配置了:
访问根目录就等同于访问http://www.example.com/link/
这里可能会产生一个问题,如果目标Web服务器对Host进行了判断,那么反向代理可能不会成功,因此需要将完美克隆的目标Host进行设置。
至此,就能完美克隆目标网站了。

注入模块化的Evil JS

使用body_filter_by_lua_block可以对网站内容进行修改,利用好这个功能,就能将JS文件引入到页面中。
在修改网页内容之前,需要通过header_filter_by_lua_blockContent-Length进行清空,因为修改后,Content-Length的大小一定是改变的。

使用ES6+标准将JS模块化

其中static.js就是引入的Evil JS,添加了type='module'是为了启用ES6+标准。
notion image
为了不和源站的目录冲突,7276df76835ed2272cc0e59f55e49902其实是一个虚拟的目录,通过location映射即可。
关于Import的说明可以看这篇文章
使用模块化功能可以让这个项目吸收更多关于浏览器丰富的操作,就像XSS平台那样。

Nginx - 记录日志或凭证

由于log_by_lua_block是最后一个流程,可以把一些数据进行收集,写入日志文件。
ngx.localtime()ngx.req.raw_header()是调用了Lua Ngx API

Nginx - 最终配置

Nginx - Dockerfile编写

Dockerfile :
通过设置环境变量的值,就能完美克隆任意网站。
docker-entrypoint.sh :

Nginx - docker-compose

我将镜像上传到了Docker镜像源中,可以通过如下docker-compose.yml创建实例:
notion image
日志:
notion image

0x03 Golang实现 - 快速部署与完美克隆

通过Google搜索“Golang http reverse proxy”发现,官方在标准库中已经包含了实现反向代理的代码:ReverseProxy
创建一个简单的反向代理服务器只需要少量的代码,而且还不需要处理HTTPS证书问题:
我记得以前国内在Google被墙了后,出现了许多Google镜像网站,其实背后的原理也都是反向代理技术,只不过实现的语言不一样罢了。

修改响应内容

httputil.NewSingleHostReverseProxy用来初始化一个结构体代理对象,结构体内有以下几个属性:
其中ModifyResponse是用来修改Response的,Response中包含了响应头和响应内容。
Pricking的实现方式:
handler.modifyResponse中主要进行对响应内容的处理,比如注入js、修改响应头等操作。
modifyResponse传入的是http.Response对象,如果要修改除Header以外的数据,需要对Response.body进行读取,修改完毕后,再重新赋值Response.body

Pricking 使用

有Go语言环境 - 本地编译:
有Go语言环境 - Go Install:
环境:
  • 反向代理服务器:MacOS 64Bit 192.168.117.1
  • 目标域名:https://payloads.online
配置文件:
Pricking是支持HTTPS反向代理的,我的博客刚好是HTTPS加密的,所以能把HTTPS转换为HTTP。
notion image
启动Pricking,确保配置文件、Static在当前目录
notion image
代理效果:
notion image
查看页面底部:
notion image
代码已经成功注入,static.js中的代码就是用于引用Pricking Js Suite的内容进行加载执行。
notion image

0x04 NodeJS实现 - 快速部署与完美克隆

Pricking-node 实现效果与Pricking类似,但我感觉JS好像更加简洁、方便,因此对照http-proxy-middleware模块编写了一个反向代理脚本。
通过onProxyRes属性可以定义针对Response的修改动作。

Pricking-node 使用

可以通过环境变量改变默认值:
环境变量
默认值
HOST
PORT
3000
PUBLIC_URI
/public
PUBLIC_DIR
pricking-js-suite

劫持Flash下载

劫持Flash的代码已经提交到pricking-js-suite,在这里我演示一下:
notion image
将flash模块启用:
notion image
访问: http://localhost:3000 点击立即下载将会触发js代码。
notion image
flash模块的代码如下:
 
完整项目代码:

参考

 
©2021-2024 倾旋. All rights reserved.