魔改开源版本HFish - 高交互Web蜜罐

× 文章目录
  1. 1. 前言
  2. 2. 诱饵
  3. 3. 改造
  4. 4. 登陆成功告警
  5. 5. 攻击行为感知
  6. 6. 效果图
  7. 7. 没时间研究的

前言

这里魔改的HFish指的是三斤大佬维护的版本,现在的版本为闭源免费使用。

考虑到蜜罐的使用场景,主要为伪装成开放端口、服务和对外的web服务

经过测试,这个版本的HFish,无法捕获全端口位置扫描,当然可以通过自定义配置端口监听,可实现端口TCP三次握手后的捕获,syn扫描无法捕获

部署在内网,在我看来,不需要太多的交互,低交互蜜罐就够用了,及时发现内网中的异常行为,我在内网部署了一套OpenCanray低交互蜜罐,这里推荐美团大佬 P师傅 p1r06u3 的项目https://github.com/p1r06u3/opencanary_web,提供了web端管理后台

这篇文章写一下我对web蜜罐的一些想法

诱饵

web蜜罐,需要一个交互式的web网站,我用了fastadmin框架模拟了一个web后台,申请了一个比较有诱惑力的域名,如admin1、admins、sysadmin、sadmin、adminer、devadmin、testadmin、loginadmin、wpadmin等等,登陆的前端代码注释里面留一下测试账号等等

1
<!--username:test password:test -->

这里和HFish 自带的web蜜罐报警不一样,因为是高交互,有后台,这里对暴力破解不会产生报警,只有登陆成功才会触发报警

这样有一个好处就是,对外仅保留web蜜罐,蜜罐上报接口和key不会暴漏

改造

HFish 对于web的上报接口主要有3个

1
2
3
web_url = /api/v1/post/report                   # WEB蜜罐上报 API
deep_url = /api/v1/post/deep_report # 暗网蜜罐上报 API
plug_url = /api/v1/post/plug_report # 插件蜜罐上报 API

做一下区分:

其中plug接口用于做攻击行为感知

deep接口用于接收登陆成功攻击成功的告警

web接口用于接收文件操作命令监控溯源等信息

这里修改一下deep接口的代码,ip通过表单提交,因为登陆成功和攻击成功,都是在后台上报,无法在客户端获取

/view/api/view.go

1
2
3
4
5
func ReportDeepWeb(c *gin.Context) {
...
ip := c.PostForm("ip")
...
}

登陆成功告警

找到后台登陆逻辑
/fastadmin/application/admin/controller/Index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function login(){
...
$result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0);
$username = $this->request->post('username');
$password = $this->request->post('password');
$ip = $this->request->ip();

if ($result === true) {
$url1 = "http://127.0.0.1:8080/api/v1/post/deep_report";
$name = "后台登录成功告警";
$jsonStr = "$name&info=$username%26%26$password&sec_key=xxx&ip=$ip";
$a = $this->request_by_curl($url1, $jsonStr);
...
}

攻击行为感知

这里参考:HFish 插件 (任意站点,皆可蜜罐),通过nginx + lua,将请求头和请求体发送到蜜罐,就是存放完整的访问日志,在检测到攻击告警时,通过分析日志来判断攻击者做了什么操作

这里省事,直接安装OpenResty

这里从docker镜像里,把lua脚本扒出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
local cjson = require "cjson"
local http = require "resty.http"

local function http_post(url, body)
local httpc = http.new()
httpc:set_timeout(30000)
local res, err_ = httpc:request_uri(url, {
method = "POST",
body = body,
headers = {["Content-Type"] = "application/json"}
})
httpc:set_keepalive(5000, 100)
httpc:close()
end

local function get_data()
local data = {
host = ngx.var.host,
uri = ngx.var.uri,
method = ngx.var.request_method,
remote_addr = ngx.var.http_x_forwarded_for,
time_local = ngx.var.time_local,
http_user_agent = ngx.var.http_user_agent,
request_time = ngx.var.request_time
}

if "GET" == ngx.var.request_method then
data["args"] = ngx.req.get_uri_args()
elseif "POST" == ngx.var.request_method then
ngx.req.read_body()
data["args"] = ngx.req.get_post_args()
end


function string.split(input, delimiter)
input = tostring(input)
delimiter = tostring(delimiter)
if (delimiter=='') then return false end
local pos,arr = 0, {}
-- for each divider found
for st,sp in function() return string.find(input, delimiter, pos, true) end do
table.insert(arr, string.sub(input, pos, st - 1))
pos = sp + 1
end
table.insert(arr, string.sub(input, pos))
return arr
end

local headers=ngx.req.get_headers()
local clientIP=headers["X_FORWARDED_FOR"]
if clientIP == nil or string.len(clientIP) == 0 or clientIP == "unknown" then
clientIP = ngx.var.remote_addr
end
if clientIP ~= nil and string.len(clientIP) >15 then
local pos = string.split(clientIP,',')
clientIP = pos[1]

end

local result = {
name = ngx.var.hfish_name,
info = data,
sec_key = ngx.var.hfish_sec_key,
ip = clientIP
}

return cjson.encode(result)
end

http_post(ngx.var.hfish_api, get_data())

nginx配置文件添加

1
2
3
4
5
set $hfish_name '攻击行为感知';  # 插件名称
set $hfish_sec_key 'xxx'; # 接口安全密钥
set $hfish_api 'http://127.0.0.1:8989/api/v1/post/plug_report'; # 插件接口
# HFish 插件核心模块
access_by_lua_file '/usr/local/src/honeypot/hfish.lua';

效果图

攻击行为感知

image.png

后台登陆成功,这里可以配合企业微信/钉钉/飞书自动告警及时响应

image.png

image.png

没时间研究的

通过nginx + lua实现更多的功能

参考:蜜罐背后的影子系统探秘 https://cloud.tencent.com/developer/article/1045869
参考:Juggler - 一个也许能骗到黑客的系统 https://github.com/C4o/Juggler

一般场景下我们会在内部部署蜜罐系统,当外部有渗透时,碰到蜜罐就会报警,蜜罐会去检索攻击源的位置,确定别攻击机器的IP端口,取得payload数据,配合IDS我们可以捕获事件的过程,然后采取对应防御措施。还有一种办法,我们可以在蜜罐被触碰的时候,把流量引入到一台具体的机器上,伪装成一个正常的服务,像侦查机一样,收集攻击服务。我们以WEB服务为例,有一个接近真实的HTTP服务器,主动或是被动的配合蜜罐收集更多的数据,当蜜罐发现威胁IP时,运用动态迁移技术,将威胁服务引到到一个提新预备好的WEB服务,记录攻击行业,还原威胁事件。

负载均衡和灰度测试的WEB服务就是根据特定的用户和被访问机器的负载情况,决定将用户的请求切入到那台服务上。我们也用这种技术, 对有可以行为的攻击请求,进行环境切换。

我们用Openresty的上流反向代理来实现这种模式。