PrivHunterAI/scan.go

281 lines
8.9 KiB
Go
Raw Normal View History

2025-01-16 10:32:36 +08:00
package main
import (
2025-02-18 18:16:48 +08:00
"encoding/json"
2025-01-16 10:32:36 +08:00
"fmt"
"io"
"log"
"net/http"
"net/url"
"strings"
"time"
2025-02-25 14:20:40 +08:00
aiapis "yuequanScan/AIAPIS"
2025-02-27 10:07:35 +08:00
"yuequanScan/config"
2025-03-21 10:57:01 +08:00
"github.com/lqqyt2423/go-mitmproxy/proxy"
2025-01-16 10:32:36 +08:00
)
2025-02-18 18:16:48 +08:00
type Result struct {
2025-04-23 17:16:58 +08:00
Method string `json:"method"`
Url string `json:"url"` // JSON 标签用于自定义字段名
// Reqbody string `json:"reqbody"`
RequestA string `json:"requestA"`
RequestB string `json:"requestB"`
2025-04-10 18:05:56 +08:00
RespBodyA string `json:"respBodyA"`
RespBodyB string `json:"respBodyB"`
Result string `json:"result"`
Reason string `json:"reason"`
Confidence string `json:"confidence"`
2025-04-24 11:11:18 +08:00
Timestamp string `json:"timestamp"`
2025-02-25 15:40:26 +08:00
}
// 扫描结果
type ScanResult struct {
2025-04-10 18:05:56 +08:00
Res string `json:"res"`
Reason string `json:"reason"`
Confidence string `json:"confidence"`
2025-02-18 18:16:48 +08:00
}
2025-01-16 10:32:36 +08:00
func scan() {
for {
time.Sleep(3 * time.Second)
logs.Range(func(key any, value any) bool {
// fmt.Println("The type of x is", reflect.TypeOf(value))
var r *RequestResponseLog
if rr, ok := value.(*RequestResponseLog); ok {
r = rr
} else {
fmt.Printf("Value is not of type RequestResponseLog\n")
}
2025-03-01 19:03:26 +08:00
//
2025-02-26 22:05:55 +08:00
if r.Request.Header != nil && r.Response.Header != nil && r.Response.Body != nil && r.Response.StatusCode == 200 {
2025-03-01 19:03:26 +08:00
// fmt.Println(r)
2025-04-23 17:16:58 +08:00
result, req1, req2, resp1, resp2, err := sendHTTPAndKimi(r) // 主要
2025-02-18 18:16:48 +08:00
if err != nil {
2025-03-01 19:03:26 +08:00
logs.Delete(key)
// fmt.Println(r)
2025-02-18 18:16:48 +08:00
fmt.Println(err)
} else {
var resultOutput Result
2025-02-26 12:47:29 +08:00
resultOutput.Method = TruncateString(r.Request.Method)
2025-03-23 10:57:01 +08:00
if r.Request.URL.RawQuery != "" {
2025-03-23 11:08:22 +08:00
resultOutput.Url = TruncateString(r.Request.URL.Scheme + "://" + r.Request.URL.Host + r.Request.URL.Path + "?" + r.Request.URL.RawQuery)
2025-03-23 10:57:01 +08:00
} else {
2025-04-10 18:05:56 +08:00
resultOutput.Url = TruncateString(r.Request.URL.Scheme + "://" + r.Request.URL.Host + r.Request.URL.Path)
2025-03-23 10:57:01 +08:00
}
2025-04-23 17:16:58 +08:00
// resultOutput.Reqbody = TruncateString(string(r.Request.Body))
2025-02-26 12:47:29 +08:00
resultOutput.RespBodyA = TruncateString(resp1)
2025-04-23 17:16:58 +08:00
httpRequest1, err := generateHTTPRequest(req1)
if err != nil {
fmt.Println("ErrorhttpRequest:", err)
}
httpRequest2, err := generateHTTPRequest(req2)
if err != nil {
fmt.Println("ErrorhttpRequest:", err)
}
resultOutput.RequestA = httpRequest1
resultOutput.RequestB = httpRequest2
2025-02-26 12:47:29 +08:00
resultOutput.RespBodyB = TruncateString(resp2)
2025-02-25 15:40:26 +08:00
//
result1, err := parseResponse(result)
2025-02-18 18:16:48 +08:00
if err != nil {
2025-02-25 15:40:26 +08:00
log.Fatalf("解析失败: %v", err)
}
var scanR ScanResult
err = json.Unmarshal([]byte(result1), &scanR)
if err != nil {
log.Println("解析 JSON 数据失败("+result+": )", err)
} else {
resultOutput.Result = scanR.Res
resultOutput.Reason = scanR.Reason
2025-04-10 18:05:56 +08:00
resultOutput.Confidence = scanR.Confidence
2025-04-24 11:11:18 +08:00
resultOutput.Timestamp = time.Now().Format("2006-01-02 15:04:05")
2025-02-25 15:40:26 +08:00
jsonData, err := json.Marshal(resultOutput)
if err != nil {
log.Fatalf("Error marshaling to JSON: %v", err)
}
log.Println(string(jsonData))
2025-02-26 12:35:38 +08:00
//--- 前端
2025-03-23 10:57:01 +08:00
var dataItem Result
2025-02-26 12:35:38 +08:00
// 解析 JSON 数据到结构体
err = json.Unmarshal([]byte(jsonData), &dataItem)
if err != nil {
log.Fatalf("Error parsing JSON: %v", err)
}
// 打印解析后的结构体内容
2025-02-26 12:47:29 +08:00
// fmt.Printf("Parsed DataItem: %+v\n", dataItem)
// if dataItem.RespBodyB{
// }
2025-02-26 14:05:11 +08:00
if dataItem.Result != "white" {
Resp = append(Resp, dataItem)
}
2025-02-26 12:35:38 +08:00
//---
2025-03-23 10:57:01 +08:00
log.Println(PrintYuequan(resultOutput.Result, resultOutput.Method, resultOutput.Url, resultOutput.Reason))
2025-02-25 15:40:26 +08:00
logs.Delete(key)
return true // 返回true继续遍历返回false停止遍历
2025-02-18 18:16:48 +08:00
}
}
2025-02-19 15:01:01 +08:00
} else {
// logs.Delete(key) // 不可以添加logs.Delete(key)
return true
2025-01-16 10:32:36 +08:00
}
return true
})
}
}
2025-04-23 17:16:58 +08:00
func sendHTTPAndKimi(r *RequestResponseLog) (result, reqA, reqB, respA, respB string, err error) {
r.Request.Header.Add("Host", r.Request.URL.Host)
2025-03-01 19:03:26 +08:00
jsonDataReq, err := json.Marshal(r.Request)
if err != nil {
fmt.Println("Error marshaling:", err)
2025-04-23 17:16:58 +08:00
return "", "", "", "", "", err // 返回错误
2025-03-01 19:03:26 +08:00
}
req1 := string(jsonDataReq)
2025-01-16 10:32:36 +08:00
resp1 := string(r.Response.Body)
fullURL := &url.URL{
Scheme: r.Request.URL.Scheme,
Host: r.Request.URL.Host,
Path: r.Request.URL.Path,
RawQuery: r.Request.URL.RawQuery,
}
2025-04-23 17:16:58 +08:00
// 达成这些要求进行越权扫描
2025-02-27 10:07:35 +08:00
if isNotSuffix(r.Request.URL.Path, config.GetConfig().Suffixes) && !containsString(r.Response.Header.Get("Content-Type"), config.GetConfig().AllowedRespHeaders) {
2025-01-16 10:32:36 +08:00
req, err := http.NewRequest(r.Request.Method, fullURL.String(), strings.NewReader(string(r.Request.Body)))
if err != nil {
fmt.Println("创建请求失败:", err)
2025-04-23 17:16:58 +08:00
return "", "", "", "", "", err // 返回错误
2025-01-16 10:32:36 +08:00
}
req.Header = r.Request.Header
2025-02-27 16:26:18 +08:00
// 增加其他头 2025 02 27
if config.GetConfig().Headers2 != nil {
for key, value := range config.GetConfig().Headers2 {
req.Header.Set(key, value)
}
}
// 2025 02 27 end
// req.Header.Set("Cookie", config.GetConfig().Cookie2)
2025-03-01 19:03:26 +08:00
// log.Println(req.Header)
2025-03-21 10:57:01 +08:00
requestInfo2 := proxy.Request{
Method: req.Method,
URL: req.URL,
Proto: req.Proto,
Header: req.Header,
Body: r.Request.Body,
}
jsonDataReq2, err := json.Marshal(requestInfo2)
if err != nil {
fmt.Println("Error marshaling:", err)
2025-04-23 17:16:58 +08:00
return "", "", "", "", "", err // 返回错误
2025-03-21 10:57:01 +08:00
}
req2 := string(jsonDataReq2)
2025-01-16 10:32:36 +08:00
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("请求失败:", err)
2025-04-23 17:16:58 +08:00
return "", "", "", "", "", err // 返回错误
2025-01-16 10:32:36 +08:00
}
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
2025-04-23 17:16:58 +08:00
return "", "", "", "", "", err // 返回错误
2025-01-16 10:32:36 +08:00
}
// 将响应体转换为字符串
resp2 := string(bodyBytes)
2025-03-01 19:03:26 +08:00
2025-02-19 15:01:01 +08:00
if len(resp1+resp2) < 65535 {
2025-03-03 11:27:16 +08:00
if !MatchString(config.GetConfig().RespBodyBWhiteList, resp2) {
// 初始值
var resultDetect string
var detectErr error
maxRetries := 5
for i := 0; i < maxRetries; i++ {
resultDetect, detectErr = detectPrivilegeEscalation(config.GetConfig().AI, req1, resp1, resp2, resp.Status)
if detectErr == nil {
break // 成功退出循环
}
// 可选:增加延迟避免频繁请求
fmt.Println("AI分析异常重试中异常原因", detectErr)
time.Sleep(5 * time.Second) // 1秒延迟
}
2025-03-01 19:42:30 +08:00
2025-03-03 11:27:16 +08:00
if detectErr != nil {
fmt.Println("Error after retries:", detectErr)
2025-04-23 17:16:58 +08:00
return "", "", "", "", "", detectErr
2025-03-01 19:03:26 +08:00
}
2025-04-23 17:16:58 +08:00
return resultDetect, req1, req2, resp1, resp2, nil
2025-03-03 11:27:16 +08:00
} else {
2025-04-24 16:05:47 +08:00
return `{"res": "false", "reason": "匹配到关键字判断为无越权未消耗AI tokens","confidence":"100%"}`, req1, req2, resp1, resp2, nil
2025-03-01 19:03:26 +08:00
}
2025-02-19 15:01:01 +08:00
} else {
2025-04-24 16:05:47 +08:00
return `{"res": "white", "reason": "请求包太大","confidence":"100%"}`, req1, req2, resp1, resp2, nil
2025-01-16 10:32:36 +08:00
}
2025-02-19 15:01:01 +08:00
2025-02-18 18:16:48 +08:00
}
2025-04-24 16:05:47 +08:00
return `{"res": "white", "reason": "白名单后缀或白名单Content-Type接口","confidence":"100%"}`, req1, "", resp1, "", nil
2025-01-16 10:32:36 +08:00
}
2025-03-01 19:30:06 +08:00
func detectPrivilegeEscalation(AI string, reqA, resp1, resp2, statusB string) (string, error) {
2025-02-06 15:37:33 +08:00
var result string
var err error
switch AI {
case "kimi":
2025-03-03 17:23:05 +08:00
model := "moonshot-v1-8k"
aiurl := "https://api.moonshot.cn/v1/chat/completions"
apikey := config.GetConfig().APIKeys.Kimi
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 kimi 检测是否越权
2025-02-06 15:37:33 +08:00
case "deepseek":
2025-03-03 17:23:05 +08:00
model := "deepseek-chat"
aiurl := "https://api.deepseek.com/v1/chat/completions"
apikey := config.GetConfig().APIKeys.DeepSeek
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 kimi 检测是否越权
2025-02-25 17:47:41 +08:00
case "qianwen":
2025-04-24 16:49:08 +08:00
model := "qwen-plus"
2025-03-03 17:23:05 +08:00
aiurl := "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
apikey := config.GetConfig().APIKeys.Qianwen
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 kimi 检测是否越权
2025-03-03 15:06:14 +08:00
case "hunyuan":
2025-03-03 17:23:05 +08:00
model := "hunyuan-turbo"
aiurl := "https://api.hunyuan.cloud.tencent.com/v1/chat/completions"
apikey := config.GetConfig().APIKeys.HunYuan
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 hunyuan 检测是否越权
case "glm":
model := "glm-4-air"
aiurl := "https://open.bigmodel.cn/api/paas/v4/chat/completions"
apikey := config.GetConfig().APIKeys.Glm
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 hunyuan 检测是否越权
case "gpt":
model := "gpt-4o"
aiurl := "https://open.bigmodel.cn/api/paas/v4/chat/completions"
apikey := config.GetConfig().APIKeys.Gpt
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 hunyuan 检测是否越权
2025-02-06 15:37:33 +08:00
default:
2025-03-03 17:23:05 +08:00
model := "moonshot-v1-8k"
aiurl := "https://api.moonshot.cn/v1/chat/completions"
apikey := config.GetConfig().APIKeys.Kimi
result, err = aiapis.AIScan(model, aiurl, apikey, reqA, resp1, resp2, statusB) // 调用 kimi 检测是否越权
2025-02-06 15:37:33 +08:00
}
if err != nil {
return "", err
}
return result, nil
}