diff --git a/.gitignore b/.gitignore index 707cbb1..e14d9ba 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .idea logs data +scan/bbscan/rules/personal_rules.txt .DS_Store test.go # Test binary, built with `go test -c` diff --git a/Jie_config.yaml b/Jie_config.yaml index f684f08..4d5892d 100644 --- a/Jie_config.yaml +++ b/Jie_config.yaml @@ -1,6 +1,6 @@ version: 1.0.4 -parallel: 10 #同时运行几个插件 +parallel: 10 # 同时扫描的最大 url 个数 # 全局 http 发包配置 http: diff --git a/README.md b/README.md index 3622957..2001996 100644 --- a/README.md +++ b/README.md @@ -235,6 +235,7 @@ import ( "github.com/yhy0/Jie/SCopilot" "github.com/yhy0/Jie/conf" "github.com/yhy0/Jie/crawler" + "github.com/yhy0/Jie/pkg/mode" "github.com/yhy0/Jie/pkg/output" "github.com/yhy0/logging" "net/url" @@ -306,6 +307,7 @@ Config.WebScan.Craw = "k" logging.Logger.Infoln(aurora.Red(v.PrintScreen()).String()) } }() + mode.Active("http://testphp.vulnweb.com/", nil) } ``` diff --git a/README_CN.md b/README_CN.md index 058af77..c17d83b 100644 --- a/README_CN.md +++ b/README_CN.md @@ -233,6 +233,7 @@ import ( "github.com/yhy0/Jie/SCopilot" "github.com/yhy0/Jie/conf" "github.com/yhy0/Jie/crawler" + "github.com/yhy0/Jie/pkg/mode" "github.com/yhy0/Jie/pkg/output" "github.com/yhy0/logging" "net/url" @@ -302,6 +303,8 @@ func lib() { logging.Logger.Infoln(aurora.Red(v.PrintScreen()).String()) } }() + + mode.Active("http://testphp.vulnweb.com/", nil) } ``` diff --git a/SCopilot/templates/SCopilot.html b/SCopilot/templates/SCopilot.html index 3ac4245..3a6d02c 100644 --- a/SCopilot/templates/SCopilot.html +++ b/SCopilot/templates/SCopilot.html @@ -161,9 +161,19 @@ <h4 class="card-title">端口信息</h4> </ul> <div class="p-3 tab-content" id="myTabContent"> <div class="tab-pane fade show active" id="contact-tab-pane" role="tabpanel" aria-labelledby="contact-tab" tabindex="0"> + {{ if .data.InfoPlugin }} + <div class="card border-primary mb-3"> + <div class="card-body"> + {{ range $plugin, $cnt := .data.InfoPlugin }} + <button id="msgPluginData" type="button" class="btn btn-outline-success btn-sm" data-plugin="{{ $plugin }}">{{ $plugin }}<span class="badge badge text-danger" style="font-size: 14px">{{ $cnt }}</span></button> + {{ end }} + </div> + </div> + {{ end }} + <ul class="list-group position-relative"> {{ range $index, $info := .data.InfoMsg }} - <li class="list-group-item "> + <li class="list-group-item msg-plugin-ul" data-plugin="{{ $info.Plugin }}"> {{ $info.Url }} <span class="badge rounded-pill bg-primary"> {{ $info.Plugin }}</span> {{ if $info.Result }}<p><span class="badge bg-warning">{{ $info.Result }}</span></p>{{ end }} @@ -198,16 +208,26 @@ <h4 class="card-title">端口信息</h4> </div> <div class="tab-pane fade" id="vuln-tab-pane" role="tabpanel" aria-labelledby="vuln-tab" tabindex="0"> + {{ if .data.InfoPlugin }} + <div class="card border-primary mb-3"> + <div class="card-body"> + {{ range $plugin, $cnt := .data.VulPlugin }} + <button id="vulPluginData" type="button" class="btn btn-outline-success btn-sm" data-plugin="{{ $plugin }}">{{ $plugin }}<span class="badge badge text-danger" style="font-size: 14px">{{ $cnt }}</span></button> + {{ end }} + </div> + </div> + {{ end }} + <ul class="list-group"> {{ range $index, $message := .data.VulMessage }} - <li class="list-group-item"> + <li class="list-group-item vul-plugin-ul" data-plugin="{{ $message.Plugin }}"> <div class="vuln-card mb-3 {{ $message.Level }}"> <div class="d-flex justify-content-between align-items-center"> <h4 class="level mb-0"> {{ if $message.VulnData.VulnType }} {{ $message.VulnData.VulnType }} - {{ end }}{{ $message.VulnData.Target }} </h4> - <span class="toggle-switch btn btn-primary">Toggle Details</span> </div> + <span class="toggle-switch btn btn-primary btn-sm">Toggle Details</span> <p class="level">{{ $message.Level }} <span class="badge rounded-pill bg-danger"> {{ $message.Plugin }}</span></p> {{ if $message.VulnData.Ip }}<p>IP: {{ $message.VulnData.Ip }}</p>{{ end }} {{ if $message.VulnData.CreateTime }}<p>Create Time: {{ $message.VulnData.CreateTime }}</p>{{ end }} @@ -424,13 +444,77 @@ <h4 class="level mb-0"> </script> <script> document.addEventListener("DOMContentLoaded", function () { - var toggleSwitches = document.querySelectorAll(".toggle-switch"); + const toggleSwitches = document.querySelectorAll(".toggle-switch"); toggleSwitches.forEach(function (toggleSwitch) { toggleSwitch.addEventListener("click", function () { - var vulnDetails = this.closest(".vuln-card").querySelector(".vuln-details"); + const vulnDetails = this.closest(".vuln-card").querySelector(".vuln-details"); vulnDetails.classList.toggle("show"); }); }); + + const msgs = document.querySelectorAll("#msgPluginData"); + msgs.forEach(function(button) { + button.addEventListener("click", function() { + const pluginName = button.getAttribute("data-plugin"); // 获取按钮上的 data-plugin 属性值 + // 获取所有的 ul + const allUls = document.querySelectorAll(".msg-plugin-ul"); + + // 判断是否已经显示了所有 ul + const isAllDisplayed = Array.from(allUls).every(function(ul) { + return ul.style.display === ""; // 检查是否所有 ul 都是显示状态 + }); + + console.log(isAllDisplayed); + // 切换显示状态 + if (isAllDisplayed) { + // 如果所有 ul 都是显示状态,则只显示对应 plugin 的 ul + allUls.forEach(function(ul) { + if (ul.getAttribute("data-plugin") === pluginName) { + ul.style.display = ""; // 显示对应 plugin 的 ul + } else { + ul.style.display = "none"; // 隐藏其他不相关的 ul + } + }); + } else { + // 如果有 ul 是隐藏状态,则显示所有 + allUls.forEach(function(ul) { + ul.style.display = ""; + }); + } + }); + }); + + const vuls = document.querySelectorAll("#vulPluginData"); + vuls.forEach(function(button) { + button.addEventListener("click", function() { + const pluginName = button.getAttribute("data-plugin"); // 获取按钮上的 data-plugin 属性值 + // 获取所有的 ul + const allUls = document.querySelectorAll(".vul-plugin-ul"); + + // 判断是否已经显示了所有 ul + const isAllDisplayed = Array.from(allUls).every(function(ul) { + return ul.style.display === ""; // 检查是否所有 ul 都是显示状态 + }); + + console.log(isAllDisplayed); + // 切换显示状态 + if (isAllDisplayed) { + // 如果所有 ul 都是显示状态,则只显示对应 plugin 的 ul + allUls.forEach(function(ul) { + if (ul.getAttribute("data-plugin") === pluginName) { + ul.style.display = ""; // 显示对应 plugin 的 ul + } else { + ul.style.display = "none"; // 隐藏其他不相关的 ul + } + }); + } else { + // 如果有 ul 是隐藏状态,则显示所有 + allUls.forEach(function(ul) { + ul.style.display = ""; + }); + } + }); + }); }); </script> diff --git a/SCopilot/templates/index.html b/SCopilot/templates/index.html index 33eab22..9a828dc 100644 --- a/SCopilot/templates/index.html +++ b/SCopilot/templates/index.html @@ -187,7 +187,6 @@ <h1 class="modal-title fs-5" id="exampleModalLabel">清空所有数据</h1> const listItems = document.querySelectorAll('.list-item'); if (searchTerm.length > 0) { - console.log("11") listItems.forEach(function (item) { const itemText = item.textContent || item.innerText; console.log(itemText.toLowerCase(searchTerm.toLowerCase())) diff --git a/conf/default.go b/conf/default.go index 1f6a4bf..2725ad5 100644 --- a/conf/default.go +++ b/conf/default.go @@ -52,5 +52,5 @@ var DangerHeaders = []string{ "X-Api-Version", } -// Parallelism 同时 10 插件运行 +// Parallelism 对一个网站同时扫描的最大 url 个数 var Parallelism = 10 diff --git a/conf/file.go b/conf/file.go index 73d8736..fb8e0c3 100644 --- a/conf/file.go +++ b/conf/file.go @@ -20,7 +20,7 @@ var FileName = "Jie_config.yaml" var defaultConfigYaml = []byte(`version: ` + Version + ` -parallel: 10 #同时运行几个插件 +parallel: 10 # 同时扫描的最大 url 个数 # 全局 http 发包配置 http: diff --git a/go.mod b/go.mod index 8aa4ec6..6c3712e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/beevik/etree v1.3.0 github.com/buger/jsonparser v1.1.1 github.com/gin-gonic/gin v1.9.1 - github.com/go-rod/rod v0.114.8 // indirect + github.com/go-rod/rod v0.114.8 github.com/google/go-github v17.0.0+incompatible // indirect github.com/google/uuid v1.6.0 github.com/json-iterator/go v1.1.12 // indirect diff --git a/lib.go b/lib.go index 5b9e890..fa25485 100644 --- a/lib.go +++ b/lib.go @@ -5,6 +5,7 @@ import ( "github.com/yhy0/Jie/SCopilot" "github.com/yhy0/Jie/conf" "github.com/yhy0/Jie/crawler" + "github.com/yhy0/Jie/pkg/mode" "github.com/yhy0/Jie/pkg/output" "github.com/yhy0/logging" "net/url" @@ -76,4 +77,6 @@ func lib() { logging.Logger.Infoln(aurora.Red(v.PrintScreen()).String()) } }() + + mode.Active("http://testphp.vulnweb.com/", nil) } diff --git a/scan/bbscan/README.md b/scan/bbscan/README.md index e532aa1..3b74780 100644 --- a/scan/bbscan/README.md +++ b/scan/bbscan/README.md @@ -7,4 +7,5 @@ - type_no 返回包 Content-Type 格式不包括 - tag 返回包内容匹配 - root_only 只有主目录下才会存在该路径 -- fingprints 网站的指纹, 多种形式以 , 分割 表示或 \ No newline at end of file +- fingprints 网站的指纹, 多种形式以 , 分割 表示或 + diff --git a/scan/bbscan/bbscan.go b/scan/bbscan/bbscan.go index a7733a3..b92e154 100644 --- a/scan/bbscan/bbscan.go +++ b/scan/bbscan/bbscan.go @@ -270,7 +270,7 @@ func BBscan(u string, root bool, fingprints []string, header map[string]string, wg.Add(1) ch <- struct{}{} - go func(t string, r *Rule) { + go func(t string, _path string, r *Rule) { defer wg.Done() defer func() { <-ch }() <-time.After(time.Duration(100) * time.Millisecond) @@ -285,7 +285,7 @@ func BBscan(u string, root bool, fingprints []string, header map[string]string, } // 黑名单,跳过 - if scan_util.IsBlackHtml(res.Body, res.Header["Content-Type"]) { + if scan_util.IsBlackHtml(res.Body, res.Header["Content-Type"], _path) { return } @@ -377,7 +377,7 @@ func BBscan(u string, root bool, fingprints []string, header map[string]string, } } } - }(target, rule) + }(target, path, rule) } @@ -407,7 +407,7 @@ func SingleScan(targets []string, path string) { return } // 黑名单,跳过 - if scan_util.IsBlackHtml(res.Body, res.Header["Content-Type"]) { + if scan_util.IsBlackHtml(res.Body, res.Header["Content-Type"], path) { return } diff --git a/scan/bbscan/bbscan_test.go b/scan/bbscan/bbscan_test.go new file mode 100644 index 0000000..0d4e633 --- /dev/null +++ b/scan/bbscan/bbscan_test.go @@ -0,0 +1,16 @@ +package bbscan + +import ( + "fmt" + "testing" +) + +/** + @author yhy + @since 2024/4/26 + @desc //TODO +**/ + +func TestBBscan(t *testing.T) { + fmt.Println(Rules["/util/exec_sh?filePath=1"]) +} diff --git a/scan/bbscan/rules/go_pprof_debug.txt b/scan/bbscan/rules/go_pprof_debug.txt index 17fa13d..775c924 100644 --- a/scan/bbscan/rules/go_pprof_debug.txt +++ b/scan/bbscan/rules/go_pprof_debug.txt @@ -1,3 +1,3 @@ # add golang pprof -/debug/pprof/heap?debug=1 {status=200} {type="text/plain"} {tag="heap profile"} -/pprof/heap?debug=1 {status=200} {type="text/plain"} {tag="heap profile"} +/debug/pprof/goroutine?debug=1 {status=200} {type="text/plain"} {tag="goroutine profile"} +/pprof/goroutine?debug=1 {status=200} {type="text/plain"} {tag="goroutine profile"} diff --git a/scan/gadget/swagger/swagger.go b/scan/gadget/swagger/swagger.go index bf97a61..77dfe62 100644 --- a/scan/gadget/swagger/swagger.go +++ b/scan/gadget/swagger/swagger.go @@ -441,6 +441,10 @@ func scanApi(method, baseUrl, path, queryParams, bodyParams string, header map[s } func scanSwagger(method, target, bodyParams string, header map[string]string, client *httpx.Client) { + parse, err := url.Parse(target) + if err != nil { + return + } // util.HttpProxy = "http://127.0.0.1:8080" if strings.EqualFold(method, "get") { res, err := client.Request(target, "GET", "", header) @@ -448,9 +452,8 @@ func scanSwagger(method, target, bodyParams string, header map[string]string, cl logging.Logger.Errorf("scanApi(GET %s) err %v", target, err) return } - // 可能是未授权, 然后对 200 的进行ssrf、注入测试 - if res.StatusCode == 200 && !util2.IsBlackHtml(res.Body, res.Header["Content-Type"]) { + if res.StatusCode == 200 && !util2.IsBlackHtml(res.Body, res.Header["Content-Type"], parse.Path) { logging.Logger.Infof("Possibly unauthorized access: GET %s", target) in := &input.CrawlResult{ @@ -523,7 +526,7 @@ func scanSwagger(method, target, bodyParams string, header map[string]string, cl return } - if res.StatusCode == 200 && !util2.IsBlackHtml(res.Body, res.Header["Content-Type"]) { // 可能是未授权 + if res.StatusCode == 200 && !util2.IsBlackHtml(res.Body, res.Header["Content-Type"], parse.Path) { // 可能是未授权 payload := fmt.Sprintf("%s %s %s", method, target, bodyParams) logging.Logger.Infof("Possibly unauthorized access: %s", payload) diff --git a/scan/util/black.go b/scan/util/black.go index 7620ebf..5d78fa8 100644 --- a/scan/util/black.go +++ b/scan/util/black.go @@ -21,7 +21,7 @@ type BlackRule struct { Rule string } -func IsBlackHtml(str string, contentType []string) bool { +func IsBlackHtml(str string, contentType []string, uri string) bool { for _, rule := range BlackLists { if rule.Type == "text" { if util.Contains(str, rule.Rule) { @@ -40,10 +40,15 @@ func IsBlackHtml(str string, contentType []string) bool { } if len(str) < 250 && util.InSliceCaseFold("application/json", contentType) { - reg, _ := regexp.Compile(`(?i)("(status|code|statusCode)"(\s+)?:(\s+)?(400|401|404|502)|"(message|msg)"(\s+)?:(\s+)?.*?(not exist|not found|请求非法)|not found)`) + reg, _ := regexp.Compile(`(?i)("(status|code|statusCode)"(\s+)?:(\s+)?(1\d{2}|400|401|404|5\d{2})|"(message|msg)"(\s+)?:(\s+)?.*?(not exist|not found|请求非法|Not Authorized)|not found)`) if len(reg.FindStringSubmatch(str)) > 0 { return true } + + // {"code":500,"msg":"No handler found for GET /assets/.env","data":null} 类似这种也是没啥用的 + if strings.Contains(str, uri) { + return true + } } return false