HFish/view/fish/view.go

359 lines
9.8 KiB
Go

package fish
import (
"bytes"
"encoding/csv"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"HFish/core/dbUtil"
"HFish/error"
"HFish/utils/log"
"HFish/utils/page"
)
var header = []string{"编号", "蜜罐类型", "蜜罐名称", "集群名称", "攻击IP", "地理信息", "威胁情报", "详情信息", "详情长度", "攻击时间"}
var judgmentMap = map[string]string{
"C2": "远控",
"Botnet": "僵尸网络",
"Hijacked": "劫持",
"Phishing": "钓鱼",
"Malware": "恶意软件",
"Exploit": "漏洞利用",
"Scanner": "扫描",
"Zombie": "傀儡机",
"Spam": "垃圾邮件",
"Suspicious": "可疑",
"Compromised": "失陷主机",
"Whitelist": "白名单",
"Brute Force": "暴力破解",
"Proxy": "代理",
"Info": "基础信息",
"MiningPool": "矿池",
"CoinMiner": "私有矿池",
"Sinkhole C2": "安全机构接管C2",
"SSH Brute Force": "SSH 暴力破解",
"FTP Brute Force": "FTP 暴力破解",
"SMTP Brute Force": "SMTP 暴力破解",
"Http Brute Force": "HTTP AUTH 暴力破解",
"Web Login Brute Force": "撞库",
"HTTP Proxy": "HTTP Proxy",
"HTTP Proxy In": "HTTP 代理入口",
"HTTP Proxy Out": "HTTP 代理出口",
"Socks Proxy": "Socks 代理",
"Socks Proxy In": "Socks 代理入口",
"Socks Proxy Out": "Socks 代理出口",
"VPN": "VPN 代理",
"VPN In": "VPN 代理入口",
"VPN Out": "VPN 代理出口",
"Tor": "Tor 代理",
"Tor Proxy In": "Tor入口",
"Tor Proxy Out": "Tor出口",
"Bogon": "保留地址",
"FullBogon": "未启用IP",
"Gateway": "网关",
"IDC": "IDC 服务器",
"Dynamic IP": "动态IP",
"Edu": "教育",
"DDNS": "动态域名",
"Mobile": "移动基站",
"Search Engine Crawler": "搜索引擎爬虫",
"CDN": "CDN 服务器",
"Advertisement": "广告",
"DNS": "DNS 服务器",
"BTtracker": "BT 服务器",
"Backbone": "骨干网",
}
// 蜜罐 页面
func Html(c *gin.Context) {
c.HTML(http.StatusOK, "fish.html", gin.H{})
}
func isCondition(condition string) bool {
if condition == ">" || condition == "<" ||
condition == ">=" || condition == "<=" ||
condition == "=" {
return true
}
return false
}
func convertJudgment(judgmentArray []interface{}) string {
var judgments string
for _, j := range judgmentArray {
js := j.(string)
judgment, ok := judgmentMap[js]
if !ok {
judgment = js
}
if len(judgments) == 0 {
judgments = judgment
} else {
judgments += " " + judgment
}
}
return judgments
}
// 获取上钩列表
func GetFishList(c *gin.Context) {
pageNo, _ := c.GetQuery("page_no")
pageSize, _ := c.GetQuery("page_size")
typex, _ := c.GetQuery("type")
colony, _ := c.GetQuery("colony")
soText, _ := c.GetQuery("so_text")
condition, _ := c.GetQuery("condition")
length, _ := c.GetQuery("length")
startTime, _ := c.GetQuery("start_time")
endTime, _ := c.GetQuery("end_time")
// 拼接 SQL
db := dbUtil.DB().Table("hfish_info").Fields("id", "type", "project_name", "agent", "ip", "country", "region", "city", "intelligence", "create_time", "info", "info_len")
dbCount := dbUtil.DB().Table("hfish_info")
if typex != "all" {
db.Where("type", "=", typex)
dbCount.Where("type", "=", typex)
}
if colony != "all" {
db.Where("agent", "=", colony)
dbCount.Where("agent", "=", colony)
}
if isCondition(condition) && length != "" {
db.Where("info_len", condition, length)
dbCount.Where("info_len", condition, length)
}
if startTime != "" && endTime != "" {
stInt, err1 := strconv.ParseInt(startTime, 10, 64)
etInt, err2 := strconv.ParseInt(endTime, 10, 64)
if err1 == nil && err2 == nil {
st := time.Unix(stInt, 0).Format("2006-01-02 15:04:05")
et := time.Unix(etInt, 0).Format("2006-01-02 15:04:05")
db.Where("create_time", ">=", st).Where("create_time", "<=", et)
dbCount.Where("create_time", ">=", st).Where("create_time", "<=", et)
} else {
log.Pr("HFish", "127.0.0.1", "parseInt startTime err", err1)
log.Pr("HFish", "127.0.0.1", "parseInt endTime err", err2)
}
}
if soText != "" {
db.Where("project_name", "like", "%"+soText+"%").OrWhere("ip", "like", "%"+soText+"%")
dbCount.Where("project_name", "like", "%"+soText+"%").OrWhere("ip", "like", "%"+soText+"%")
}
// 统计查询数量
totalCount, errCount := dbCount.Count()
if errCount != nil {
log.Pr("HFish", "127.0.0.1", "统计分页总数失败", errCount)
}
// 查询列表
pageNoInt, _ := strconv.Atoi(pageNo)
pageSizeInt, _ := strconv.Atoi(pageSize)
pageStart := page.Start(pageNoInt, pageSizeInt)
result, err := db.OrderBy("id desc").Limit(pageSizeInt).Offset(pageStart).Get()
if err != nil {
log.Pr("HFish", "127.0.0.1", "查询上钩信息列表失败", err)
}
totalCountString := strconv.FormatInt(totalCount, 10)
totalCountInt, _ := strconv.Atoi(totalCountString)
pageCount := page.TotalPage(totalCountInt, pageSizeInt)
for i, info := range result {
intelligence, ok := info["intelligence"].(string)
if !ok || len(intelligence) == 0 {
continue
}
var intelligenceData json.RawMessage
err := json.Unmarshal([]byte(intelligence), &intelligenceData)
if err != nil {
log.Pr("HFish", "127.0.0.1", "json unmarshal err", err)
continue
}
result[i]["intelligence"] = intelligenceData
}
data := map[string]interface{}{
"result": result,
"pageCount": pageCount,
"totalCount": totalCount,
"page": pageNo,
}
c.JSON(http.StatusOK, error.ErrSuccessWithData(data))
}
// 批量导出蜜罐数据
func ExportFishList(c *gin.Context) {
typex, _ := c.GetQuery("type")
colony, _ := c.GetQuery("colony")
soText, _ := c.GetQuery("so_text")
condition, _ := c.GetQuery("condition")
length, _ := c.GetQuery("length")
startTime, _ := c.GetQuery("start_time")
endTime, _ := c.GetQuery("end_time")
// 拼接 SQL
db := dbUtil.DB().Table("hfish_info").Fields("id", "type", "project_name", "agent", "ip", "country", "region", "city", "intelligence", "create_time", "info", "info_len")
if typex != "all" {
db.Where("type", "=", typex)
}
if colony != "all" {
db.Where("agent", "=", colony)
}
if isCondition(condition) && length != "" {
db.Where("info_len", condition, length)
}
if startTime != "" && endTime != "" {
stInt, err1 := strconv.ParseInt(startTime, 10, 64)
etInt, err2 := strconv.ParseInt(endTime, 10, 64)
if err1 == nil && err2 == nil {
st := time.Unix(stInt, 0).Format("2006-01-02 15:04:05")
et := time.Unix(etInt, 0).Format("2006-01-02 15:04:05")
db.Where("create_time", ">=", st).Where("create_time", "<=", et)
} else {
log.Pr("HFish", "127.0.0.1", "parseInt startTime err", err1)
log.Pr("HFish", "127.0.0.1", "parseInt endTime err", err2)
}
}
if soText != "" {
db.Where("project_name", "like", "%"+soText+"%").OrWhere("ip", "like", "%"+soText+"%")
}
result, err := db.OrderBy("id desc").Get()
if err != nil {
log.Pr("HFish", "127.0.0.1", "查询上钩信息列表失败", err)
c.JSON(http.StatusOK, error.ErrExportData)
return
}
b := &bytes.Buffer{}
wr := csv.NewWriter(b)
wr.Write(header)
for i, info := range result {
id := fmt.Sprintf("%d", i+1)
ip := info["ip"].(string)
var infoLen string
iLen, ok := info["info_len"].(int64)
if ok {
infoLen = fmt.Sprintf("%d", iLen)
}
var intelligenceResult string
intelligenceData := make(map[string]map[string]interface{})
intelligence, _ := info["intelligence"].(string)
if len(intelligence) > 20 { // 没有威胁情报的就不用反序列化了
if err := json.Unmarshal([]byte(intelligence), &intelligenceData); err != nil {
log.Pr("HFish", "127.0.0.1", "intelligence json unmarshal err", err)
intelligenceResult = intelligence
} else {
judgments, ok := intelligenceData[ip]["judgments"].([]interface{})
if ok {
intelligenceResult = convertJudgment(judgments)
} else {
intelligenceResult = intelligence
}
}
} else {
intelligenceResult = intelligence
}
var geo string
country, ok := info["country"].(string)
if ok && country != "" {
geo = country
}
region, ok := info["region"].(string)
if ok && region != "" && region != country {
geo += "-" + region
}
city, ok := info["city"].(string)
if ok && city != "" && city != country && city != region {
geo += "-" + city
}
data := []string{id, info["type"].(string), info["project_name"].(string),
info["agent"].(string), info["ip"].(string), geo, intelligenceResult,
info["info"].(string), infoLen, info["create_time"].(string)}
wr.Write(data)
}
wr.Flush()
c.Writer.Header().Set("Content-Type", "text/csv")
c.Writer.Header().Set("Content-Disposition", "attachment;filename=hfish.csv")
c.String(http.StatusOK, b.String())
}
// 删除蜜罐
func PostFishDel(c *gin.Context) {
id := c.PostForm("id")
idx := strings.Split(id, ",")
inId := make([]interface{}, 20)
for _, x := range idx {
inId = append(inId, x)
}
_, err := dbUtil.DB().Table("hfish_info").WhereIn("id", inId).Delete()
if err != nil {
log.Pr("HFish", "127.0.0.1", "删除蜜罐失败", err)
}
c.JSON(http.StatusOK, error.ErrSuccess)
}
// 获取蜜罐信息
func GetFishInfo(c *gin.Context) {
id, _ := c.GetQuery("id")
result, err := dbUtil.DB().Table("hfish_info").Fields("info").Where("id", "=", id).First()
if err != nil {
log.Pr("HFish", "127.0.0.1", "获取蜜罐信息失败", err)
}
c.JSON(http.StatusOK, error.ErrSuccessWithData(result))
}
// 获取蜜罐分类信息,集群信息
func GetFishTypeInfo(c *gin.Context) {
resultType, errType := dbUtil.DB().Table("hfish_info").Fields("type").GroupBy("type").Get()
if errType != nil {
log.Pr("HFish", "127.0.0.1", "获取蜜罐分类失败", errType)
}
resultAgent, errAgent := dbUtil.DB().Table("hfish_info").Fields("agent").GroupBy("agent").Get()
if errAgent != nil {
log.Pr("HFish", "127.0.0.1", "获取集群分类失败", errAgent)
}
data := map[string]interface{}{
"resultInfoType": resultType,
"resultColonyName": resultAgent,
}
c.JSON(http.StatusOK, error.ErrSuccessWithData(data))
}