From c18b3ffc296f87bb53fc1afa24e47ff66f0c7053 Mon Sep 17 00:00:00 2001 From: qiwentaidi <104491549+qiwentaidi@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:32:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81html=E3=80=81json=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E4=BB=BB=E5=8A=A1=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 6 +- core/info/tianyancha.go | 42 +- core/waf/waf.go | 2 +- core/webscan/callnuclei.go | 30 +- core/webscan/honeypot.go | 12 + core/webscan/infoscan.go | 24 +- database.go | 55 ++- file.go | 26 +- frontend/src/assets/icon/textwrap.svg | 1 - frontend/src/export.ts | 4 +- frontend/src/stores/interface.ts | 22 -- frontend/src/stores/options.ts | 2 + frontend/src/views/AppStarter.vue | 6 +- frontend/src/views/Asset/Company.vue | 32 +- frontend/src/views/Asset/Subdomain.vue | 14 +- frontend/src/views/Permeation/Portscan.vue | 55 +-- frontend/src/views/Permeation/Webscan.vue | 180 +++++++-- frontend/src/views/PocManagement.vue | 65 ++-- frontend/src/views/Tools/DataHanding.vue | 3 +- frontend/wailsjs/go/main/App.d.ts | 5 +- frontend/wailsjs/go/main/Database.d.ts | 17 +- frontend/wailsjs/go/main/Database.js | 16 + frontend/wailsjs/go/main/File.d.ts | 4 +- frontend/wailsjs/go/main/File.js | 8 +- frontend/wailsjs/go/models.ts | 421 +++++++++++++++------ lib/fileutil/file.go | 21 + lib/{util => fileutil}/unzip.go | 2 +- lib/report/default.go | 211 +++++++++++ lib/report/report.go | 111 ++++++ lib/structs/structs.go | 161 +++++--- lib/update/update.go | 3 +- 31 files changed, 1145 insertions(+), 416 deletions(-) create mode 100644 core/webscan/honeypot.go delete mode 100644 frontend/src/assets/icon/textwrap.svg create mode 100644 lib/fileutil/file.go rename lib/{util => fileutil}/unzip.go (99%) create mode 100644 lib/report/default.go create mode 100644 lib/report/report.go diff --git a/app.go b/app.go index f70eb4a5..be593ebe 100644 --- a/app.go +++ b/app.go @@ -268,7 +268,7 @@ func (a *App) InitTycHeader(token string) { info.InitHEAD(token) } -func (a *App) SubsidiariesAndDomains(query string, subLevel, ratio int, searchDomain bool, machine string) []info.CompanyInfo { +func (a *App) SubsidiariesAndDomains(query string, subLevel, ratio int, searchDomain bool, machine string) []structs.CompanyInfo { tkm := info.CheckKeyMap(a.ctx, query) time.Sleep(time.Second) 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 return result } -func (a *App) WechatOfficial(query string) []info.WechatReulst { +func (a *App) WechatOfficial(query string) []structs.WechatReulst { var companyId string for _, tkm := range info.TycKeyMap { if tkm.CompanyName == query { @@ -499,7 +499,7 @@ func (a *App) NewWebScanner(options structs.WebscanOptions, proxy clients.Proxy) } id++ gologger.Info(a.ctx, fmt.Sprintf("vulnerability scanning %d/%d", id, count)) - webscan.NewNucleiEngine(a.ctx, proxy, webscan.NucleiOption{ + webscan.NewNucleiEngine(a.ctx, proxy, structs.NucleiOption{ URL: target, Tags: util.RemoveDuplicates(tags), TemplateFile: options.TemplateFiles, diff --git a/core/info/tianyancha.go b/core/info/tianyancha.go index a0d125d5..aa65025c 100644 --- a/core/info/tianyancha.go +++ b/core/info/tianyancha.go @@ -126,17 +126,8 @@ func GetCompanyID(ctx context.Context, company string) (string, string) { return company_id, company_name } -type CompanyInfo struct { - CompanyName string - Holding string - Investment string // 投资比例 - RegStatus string - Domains []string - CompanyId string -} - // 返回查询公司的名称和子公司的名称, isSecond 是否为二次查询 -func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio int, isSecond bool, searchDomain bool, machine string) (Asset []CompanyInfo) { +func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio int, isSecond bool, searchDomain bool, machine string) (Asset []structs.CompanyInfo) { data := make(map[string]interface{}) data["gid"] = companyId data["pageSize"] = 100 @@ -161,7 +152,14 @@ func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio gologger.Debug(ctx, err) } } - Asset = append(Asset, CompanyInfo{companyName, "本公司", "", qr.State, util.RemoveDuplicates(domains), companyId}) + Asset = append(Asset, structs.CompanyInfo{ + CompanyName: companyName, + Holding: "本公司", + Investment: "", + RegStatus: qr.State, + Domains: util.RemoveDuplicates(domains), + CompanyId: companyId, + }) } for _, result := range qr.Data.Result { gq, _ := strconv.Atoi(strings.TrimSuffix(result.Percent, "%")) @@ -174,7 +172,14 @@ func SearchSubsidiary(ctx context.Context, companyName, companyId string, ratio gologger.Debug(ctx, err) } } - Asset = append(Asset, CompanyInfo{result.Name, result.Percent, result.Amount, result.RegStatus, util.RemoveDuplicates(subsidiaryDomains), fmt.Sprint(result.ID)}) + Asset = append(Asset, structs.CompanyInfo{ + CompanyName: result.Name, + Holding: result.Percent, + Investment: result.Amount, + RegStatus: result.RegStatus, + Domains: util.RemoveDuplicates(subsidiaryDomains), + CompanyId: fmt.Sprint(result.ID), + }) } } return @@ -199,17 +204,8 @@ type OfficialAccounts struct { } `json:"data"` } -type WechatReulst struct { - CompanyName string - WechatName string - WechatNums string - Logo string - Qrcode string - Introduction string -} - // 获取微信公众号信息 -func WeChatOfficialAccounts(ctx context.Context, companyName, companyId string) (wr []WechatReulst) { +func WeChatOfficialAccounts(ctx context.Context, companyName, companyId string) (wr []structs.WechatReulst) { _, 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()) if err != nil { gologger.Error(ctx, err) @@ -228,7 +224,7 @@ func WeChatOfficialAccounts(ctx context.Context, companyName, companyId string) } json.Unmarshal(b, &oa) for _, result := range oa.Data.ResultList { - wr = append(wr, WechatReulst{ + wr = append(wr, structs.WechatReulst{ CompanyName: companyName, WechatNums: result.PublicNum, WechatName: result.Title, diff --git a/core/waf/waf.go b/core/waf/waf.go index d82eb15c..f149e8d8 100644 --- a/core/waf/waf.go +++ b/core/waf/waf.go @@ -21,7 +21,7 @@ var ( "qianxin": {".360safedns.com", ".360cloudwaf.com", ".360wzb.com", ".qaxcloudwaf.com"}, "baiduyunjiasu": {".yunjiasu-cdn.net"}, "anquanbao": {".anquanbao.net", ".anquanbao.com"}, - "aliyun": {"kunlun", "aliyunddos", "aliyunwaf", "aligaofang", "aliyundunwaf", ".yundunwaf2.com"}, + "aliyun": {"kunlun", "aliyunddos", "aliyunwaf", "aligaofang", "aliyundunwaf", ".yundunwaf2.com", ".yundunwaf1.com"}, "xuanwudun": {".saaswaf.com", ".dbappwaf.cn"}, "yundun": {".hwwsdns.cn", ".yunduncname.com"}, "knownsec-ns": {".jiasule.net"}, diff --git a/core/webscan/callnuclei.go b/core/webscan/callnuclei.go index b6d32aa1..72333034 100644 --- a/core/webscan/callnuclei.go +++ b/core/webscan/callnuclei.go @@ -5,6 +5,7 @@ import ( "fmt" "slack-wails/lib/clients" "slack-wails/lib/gologger" + "slack-wails/lib/structs" "strings" nuclei "github.com/projectdiscovery/nuclei/v3/lib" @@ -13,28 +14,7 @@ import ( "github.com/wailsapp/wails/v2/pkg/runtime" ) -type VulnerabilityInfo struct { - ID string - Name string - Description string - Reference string - Type string - Risk string - URL string - Request string - Response string - Extract string -} - -type NucleiOption struct { - SkipNucleiWithoutTags bool // 如果没有扫描到指纹,是否需要扫描全漏洞还是直接跳过 - URL string - Tags []string // 全漏洞扫描时,使用自定义标签 - TemplateFile []string - TemplateFolders []string -} - -func NewNucleiEngine(ctx context.Context, proxy clients.Proxy, o NucleiOption) { +func NewNucleiEngine(ctx context.Context, proxy clients.Proxy, o structs.NucleiOption) { if o.SkipNucleiWithoutTags && len(o.Tags) == 0 { gologger.Info(ctx, fmt.Sprintf("[nuclei] %s does not have tags, scan skipped", o.URL)) return @@ -76,7 +56,7 @@ func NewNucleiEngine(ctx context.Context, proxy clients.Proxy, o NucleiOption) { if event.Info.Reference != nil && !event.Info.Reference.IsEmpty() { reference = strings.Join(event.Info.Reference.ToSlice(), ",") } - runtime.EventsEmit(ctx, "nucleiResult", VulnerabilityInfo{ + runtime.EventsEmit(ctx, "nucleiResult", structs.VulnerabilityInfo{ ID: event.TemplateID, Name: event.Info.Name, Description: event.Info.Description, @@ -115,6 +95,10 @@ func showRequest(event *output.ResultEvent) string { func showResponse(event *output.ResultEvent) string { if event.Response != "" { + byteResponse := []byte(event.Response) + if len(byteResponse) > 1024*512 { + return string(byteResponse[:1024*512]) + " ..." + } return event.Response } if event.Interaction != nil { diff --git a/core/webscan/honeypot.go b/core/webscan/honeypot.go new file mode 100644 index 00000000..e8ed35d4 --- /dev/null +++ b/core/webscan/honeypot.go @@ -0,0 +1,12 @@ +package webscan + +import "strings" + +func checkHoneypotWithHeaders(rawHeaders string) bool { + count := strings.Count(rawHeaders, "Set-Cookie") + return count > 5 +} + +func checkHoneypotWithFingerprintLength(length int) bool { + return length > 15 +} diff --git a/core/webscan/infoscan.go b/core/webscan/infoscan.go index 13fd570b..86a96e35 100644 --- a/core/webscan/infoscan.go +++ b/core/webscan/infoscan.go @@ -50,18 +50,6 @@ type WebInfo struct { Cert string // TLS证书 } -type InfoResult struct { - URL string - StatusCode int - Length int - Title string - Fingerprints []string - IsWAF bool - WAF string - Detect string - Screenshot string // 截图图片路径 -} - type FingerScanner struct { ctx context.Context urls []*url.URL @@ -108,7 +96,7 @@ func NewFingerScanner(ctx context.Context, proxy clients.Proxy, options structs. func (s *FingerScanner) NewFingerScan() { var wg sync.WaitGroup single := make(chan struct{}) - retChan := make(chan InfoResult, len(s.urls)) + retChan := make(chan structs.InfoResult, len(s.urls)) go func() { for pr := range retChan { runtime.EventsEmit(s.ctx, "webFingerScan", pr) @@ -144,7 +132,7 @@ func (s *FingerScanner) NewFingerScan() { goto ContinueExecution } // 如果是正常的无法响应则直接返回 - retChan <- InfoResult{ + retChan <- structs.InfoResult{ URL: u.String(), StatusCode: 0, } @@ -202,7 +190,7 @@ func (s *FingerScanner) NewFingerScan() { fingerprints = append(fingerprints, "Fastjson") } - if len(fingerprints) >= 20 { + if checkHoneypotWithHeaders(web.HeadeString) || checkHoneypotWithFingerprintLength(len(fingerprints)) { fingerprints = []string{"疑似蜜罐"} } @@ -218,7 +206,7 @@ func (s *FingerScanner) NewFingerScan() { s.basicURLWithFingerprint[u.String()] = append(s.basicURLWithFingerprint[u.String()], fingerprints...) s.mutex.Unlock() - retChan <- InfoResult{ + retChan <- structs.InfoResult{ URL: u.String(), StatusCode: web.StatusCode, Length: web.ContentLength, @@ -266,7 +254,7 @@ func (s *FingerScanner) NewActiveFingerScan(rootPath bool) { visited := make(map[string]bool) // 用于记录已访问的URL和路径组合 single := make(chan struct{}) - retChan := make(chan InfoResult, len(s.urls)) + retChan := make(chan structs.InfoResult, len(s.urls)) go func() { for pr := range retChan { runtime.EventsEmit(s.ctx, "webFingerScan", pr) @@ -315,7 +303,7 @@ func (s *FingerScanner) NewActiveFingerScan(rootPath bool) { s.basicURLWithFingerprint[fp.URL.String()] = append(s.basicURLWithFingerprint[fp.URL.String()], result...) s.mutex.Unlock() - retChan <- InfoResult{ + retChan <- structs.InfoResult{ URL: fullURL, StatusCode: ti.StatusCode, Length: ti.ContentLength, diff --git a/database.go b/database.go index ad7811a1..76d0f15a 100644 --- a/database.go +++ b/database.go @@ -3,11 +3,13 @@ package main import ( "context" "database/sql" + "encoding/json" "fmt" "os" "slack-wails/core/portscan" - "slack-wails/core/webscan" + "slack-wails/lib/fileutil" "slack-wails/lib/gologger" + "slack-wails/lib/report" "slack-wails/lib/structs" "slack-wails/lib/util" "strings" @@ -820,16 +822,21 @@ func (d *Database) DeleteScanTask(taskid string) bool { return isSuccess } -func (d *Database) SelectFingerscanResult(taskid string) []webscan.InfoResult { +func (d *Database) RenameScanTask(taskid, taskname string) bool { + updateStmt := "UPDATE scanTask SET task_name = ? WHERE task_id = ?" + return d.ExecSqlStatement(updateStmt, taskname, taskid) +} + +func (d *Database) SelectFingerscanResult(taskid string) []structs.InfoResult { rows, err := d.DB.Query("SELECT * FROM FingerprintInfo WHERE task_id = ?;", taskid) if err != nil { gologger.Debug(d.ctx, err) - return []webscan.InfoResult{} + return []structs.InfoResult{} } defer rows.Close() - var results []webscan.InfoResult + var results []structs.InfoResult for rows.Next() { - var result webscan.InfoResult + var result structs.InfoResult var fingerprintsStr string var task_id string 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 { return results } -func (d *Database) SelectPocscanResult(taskid string) []webscan.VulnerabilityInfo { +func (d *Database) SelectPocscanResult(taskid string) []structs.VulnerabilityInfo { rows, err := d.DB.Query("SELECT * FROM VulnerabilityInfo WHERE task_id = ?", taskid) if err != nil { - return []webscan.VulnerabilityInfo{} + return []structs.VulnerabilityInfo{} } defer rows.Close() - var results []webscan.VulnerabilityInfo + var results []structs.VulnerabilityInfo for rows.Next() { - var result webscan.VulnerabilityInfo + var result structs.VulnerabilityInfo var task_id string 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) if err != nil { @@ -871,12 +878,12 @@ func (d *Database) SelectPocscanResult(taskid string) []webscan.VulnerabilityInf return results } -func (d *Database) InsertFingerscanResult(taskid string, result webscan.InfoResult) bool { +func (d *Database) InsertFingerscanResult(taskid string, result structs.InfoResult) bool { insertStmt := "INSERT INTO FingerprintInfo (task_id, url, status, length, title, detect, is_waf, waf, fingerprints, screenshot) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" 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) } -func (d *Database) InsertPocscanResult(taskid string, result webscan.VulnerabilityInfo) bool { +func (d *Database) InsertPocscanResult(taskid string, result structs.VulnerabilityInfo) bool { insertStmt := "INSERT INTO VulnerabilityInfo (task_id, template_id, vuln_name, protocol, severity, vuln_url, extract, request, response, description, reference) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" 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) } @@ -885,3 +892,29 @@ func (d *Database) DeletePocscanResult(taskid, template_id, vuln_url string) boo deleteStmt := "DELETE FROM VulnerabilityInfo WHERE task_id = ? AND template_id = ? AND vuln_url = ?" return d.ExecSqlStatement(deleteStmt, taskid, template_id, vuln_url) } + +func (d *Database) ExportWebReportWithJson(reportpath string, task structs.TaskResult) bool { + fingerprintsResult := d.SelectFingerscanResult(task.TaskId) + pocsResult := d.SelectPocscanResult(task.TaskId) + result := structs.WebReport{ + Targets: task.Targets, + Fingerprints: fingerprintsResult, + POCs: pocsResult, + } + return fileutil.SaveJsonWithFormat(d.ctx, reportpath, result) +} + +func (d *Database) ReadWebReportWithJson(reportpath string) (result structs.WebReport, err error) { + data, err := os.ReadFile(reportpath) + if err != nil { + return + } + err = json.Unmarshal(data, &result) + return +} + +func (d *Database) ExportWebReportWithHtml(reportpath, taskid string) bool { + fingerprintsResult := d.SelectFingerscanResult(taskid) + pocsResult := d.SelectPocscanResult(taskid) + return os.WriteFile(reportpath, []byte(report.GenerateReport(fingerprintsResult, pocsResult)), 0644) == nil +} diff --git a/file.go b/file.go index 5535d5e8..60d52021 100644 --- a/file.go +++ b/file.go @@ -11,6 +11,7 @@ import ( "os/exec" "path/filepath" rt "runtime" + "slack-wails/lib/fileutil" "slack-wails/lib/gologger" "slack-wails/lib/structs" "slack-wails/lib/update" @@ -101,7 +102,7 @@ func (f *File) DirectoryDialog() string { } // selection会返回保存的文件路径+文件名 例如/Users/xxx/Downloads/test.xlsx -func (f *File) SaveFile(filename string) string { +func (f *File) SaveFileDialog(filename string) string { selection, err := runtime.SaveFileDialog(f.ctx, runtime.SaveDialogOptions{ Title: "保存文件", DefaultFilename: filename, @@ -227,7 +228,7 @@ func (f *File) UpdatePocFile(version string) bool { gologger.Error(f.ctx, err) return false } - uz := util.NewUnzip() + uz := fileutil.NewUnzip() if _, err := uz.Extract(defaultFile+"config.zip", defaultFile); err != nil { gologger.Error(f.ctx, err) return false @@ -302,7 +303,7 @@ func (a *App) DownloadCyberChef(url string) error { return err } runtime.EventsEmit(a.ctx, "downloadComplete", fileName) - uz := util.NewUnzip() + uz := fileutil.NewUnzip() if _, err := uz.Extract(util.HomeDir()+cyber, a.defaultPath); err != nil { return err } @@ -454,7 +455,7 @@ func (f *File) GetLocalNaConfig() *[]structs.Navigation { func (f *File) InsetGroupNavigation(n structs.Navigation) bool { navigation = append(navigation, n) - return f.SaveJsonFile(navigation) + return fileutil.SaveJsonWithFormat(f.ctx, na, navigation) } func (f *File) InsetItemNavigation(groupName string, child structs.Children) bool { @@ -463,25 +464,12 @@ func (f *File) InsetItemNavigation(groupName string, child structs.Children) boo navigation[i].Children = append(n.Children, child) } } - return f.SaveJsonFile(navigation) + return fileutil.SaveJsonWithFormat(f.ctx, na, navigation) } func (f *File) SaveNavigation(n []structs.Navigation) bool { navigation = n - return f.SaveJsonFile(navigation) -} - -func (f *File) SaveJsonFile(content interface{}) bool { - b, err := json.MarshalIndent(content, "", " ") - if err != nil { - gologger.Error(f.ctx, err) - return false - } - if err := os.WriteFile(na, b, 0777); err != nil { - gologger.Error(f.ctx, err) - return false - } - return true + return fileutil.SaveJsonWithFormat(f.ctx, na, navigation) } func (f *File) OpenFolder(filepath string) string { diff --git a/frontend/src/assets/icon/textwrap.svg b/frontend/src/assets/icon/textwrap.svg deleted file mode 100644 index 9ff51540..00000000 --- a/frontend/src/assets/icon/textwrap.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/export.ts b/frontend/src/export.ts index 1628ca55..67ae1c78 100644 --- a/frontend/src/export.ts +++ b/frontend/src/export.ts @@ -1,6 +1,6 @@ import * as XLSX from "xlsx"; import { ElNotification } from "element-plus"; -import { WriteFile, SaveFile } from "wailsjs/go/main/File"; +import { WriteFile, SaveFileDialog } from "wailsjs/go/main/File"; // 单sheet导出 export async function ExportToXlsx( headers: string[], @@ -66,7 +66,7 @@ export async function ExportFile( filename: string, content: string ) { - const path = await SaveFile(filename); + const path = await SaveFileDialog(filename); if (!path) { return; } diff --git a/frontend/src/stores/interface.ts b/frontend/src/stores/interface.ts index f7bc1de0..cd8c852e 100644 --- a/frontend/src/stores/interface.ts +++ b/frontend/src/stores/interface.ts @@ -72,28 +72,6 @@ export interface HunterEntryTips { tags: string[]; } -export interface CompanyInfo { - CompanyName?: string; - Holding?: string; - Investment?: string; - RegStatus?: string; - Domains?: string[]; -} - -export interface WechatInfo { - CompanyName?: string; - WechatName?: string; - WechatNums?: string; - Logo?: string; - Qrcode?: string; - Introduction?: string; -} - -export interface QuakeTipsResult { - Code?: number; - Message?: string; - Data?: QuakeTipsData[]; -} export interface QuakeTipsData { Product_name: string; diff --git a/frontend/src/stores/options.ts b/frontend/src/stores/options.ts index 4133343e..23c1d393 100644 --- a/frontend/src/stores/options.ts +++ b/frontend/src/stores/options.ts @@ -33,6 +33,8 @@ export const webscanOptions = [ }, ] +export const webReportOptions = ["HTML", "JSON", "EXCEL"] + export const portscanOptions = [ { label: "SYN", diff --git a/frontend/src/views/AppStarter.vue b/frontend/src/views/AppStarter.vue index ee2926ae..4ee2a746 100644 --- a/frontend/src/views/AppStarter.vue +++ b/frontend/src/views/AppStarter.vue @@ -139,10 +139,10 @@ const localGroup = ({ deleteGroup: function (name: string) { ElMessageBox.confirm( '确定删除该分组?', - 'Warning', + '警告', { - confirmButtonText: 'OK', - cancelButtonText: 'Cancel', + confirmButtonText: '确认', + cancelButtonText: '取消', type: 'warning', } ) diff --git a/frontend/src/views/Asset/Company.vue b/frontend/src/views/Asset/Company.vue index c32c952c..b308a73b 100644 --- a/frontend/src/views/Asset/Company.vue +++ b/frontend/src/views/Asset/Company.vue @@ -4,9 +4,8 @@ import { QuestionFilled, Plus, ChromeFilled } from '@element-plus/icons-vue'; import { ElMessage } from 'element-plus' import { WechatOfficial, SubsidiariesAndDomains, InitTycHeader, Callgologger, TycCheckLogin } from "wailsjs/go/main/App"; import { ExportAssetToXlsx } from '@/export' -import { CompanyInfo, WechatInfo } from "@/stores/interface"; import usePagination from "@/usePagination"; -import { transformArrayFields } from "@/util"; +import { Copy, transformArrayFields } from "@/util"; import exportIcon from '@/assets/icon/doucment-export.svg' import global from "@/global"; import { LinkSubdomain } from "@/linkage"; @@ -15,6 +14,7 @@ import CustomTabs from "@/components/CustomTabs.vue"; import wechatIcon from "@/assets/icon/wechat.svg" import { debounce } from "lodash" import { BrowserOpenURL } from "wailsjs/runtime/runtime"; +import { structs } from "wailsjs/go/models"; const throttleUpdate = throttle(() => { pc.table.pageContent = pc.ctrl.watchResultChange(pc.table); @@ -39,13 +39,11 @@ const from = reactive({ token: '', activeName: 'subcompany', runningStatus: false, - companyData: [] as CompanyInfo[], - wehcatData: [] as WechatInfo[], machineStr: '' }) -let pc = usePagination(20) // paginationCompany -let pw = usePagination(20) // paginationWehcat +let pc = usePagination(20) // paginationCompany +let pw = usePagination(20) // paginationWehcat async function Collect() { if (from.company == "") { @@ -85,7 +83,7 @@ async function Collect() { const promises = companys.map(async companyName => { Callgologger("info", `正在收集${companyName}的子公司信息`) if (typeof companyName === 'string') { - const result: CompanyInfo[] = await SubsidiariesAndDomains(companyName, from.subcompanyLevel, from.defaultHold, from.domain, from.machineStr); + const result = await SubsidiariesAndDomains(companyName, from.subcompanyLevel, from.defaultHold, from.domain, from.machineStr); if (result.length > 0) { pc.table.result.push(...result) throttleUpdate() @@ -107,7 +105,7 @@ async function Collect() { const promises2 = allCompany.map(async companyName => { Callgologger("info", `正在收集${companyName}的微信公众号资产`) if (typeof companyName === 'string') { - const result: WechatInfo[] = await WechatOfficial(companyName); + const result = await WechatOfficial(companyName); if (Array.isArray(result) && result.length > 0) { pw.table.result.push(...result); pw.table.pageContent = pw.ctrl.watchResultChange(pw.table) @@ -133,6 +131,16 @@ const debouncedInput = debounce(() => { // 2秒后将数据存储到localStorage localStorage.setItem('tyc-token', from.token); }, 2000); + +function copyAllDomains() { + let allDomains = []; + pc.table.result.forEach(item => { + if (item.Domains.length > 0) { + allDomains.push(...item.Domains); + } + }); + Copy(allDomains.join('\n')) +} @@ -208,7 +216,13 @@ const debouncedInput = debounce(() => { }} - + + - - 更多功能 - - - - - + + 更多功能 + + + + + 新建任务 @@ -364,8 +364,19 @@ function stopShodan() { - - + + + +