From 06aa81bb2559e4ccc630ace81d107e502ee5b9ee Mon Sep 17 00:00:00 2001 From: yhy <31311038+yhy0@users.noreply.github.com> Date: Fri, 5 Jan 2024 20:00:06 +0800 Subject: [PATCH] =?UTF-8?q?[fix]=20=E4=BF=AE=E5=A4=8D=20web=20=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E4=BF=AE=E6=94=B9=E6=8F=92=E4=BB=B6=E4=B8=8D=E7=94=9F?= =?UTF-8?q?=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jie_config.yaml | 4 +- README.md | 2 +- SCopilot/templates/config.html | 2 + SCopilot/web.go | 190 ++++++++++++++++----------------- conf/banner.go | 2 +- conf/default.go | 37 +++---- conf/file.go | 96 +++++++++-------- 7 files changed, 174 insertions(+), 159 deletions(-) diff --git a/Jie_config.yaml b/Jie_config.yaml index 4924526..4599d95 100644 --- a/Jie_config.yaml +++ b/Jie_config.yaml @@ -1,4 +1,4 @@ -version: 1.0.0 +version: 1.0.1 parallel: 10 #同时运行几个插件 @@ -124,7 +124,7 @@ mitmproxy: - # 排除的后缀, 不会被扫描器扫描 按格式增加 filterSuffix: .3g2, .3gp, .7z, .apk, .arj, .avi, .axd, .bmp, .csv, .deb, .dll, .doc, .drv, .eot, .exe, .flv, .gif, .gifv, .gz, .h264, .ico, .iso, .jar, .jpeg, .jpg, .lock, .m4a, .m4v, .map, .mkv, .mov, .mp3, .mp4, .mpeg, .mpg, .msi, .ogg, .ogm, .ogv, .otf, .pdf, .pkg, .png, .ppt, .psd, .rar, .rm, .rpm, .svg, .swf, .sys, .tar.gz, .tar, .tif, .tiff, .ttf, .txt, .vob, .wav, .webm, .webp, .wmv, .woff, .woff2, .xcf, .xls, .xlsx, .zip - maxLength: 3000 # 这个还没有实现,我没有使用队列. 队列长度限制, 也可以理解为最大允许多少等待扫描的请求, 请根据内存大小自行调整 + maxLength: 3000 # 队列长度限制, 也可以理解为最大允许多少等待扫描的请求, 请根据内存大小自行调整,这个还没有实现,我没有使用队列 # 信息收集类的正则 collection: diff --git a/README.md b/README.md index 89bb5c8..1745d23 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Release - Release + Release GitHub Repo stars diff --git a/SCopilot/templates/config.html b/SCopilot/templates/config.html index c3353d1..f0db00d 100644 --- a/SCopilot/templates/config.html +++ b/SCopilot/templates/config.html @@ -61,6 +61,8 @@

Security Copilot Report - Jie

配置

+
web 页面修改并不会同步到配置文件(不影响生效,但如果修改配置文件后,则会以修改的配置文件为准)
+
diff --git a/SCopilot/web.go b/SCopilot/web.go index 96ab240..4d177ad 100644 --- a/SCopilot/web.go +++ b/SCopilot/web.go @@ -12,6 +12,7 @@ import ( "html/template" "net/http" "runtime" + "strings" "time" ) @@ -41,7 +42,7 @@ func handleWebSocket(c *gin.Context) { return } defer conn.Close() - + // 数据更改 for { select { @@ -76,45 +77,45 @@ func Init() { logging.Logger.Infoln("Start SCopilot web service at :" + conf.GlobalConfig.Passive.WebPort) gin.SetMode("release") router := gin.Default() - + // 设置模板资源 router.SetHTMLTemplate(template.Must(template.New("").ParseFS(templates, "templates/*"))) - + router.GET("/ws", handleWebSocket) - + // basic 认证 authorized := router.Group("/", gin.BasicAuth(gin.Accounts{ conf.GlobalConfig.Passive.WebUser: conf.GlobalConfig.Passive.WebPass, })) - + if conf.GlobalConfig.Debug { runtime.SetBlockProfileRate(1) // 开启对阻塞操作的跟踪,block runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪,mutex - + pprof.RouteRegister(authorized, "pprof") } - + authorized.GET("/", func(c *gin.Context) { c.Redirect(302, "/index") }) - + authorized.GET("/index", func(c *gin.Context) { c.HTML(http.StatusOK, "index.html", gin.H{ "list": output.SCopilotLists, "year": time.Now().Year(), }) }) - + authorized.GET("/SCopilot", func(c *gin.Context) { host := c.Query("host") - + c.HTML(http.StatusOK, "SCopilot.html", gin.H{ "data": output.SCopilotMessage[host], "ipInfo": output.IPInfoList[output.SCopilotMessage[host].HostNoPort], "year": time.Now().Year(), }) }) - + authorized.GET("/config", func(c *gin.Context) { c.HTML(http.StatusOK, "config.html", gin.H{ "plugins": conf.Plugin, @@ -125,103 +126,102 @@ func Init() { "year": time.Now().Year(), }) }) - - // authorized.POST("/config", func(c *gin.Context) { - // plugins := c.PostForm("plugin") - // include := c.PostForm("include") - // exclude := c.PostForm("exclude") - // filterSuffix := c.PostForm("filterSuffix") - // - // if plugins != "" { - // // 先全部关闭,再根据配置开启对应的,防止配置文件中删除了某个插件,但是程序中还在运行 - // for k := range conf.Plugin { - // conf.Plugin[k] = false - // } - // for _, plugin := range strings.Split(plugins, ",") { - // if plugin != "" { - // conf.DefaultPlugins[plugin] = true - // mitmproxy.Conf.Plugins = append(mitmproxy.Conf.Plugins, plugin) - // } - // } - // viper.Set("Plugins", mitmproxy.Conf.Plugins) - // } - // - // if include != "" { - // include = strings.TrimLeft(include, "[") - // include = strings.TrimRight(include, "]") - // mitmproxy.Conf.Include = strings.Split(include, " ") - // viper.Set("Include", mitmproxy.Conf.Include) - // } - // - // if exclude != "" { - // exclude = strings.TrimLeft(exclude, "[") - // exclude = strings.TrimRight(exclude, "]") - // mitmproxy.Conf.Exclude = strings.Split(exclude, " ") - // viper.Set("Exclude", mitmproxy.Conf.Exclude) - // } - // - // if filterSuffix != "" { - // filterSuffix = strings.TrimLeft(filterSuffix, "[") - // filterSuffix = strings.TrimRight(filterSuffix, "]") - // mitmproxy.Conf.FilterSuffix = strings.Split(filterSuffix, " ") - // viper.Set("FilterSuffix", mitmproxy.Conf.FilterSuffix) - // } - // - // sqlmap := c.PostForm("sqlmap-switch") - // sqlmap_api := c.PostForm("sqlmap_api") - // username := c.PostForm("username") - // password := c.PostForm("password") - // - // if sqlmap == "on" { - // conf.DefaultPlugins["sqlmap"] = true - // conf.GlobalConfig.SqlmapApi = conf.Sqlmap{ - // On: true, - // Url: sqlmap_api, - // Username: username, - // Password: password, - // } - // } else { - // conf.DefaultPlugins["sqlmap"] = false - // conf.GlobalConfig.SqlmapApi = conf.Sqlmap{ - // On: false, - // Url: sqlmap_api, - // Username: username, - // Password: password, - // } - // } - // - // // 写文件 - // err := viper.WriteConfigAs(mitmproxy.ConfigFile) - // if err != nil { - // logging.Logger.Errorln("fail to write 'SCopilot.yaml': %v", err) - // } - // - // c.HTML(http.StatusOK, "config.html", gin.H{ - // "config": conf.DefaultPlugins, - // "include": mitmproxy.Conf.Include, - // "exclude": mitmproxy.Conf.Exclude, - // "filterSuffix": mitmproxy.Conf.FilterSuffix, - // "sqlmap": conf.GlobalConfig.SqlmapApi, - // "year": time.Now().Year(), - // }) - // }) - + + authorized.POST("/config", func(c *gin.Context) { + plugins := c.PostForm("plugin") + include := c.PostForm("include") + exclude := c.PostForm("exclude") + filterSuffix := c.PostForm("filterSuffix") + + if plugins != "" { + // 先全部关闭,再根据配置开启对应的,防止配置文件中关闭了某个插件,但是程序中还在运行 + for k := range conf.Plugin { + conf.Plugin[k] = false + } + for _, plugin := range strings.Split(plugins, ",") { + if plugin != "" { + conf.Plugin[plugin] = true + } + } + // viper.Set("Plugins", mitmproxy.Conf.Plugins) + } + + if include != "" { + include = strings.TrimLeft(include, "[") + include = strings.TrimRight(include, "]") + conf.GlobalConfig.Mitmproxy.Include = strings.Split(include, " ") + // viper.Set("Include", mitmproxy.Conf.Include) + } + + if exclude != "" { + exclude = strings.TrimLeft(exclude, "[") + exclude = strings.TrimRight(exclude, "]") + conf.GlobalConfig.Mitmproxy.Exclude = strings.Split(exclude, " ") + // viper.Set("Exclude", mitmproxy.Conf.Exclude) + } + + if filterSuffix != "" { + filterSuffix = strings.TrimLeft(filterSuffix, "[") + filterSuffix = strings.TrimRight(filterSuffix, "]") + conf.GlobalConfig.Mitmproxy.FilterSuffix = filterSuffix + // viper.Set("FilterSuffix", mitmproxy.Conf.FilterSuffix) + } + + sqlmap := c.PostForm("sqlmap-switch") + sqlmapApi := c.PostForm("sqlmap_api") + username := c.PostForm("username") + password := c.PostForm("password") + + if sqlmap == "on" { + conf.Plugin["sqlmap"] = true + conf.GlobalConfig.SqlmapApi = conf.Sqlmap{ + Enabled: true, + Url: sqlmapApi, + Username: username, + Password: password, + } + } else { + conf.Plugin["sqlmap"] = false + conf.GlobalConfig.SqlmapApi = conf.Sqlmap{ + Enabled: false, + Url: sqlmapApi, + Username: username, + Password: password, + } + } + + // 写文件 + // err := viper.WriteConfigAs(mitmproxy.ConfigFile) + // if err != nil { + // logging.Logger.Errorln("fail to write 'SCopilot.yaml': %v", err) + // } + + c.HTML(http.StatusOK, "config.html", gin.H{ + "config": conf.Plugin, + "include": conf.GlobalConfig.Mitmproxy.Include, + "exclude": conf.GlobalConfig.Mitmproxy.Exclude, + "filterSuffix": conf.GlobalConfig.Mitmproxy.FilterSuffix, + "sqlmap": conf.GlobalConfig.SqlmapApi, + "year": time.Now().Year(), + }) + }) + authorized.GET("/clear", func(c *gin.Context) { output.SCopilotLists = nil output.SCopilotMessage = make(map[string]*output.SCopilotData) output.IPInfoList = make(map[string]*output.IPInfo) - + c.HTML(http.StatusOK, "index.html", gin.H{ "list": output.SCopilotLists, "year": time.Now().Year(), }) }) - + authorized.GET("/about", func(c *gin.Context) { c.HTML(http.StatusOK, "about.html", gin.H{ "year": time.Now().Year(), }) }) - + router.Run(":" + conf.GlobalConfig.Passive.WebPort) } diff --git a/conf/banner.go b/conf/banner.go index 3c3581d..2c722a2 100644 --- a/conf/banner.go +++ b/conf/banner.go @@ -17,4 +17,4 @@ var Banner = ` const Website = "https://github.com/yhy0/Jie" -const Version = "1.0.1" +const Version = "1.0.2" diff --git a/conf/default.go b/conf/default.go index 0216b85..1365f3d 100644 --- a/conf/default.go +++ b/conf/default.go @@ -9,24 +9,25 @@ package conf var ( // Plugin 插件单独从配置文件中读取出来,方便使用 Plugin = map[string]bool{ - "xss": false, - "sql": false, - "sqlmap": false, - "cmd": false, - "xxe": false, - "ssrf": false, - "brute": false, // web 类登录爆破 - "hydra": false, // mysql、redis类服务爆破 - "bypass403": false, - "jsonp": false, - "crlf": false, - "log4j": false, - "fastjson": false, - "portScan": false, - "poc": false, - "nuclei": false, - "bbscan": false, - "archive": false, + "xss": false, + "sql": false, + "sqlmap": false, + "cmd": false, + "xxe": false, + "ssrf": false, + "brute": false, // web 类登录爆破 + "hydra": false, // mysql、redis类服务爆破 + "bypass403": false, + "jsonp": false, + "crlf": false, + "log4j": false, + "fastjson": false, + "portScan": false, + "poc": false, + "nuclei": false, + "bbscan": false, + "archive": false, + "nginx-alias-traversal": false, } ) diff --git a/conf/file.go b/conf/file.go index 05a2e95..57aa4e2 100644 --- a/conf/file.go +++ b/conf/file.go @@ -179,7 +179,7 @@ collection: func HotConf() { viper.SetConfigType("yaml") viper.SetConfigFile(ConfigFile) - + // watch 监控配置文件变化 viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { @@ -193,7 +193,7 @@ func HotConf() { func Init() { // 配置文件路径 当前文件夹 + SCopilot.yaml ConfigFile = path.Join("./" + FileName) - + // 检测配置文件是否存在 if !util.Exists(ConfigFile) { err := WriteYamlConfig() @@ -205,9 +205,9 @@ func Init() { } else { logging.Logger.Infoln("Load profile ", ConfigFile) } - + ReadYamlConfig() - + HotConf() } @@ -220,13 +220,13 @@ func WriteYamlConfig() error { panic(err) } } - + // 写入默认配置文件 err := ioutil.WriteFile(FileName, defaultConfigYaml, 0644) if err != nil { logging.Logger.Fatalf("创建默认配置文件失败: %s", err) } - + return nil } @@ -234,13 +234,13 @@ func WriteYamlConfig() error { func ReadYamlConfig() { viper.SetConfigType("yaml") viper.SetConfigFile(ConfigFile) - + err := viper.ReadInConfig() if err != nil { logging.Logger.Fatalf("Fail to read %s: %+v", ConfigFile, err) } err = viper.Unmarshal(&GlobalConfig) - + if err != nil { logging.Logger.Fatalf("Fail to parse '%s', check format: %+v", ConfigFile, err) } @@ -253,69 +253,81 @@ func ReadPlugin() { for k := range Plugin { Plugin[k] = false } - - if GlobalConfig.Plugins.BruteForce.Web { - Plugin["brute"] = true - } - if GlobalConfig.Plugins.BruteForce.Service { - Plugin["hydra"] = true - } - if GlobalConfig.Plugins.CmdInjection.Enabled { - Plugin["cmd"] = true - } - - if GlobalConfig.Plugins.CrlfInjection.Enabled { - Plugin["crlf"] = true - } - + if GlobalConfig.Plugins.XSS.Enabled { Plugin["xss"] = true } - + if GlobalConfig.Plugins.Sql.Enabled { Plugin["sql"] = true } - + if GlobalConfig.Plugins.SqlmapApi.Enabled { Plugin["sqlmap"] = true } + + if GlobalConfig.Plugins.CmdInjection.Enabled { + Plugin["cmd"] = true + } + if GlobalConfig.Plugins.XXE.Enabled { Plugin["xxe"] = true } - + if GlobalConfig.Plugins.SSRF.Enabled { Plugin["ssrf"] = true } - - if GlobalConfig.Plugins.BBscan.Enabled { - Plugin["bbscan"] = true + + if GlobalConfig.Plugins.BruteForce.Web { + Plugin["brute"] = true } - - if GlobalConfig.Plugins.Jsonp.Enabled { - Plugin["jsonp"] = true + + if GlobalConfig.Plugins.BruteForce.Service { + Plugin["hydra"] = true } - + if GlobalConfig.Plugins.ByPass403.Enabled { Plugin["bypass403"] = true } - + + if GlobalConfig.Plugins.Jsonp.Enabled { + Plugin["jsonp"] = true + } + + if GlobalConfig.Plugins.CrlfInjection.Enabled { + Plugin["crlf"] = true + } + + if GlobalConfig.Plugins.Log4j.Enabled { + Plugin["log4j"] = true + } + if GlobalConfig.Plugins.Fastjson.Enabled { Plugin["fastjson"] = true } - - if GlobalConfig.Plugins.NginxAliasTraversal.Enabled { - Plugin["nginx-alias-traversal"] = true + + if GlobalConfig.Plugins.PortScan.Enabled { + Plugin["portScan"] = true } - + if GlobalConfig.Plugins.Poc.Enabled { Plugin["poc"] = true } - + if GlobalConfig.Plugins.Nuclei.Enabled { Plugin["nuclei"] = true } - - if GlobalConfig.Plugins.PortScan.Enabled { - Plugin["portScan"] = true + + if GlobalConfig.Plugins.BBscan.Enabled { + Plugin["bbscan"] = true + } + + if GlobalConfig.Plugins.Archive.Enabled { + Plugin["archive"] = true + } + + if GlobalConfig.Plugins.NginxAliasTraversal.Enabled { + Plugin["nginx-alias-traversal"] = true } + }