Skip to content

Commit c18b3ff

Browse files
committed
支持html、json格式任务导出
1 parent 336b429 commit c18b3ff

31 files changed

+1145
-416
lines changed

app.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func (a *App) InitTycHeader(token string) {
268268
info.InitHEAD(token)
269269
}
270270

271-
func (a *App) SubsidiariesAndDomains(query string, subLevel, ratio int, searchDomain bool, machine string) []info.CompanyInfo {
271+
func (a *App) SubsidiariesAndDomains(query string, subLevel, ratio int, searchDomain bool, machine string) []structs.CompanyInfo {
272272
tkm := info.CheckKeyMap(a.ctx, query)
273273
time.Sleep(time.Second)
274274
result := info.SearchSubsidiary(a.ctx, tkm.CompanyName, tkm.CompanyId, ratio, false, searchDomain, machine)
@@ -297,7 +297,7 @@ func (a *App) SubsidiariesAndDomains(query string, subLevel, ratio int, searchDo
297297
return result
298298
}
299299

300-
func (a *App) WechatOfficial(query string) []info.WechatReulst {
300+
func (a *App) WechatOfficial(query string) []structs.WechatReulst {
301301
var companyId string
302302
for _, tkm := range info.TycKeyMap {
303303
if tkm.CompanyName == query {
@@ -499,7 +499,7 @@ func (a *App) NewWebScanner(options structs.WebscanOptions, proxy clients.Proxy)
499499
}
500500
id++
501501
gologger.Info(a.ctx, fmt.Sprintf("vulnerability scanning %d/%d", id, count))
502-
webscan.NewNucleiEngine(a.ctx, proxy, webscan.NucleiOption{
502+
webscan.NewNucleiEngine(a.ctx, proxy, structs.NucleiOption{
503503
URL: target,
504504
Tags: util.RemoveDuplicates(tags),
505505
TemplateFile: options.TemplateFiles,

core/info/tianyancha.go

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,8 @@ func GetCompanyID(ctx context.Context, company string) (string, string) {
126126
return company_id, company_name
127127
}
128128

129-
type CompanyInfo struct {
130-
CompanyName string
131-
Holding string
132-
Investment string // 投资比例
133-
RegStatus string
134-
Domains []string
135-
CompanyId string
136-
}
137-
138129
// 返回查询公司的名称和子公司的名称, isSecond 是否为二次查询
139-
func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio int, isSecond bool, searchDomain bool, machine string) (Asset []CompanyInfo) {
130+
func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio int, isSecond bool, searchDomain bool, machine string) (Asset []structs.CompanyInfo) {
140131
data := make(map[string]interface{})
141132
data["gid"] = companyId
142133
data["pageSize"] = 100
@@ -161,7 +152,14 @@ func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio
161152
gologger.Debug(ctx, err)
162153
}
163154
}
164-
Asset = append(Asset, CompanyInfo{companyName, "本公司", "", qr.State, util.RemoveDuplicates(domains), companyId})
155+
Asset = append(Asset, structs.CompanyInfo{
156+
CompanyName: companyName,
157+
Holding: "本公司",
158+
Investment: "",
159+
RegStatus: qr.State,
160+
Domains: util.RemoveDuplicates(domains),
161+
CompanyId: companyId,
162+
})
165163
}
166164
for _, result := range qr.Data.Result {
167165
gq, _ := strconv.Atoi(strings.TrimSuffix(result.Percent, "%"))
@@ -174,7 +172,14 @@ func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio
174172
gologger.Debug(ctx, err)
175173
}
176174
}
177-
Asset = append(Asset, CompanyInfo{result.Name, result.Percent, result.Amount, result.RegStatus, util.RemoveDuplicates(subsidiaryDomains), fmt.Sprint(result.ID)})
175+
Asset = append(Asset, structs.CompanyInfo{
176+
CompanyName: result.Name,
177+
Holding: result.Percent,
178+
Investment: result.Amount,
179+
RegStatus: result.RegStatus,
180+
Domains: util.RemoveDuplicates(subsidiaryDomains),
181+
CompanyId: fmt.Sprint(result.ID),
182+
})
178183
}
179184
}
180185
return
@@ -199,17 +204,8 @@ type OfficialAccounts struct {
199204
} `json:"data"`
200205
}
201206

202-
type WechatReulst struct {
203-
CompanyName string
204-
WechatName string
205-
WechatNums string
206-
Logo string
207-
Qrcode string
208-
Introduction string
209-
}
210-
211207
// 获取微信公众号信息
212-
func WeChatOfficialAccounts(ctx context.Context, companyName, companyId string) (wr []WechatReulst) {
208+
func WeChatOfficialAccounts(ctx context.Context, companyName, companyId string) (wr []structs.WechatReulst) {
213209
_, b, err := clients.NewRequest("GET", "https://capi.tianyancha.com/cloud-business-state/wechat/list?graphId="+companyId+"&pageSize=1&pageNum=1", gethead, nil, 10, true, clients.DefaultClient())
214210
if err != nil {
215211
gologger.Error(ctx, err)
@@ -228,7 +224,7 @@ func WeChatOfficialAccounts(ctx context.Context, companyName, companyId string)
228224
}
229225
json.Unmarshal(b, &oa)
230226
for _, result := range oa.Data.ResultList {
231-
wr = append(wr, WechatReulst{
227+
wr = append(wr, structs.WechatReulst{
232228
CompanyName: companyName,
233229
WechatNums: result.PublicNum,
234230
WechatName: result.Title,

core/waf/waf.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var (
2121
"qianxin": {".360safedns.com", ".360cloudwaf.com", ".360wzb.com", ".qaxcloudwaf.com"},
2222
"baiduyunjiasu": {".yunjiasu-cdn.net"},
2323
"anquanbao": {".anquanbao.net", ".anquanbao.com"},
24-
"aliyun": {"kunlun", "aliyunddos", "aliyunwaf", "aligaofang", "aliyundunwaf", ".yundunwaf2.com"},
24+
"aliyun": {"kunlun", "aliyunddos", "aliyunwaf", "aligaofang", "aliyundunwaf", ".yundunwaf2.com", ".yundunwaf1.com"},
2525
"xuanwudun": {".saaswaf.com", ".dbappwaf.cn"},
2626
"yundun": {".hwwsdns.cn", ".yunduncname.com"},
2727
"knownsec-ns": {".jiasule.net"},

core/webscan/callnuclei.go

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"slack-wails/lib/clients"
77
"slack-wails/lib/gologger"
8+
"slack-wails/lib/structs"
89
"strings"
910

1011
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
@@ -13,28 +14,7 @@ import (
1314
"github.com/wailsapp/wails/v2/pkg/runtime"
1415
)
1516

16-
type VulnerabilityInfo struct {
17-
ID string
18-
Name string
19-
Description string
20-
Reference string
21-
Type string
22-
Risk string
23-
URL string
24-
Request string
25-
Response string
26-
Extract string
27-
}
28-
29-
type NucleiOption struct {
30-
SkipNucleiWithoutTags bool // 如果没有扫描到指纹,是否需要扫描全漏洞还是直接跳过
31-
URL string
32-
Tags []string // 全漏洞扫描时,使用自定义标签
33-
TemplateFile []string
34-
TemplateFolders []string
35-
}
36-
37-
func NewNucleiEngine(ctx context.Context, proxy clients.Proxy, o NucleiOption) {
17+
func NewNucleiEngine(ctx context.Context, proxy clients.Proxy, o structs.NucleiOption) {
3818
if o.SkipNucleiWithoutTags && len(o.Tags) == 0 {
3919
gologger.Info(ctx, fmt.Sprintf("[nuclei] %s does not have tags, scan skipped", o.URL))
4020
return
@@ -76,7 +56,7 @@ func NewNucleiEngine(ctx context.Context, proxy clients.Proxy, o NucleiOption) {
7656
if event.Info.Reference != nil && !event.Info.Reference.IsEmpty() {
7757
reference = strings.Join(event.Info.Reference.ToSlice(), ",")
7858
}
79-
runtime.EventsEmit(ctx, "nucleiResult", VulnerabilityInfo{
59+
runtime.EventsEmit(ctx, "nucleiResult", structs.VulnerabilityInfo{
8060
ID: event.TemplateID,
8161
Name: event.Info.Name,
8262
Description: event.Info.Description,
@@ -115,6 +95,10 @@ func showRequest(event *output.ResultEvent) string {
11595

11696
func showResponse(event *output.ResultEvent) string {
11797
if event.Response != "" {
98+
byteResponse := []byte(event.Response)
99+
if len(byteResponse) > 1024*512 {
100+
return string(byteResponse[:1024*512]) + " ..."
101+
}
118102
return event.Response
119103
}
120104
if event.Interaction != nil {

core/webscan/honeypot.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package webscan
2+
3+
import "strings"
4+
5+
func checkHoneypotWithHeaders(rawHeaders string) bool {
6+
count := strings.Count(rawHeaders, "Set-Cookie")
7+
return count > 5
8+
}
9+
10+
func checkHoneypotWithFingerprintLength(length int) bool {
11+
return length > 15
12+
}

core/webscan/infoscan.go

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,6 @@ type WebInfo struct {
5050
Cert string // TLS证书
5151
}
5252

53-
type InfoResult struct {
54-
URL string
55-
StatusCode int
56-
Length int
57-
Title string
58-
Fingerprints []string
59-
IsWAF bool
60-
WAF string
61-
Detect string
62-
Screenshot string // 截图图片路径
63-
}
64-
6553
type FingerScanner struct {
6654
ctx context.Context
6755
urls []*url.URL
@@ -108,7 +96,7 @@ func NewFingerScanner(ctx context.Context, proxy clients.Proxy, options structs.
10896
func (s *FingerScanner) NewFingerScan() {
10997
var wg sync.WaitGroup
11098
single := make(chan struct{})
111-
retChan := make(chan InfoResult, len(s.urls))
99+
retChan := make(chan structs.InfoResult, len(s.urls))
112100
go func() {
113101
for pr := range retChan {
114102
runtime.EventsEmit(s.ctx, "webFingerScan", pr)
@@ -144,7 +132,7 @@ func (s *FingerScanner) NewFingerScan() {
144132
goto ContinueExecution
145133
}
146134
// 如果是正常的无法响应则直接返回
147-
retChan <- InfoResult{
135+
retChan <- structs.InfoResult{
148136
URL: u.String(),
149137
StatusCode: 0,
150138
}
@@ -202,7 +190,7 @@ func (s *FingerScanner) NewFingerScan() {
202190
fingerprints = append(fingerprints, "Fastjson")
203191
}
204192

205-
if len(fingerprints) >= 20 {
193+
if checkHoneypotWithHeaders(web.HeadeString) || checkHoneypotWithFingerprintLength(len(fingerprints)) {
206194
fingerprints = []string{"疑似蜜罐"}
207195
}
208196

@@ -218,7 +206,7 @@ func (s *FingerScanner) NewFingerScan() {
218206
s.basicURLWithFingerprint[u.String()] = append(s.basicURLWithFingerprint[u.String()], fingerprints...)
219207
s.mutex.Unlock()
220208

221-
retChan <- InfoResult{
209+
retChan <- structs.InfoResult{
222210
URL: u.String(),
223211
StatusCode: web.StatusCode,
224212
Length: web.ContentLength,
@@ -266,7 +254,7 @@ func (s *FingerScanner) NewActiveFingerScan(rootPath bool) {
266254
visited := make(map[string]bool) // 用于记录已访问的URL和路径组合
267255

268256
single := make(chan struct{})
269-
retChan := make(chan InfoResult, len(s.urls))
257+
retChan := make(chan structs.InfoResult, len(s.urls))
270258
go func() {
271259
for pr := range retChan {
272260
runtime.EventsEmit(s.ctx, "webFingerScan", pr)
@@ -315,7 +303,7 @@ func (s *FingerScanner) NewActiveFingerScan(rootPath bool) {
315303
s.basicURLWithFingerprint[fp.URL.String()] = append(s.basicURLWithFingerprint[fp.URL.String()], result...)
316304
s.mutex.Unlock()
317305

318-
retChan <- InfoResult{
306+
retChan <- structs.InfoResult{
319307
URL: fullURL,
320308
StatusCode: ti.StatusCode,
321309
Length: ti.ContentLength,

database.go

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package main
33
import (
44
"context"
55
"database/sql"
6+
"encoding/json"
67
"fmt"
78
"os"
89
"slack-wails/core/portscan"
9-
"slack-wails/core/webscan"
10+
"slack-wails/lib/fileutil"
1011
"slack-wails/lib/gologger"
12+
"slack-wails/lib/report"
1113
"slack-wails/lib/structs"
1214
"slack-wails/lib/util"
1315
"strings"
@@ -820,16 +822,21 @@ func (d *Database) DeleteScanTask(taskid string) bool {
820822
return isSuccess
821823
}
822824

823-
func (d *Database) SelectFingerscanResult(taskid string) []webscan.InfoResult {
825+
func (d *Database) RenameScanTask(taskid, taskname string) bool {
826+
updateStmt := "UPDATE scanTask SET task_name = ? WHERE task_id = ?"
827+
return d.ExecSqlStatement(updateStmt, taskname, taskid)
828+
}
829+
830+
func (d *Database) SelectFingerscanResult(taskid string) []structs.InfoResult {
824831
rows, err := d.DB.Query("SELECT * FROM FingerprintInfo WHERE task_id = ?;", taskid)
825832
if err != nil {
826833
gologger.Debug(d.ctx, err)
827-
return []webscan.InfoResult{}
834+
return []structs.InfoResult{}
828835
}
829836
defer rows.Close()
830-
var results []webscan.InfoResult
837+
var results []structs.InfoResult
831838
for rows.Next() {
832-
var result webscan.InfoResult
839+
var result structs.InfoResult
833840
var fingerprintsStr string
834841
var task_id string
835842
err = rows.Scan(&task_id, &result.URL, &result.StatusCode, &result.Length, &result.Title, &result.Detect, &result.IsWAF, &result.WAF, &fingerprintsStr, &result.Screenshot)
@@ -851,15 +858,15 @@ func (d *Database) SelectFingerscanResult(taskid string) []webscan.InfoResult {
851858
return results
852859
}
853860

854-
func (d *Database) SelectPocscanResult(taskid string) []webscan.VulnerabilityInfo {
861+
func (d *Database) SelectPocscanResult(taskid string) []structs.VulnerabilityInfo {
855862
rows, err := d.DB.Query("SELECT * FROM VulnerabilityInfo WHERE task_id = ?", taskid)
856863
if err != nil {
857-
return []webscan.VulnerabilityInfo{}
864+
return []structs.VulnerabilityInfo{}
858865
}
859866
defer rows.Close()
860-
var results []webscan.VulnerabilityInfo
867+
var results []structs.VulnerabilityInfo
861868
for rows.Next() {
862-
var result webscan.VulnerabilityInfo
869+
var result structs.VulnerabilityInfo
863870
var task_id string
864871
err = rows.Scan(&task_id, &result.ID, &result.Name, &result.Type, &result.Risk, &result.URL, &result.Extract, &result.Request, &result.Response, &result.Description, &result.Reference)
865872
if err != nil {
@@ -871,12 +878,12 @@ func (d *Database) SelectPocscanResult(taskid string) []webscan.VulnerabilityInf
871878
return results
872879
}
873880

874-
func (d *Database) InsertFingerscanResult(taskid string, result webscan.InfoResult) bool {
881+
func (d *Database) InsertFingerscanResult(taskid string, result structs.InfoResult) bool {
875882
insertStmt := "INSERT INTO FingerprintInfo (task_id, url, status, length, title, detect, is_waf, waf, fingerprints, screenshot) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
876883
return d.ExecSqlStatement(insertStmt, taskid, result.URL, result.StatusCode, result.Length, result.Title, result.Detect, result.IsWAF, result.WAF, strings.Join(result.Fingerprints, ","), result.Screenshot)
877884
}
878885

879-
func (d *Database) InsertPocscanResult(taskid string, result webscan.VulnerabilityInfo) bool {
886+
func (d *Database) InsertPocscanResult(taskid string, result structs.VulnerabilityInfo) bool {
880887
insertStmt := "INSERT INTO VulnerabilityInfo (task_id, template_id, vuln_name, protocol, severity, vuln_url, extract, request, response, description, reference) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
881888
return d.ExecSqlStatement(insertStmt, taskid, result.ID, result.Name, result.Type, result.Risk, result.URL, result.Extract, result.Request, result.Response, result.Description, result.Reference)
882889
}
@@ -885,3 +892,29 @@ func (d *Database) DeletePocscanResult(taskid, template_id, vuln_url string) boo
885892
deleteStmt := "DELETE FROM VulnerabilityInfo WHERE task_id = ? AND template_id = ? AND vuln_url = ?"
886893
return d.ExecSqlStatement(deleteStmt, taskid, template_id, vuln_url)
887894
}
895+
896+
func (d *Database) ExportWebReportWithJson(reportpath string, task structs.TaskResult) bool {
897+
fingerprintsResult := d.SelectFingerscanResult(task.TaskId)
898+
pocsResult := d.SelectPocscanResult(task.TaskId)
899+
result := structs.WebReport{
900+
Targets: task.Targets,
901+
Fingerprints: fingerprintsResult,
902+
POCs: pocsResult,
903+
}
904+
return fileutil.SaveJsonWithFormat(d.ctx, reportpath, result)
905+
}
906+
907+
func (d *Database) ReadWebReportWithJson(reportpath string) (result structs.WebReport, err error) {
908+
data, err := os.ReadFile(reportpath)
909+
if err != nil {
910+
return
911+
}
912+
err = json.Unmarshal(data, &result)
913+
return
914+
}
915+
916+
func (d *Database) ExportWebReportWithHtml(reportpath, taskid string) bool {
917+
fingerprintsResult := d.SelectFingerscanResult(taskid)
918+
pocsResult := d.SelectPocscanResult(taskid)
919+
return os.WriteFile(reportpath, []byte(report.GenerateReport(fingerprintsResult, pocsResult)), 0644) == nil
920+
}

0 commit comments

Comments
 (0)