From 7294051b4440b47a5307e93125cb946548326a87 Mon Sep 17 00:00:00 2001 From: shadow1ng Date: Thu, 22 Apr 2021 23:41:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9webtitle=E6=A8=A1=E5=9D=97,?= =?UTF-8?q?=E5=8A=A0=E5=85=A5gbk=E8=A7=A3=E7=A0=81,=E5=87=8F=E5=B0=91?= =?UTF-8?q?=E4=B9=B1=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Plugins/webtitle.go | 150 +++++++++++++++++++++++++++++++++++++------- README.md | 1 + WebScan/lib/http.go | 8 +-- go.mod | 1 + 4 files changed, 132 insertions(+), 28 deletions(-) diff --git a/Plugins/webtitle.go b/Plugins/webtitle.go index ada590f..bc61d95 100644 --- a/Plugins/webtitle.go +++ b/Plugins/webtitle.go @@ -1,16 +1,24 @@ package Plugins import ( + "bytes" "fmt" "github.com/shadow1ng/fscan/WebScan" "github.com/shadow1ng/fscan/WebScan/lib" "github.com/shadow1ng/fscan/common" + "golang.org/x/text/encoding/simplifiedchinese" + "golang.org/x/text/transform" "io/ioutil" "net/http" + "net/url" "regexp" "strings" ) +var ( + Charsets = []string{"utf-8", "gbk", "gb2312"} +) + func WebTitle(info *common.HostInfo) error { err := GOWebTitle(info) if err != nil { @@ -20,6 +28,11 @@ func WebTitle(info *common.HostInfo) error { return err } +//flag 1 first try +//flag 2 /favicon.ico +//flag 3 302 +//flag 4 400 -> https + func GOWebTitle(info *common.HostInfo) error { var CheckData []WebScan.CheckDatas if info.Url == "" { @@ -36,19 +49,42 @@ func GOWebTitle(info *common.HostInfo) error { } } - err, result, CheckData := geturl(info, true, CheckData) + err, result, CheckData := geturl(info, 1, CheckData) if err != nil { return err } - - if result == "https" { - err, _, CheckData = geturl(info, true, CheckData) - if err != nil { - return err + if strings.Contains(result, "://") { + //有跳转 + redirecturl, err := url.Parse(result) + if err == nil { + info.Url = redirecturl.String() + err, result, CheckData = geturl(info, 3, CheckData) + if err != nil { + return err + } } } - err, _, CheckData = geturl(info, false, CheckData) + if result == "https" { + err, result, CheckData = geturl(info, 1, CheckData) + if strings.Contains(result, "://") { + //有跳转 + redirecturl, err := url.Parse(result) + if err == nil { + info.Url = redirecturl.String() + err, result, CheckData = geturl(info, 3, CheckData) + if err != nil { + return err + } + } + } else { + if err != nil { + return err + } + } + } + + err, _, CheckData = geturl(info, 2, CheckData) if err != nil { return err } @@ -61,11 +97,17 @@ func GOWebTitle(info *common.HostInfo) error { return err } -func geturl(info *common.HostInfo, flag bool, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) { +func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) { Url := info.Url - if flag == false { - Url += "/favicon.ico" + if flag == 2 { + URL, err := url.Parse(Url) + if err == nil { + Url = fmt.Sprintf("%s://%s/favicon.ico", URL.Scheme, URL.Host) + } else { + Url += "/favicon.ico" + } } + res, err := http.NewRequest("GET", Url, nil) if err == nil { res.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36") @@ -73,34 +115,84 @@ func geturl(info *common.HostInfo, flag bool, CheckData []WebScan.CheckDatas) (e res.Header.Set("Accept-Language", "zh-CN,zh;q=0.9") res.Header.Set("Accept-Encoding", "gzip, deflate") if common.Pocinfo.Cookie != "" { - res.Header.Set("Cookie", common.Pocinfo.Cookie) - } - if flag == true { res.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie) + } else { + res.Header.Set("Cookie", "rememberMe=1") } res.Header.Set("Connection", "close") - resp, err := lib.Client.Do(res) + + var client *http.Client + if flag == 1 { + client = lib.ClientNoRedirect + } else { + client = lib.Client + } + + resp, err := client.Do(res) if err == nil { defer resp.Body.Close() var title string body, _ := ioutil.ReadAll(resp.Body) - re := regexp.MustCompile("(.*)") - find := re.FindAllStringSubmatch(string(body), -1) - if len(find) > 0 { - title = find[0][1] + if flag != 2 { + re := regexp.MustCompile("(?im)(.*)") + find := re.FindSubmatch(body) + if len(find) > 1 { + text := find[1] + GetEncoding := func() string { // 判断Content-Type + r1, err := regexp.Compile(`(?im)charset=\s*?([\w-]+)`) + if err != nil { + return "" + } + headerCharset := r1.FindString(resp.Header.Get("Content-Type")) + if headerCharset != "" { + for _, v := range Charsets { // headers 编码优先,所以放在前面 + if strings.Contains(strings.ToLower(headerCharset), v) == true { + return v + } + } + } + + r2, err := regexp.Compile(`(?im)`) + if err != nil { + return "" + } + htmlCharset := r2.FindString(string(body)) + if htmlCharset != "" { + for _, v := range Charsets { + if strings.Contains(strings.ToLower(htmlCharset), v) == true { + return v + } + } + } + return "" + } + encoding := GetEncoding() + if encoding == "gbk" || encoding == "gb2312" { + titleGBK, err := Decodegbk(text) + if err == nil { + title = string(titleGBK) + } + } else { + title = string(text) + } + } else { + title = "None" + } + title = strings.Trim(title, "\r\n \t") + title = strings.Replace(title, "\n", "", -1) + title = strings.Replace(title, "\r", "", -1) + title = strings.Replace(title, " ", " ", -1) if len(title) > 100 { title = title[:100] } - } else { - title = "None" - } - if flag == true { result := fmt.Sprintf("[*] WebTitle:%-25v %-3v %v", Url, resp.StatusCode, title) common.LogSuccess(result) } - CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)}) - + redirURL, err1 := resp.Location() + if err1 == nil { + return nil, redirURL.String(), CheckData + } if resp.StatusCode == 400 && info.Url[:5] != "https" { info.Url = strings.Replace(info.Url, "http://", "https://", 1) return err, "https", CheckData @@ -111,3 +203,13 @@ func geturl(info *common.HostInfo, flag bool, CheckData []WebScan.CheckDatas) (e } return err, "", CheckData } + +func Decodegbk(s []byte) ([]byte, error) { // GBK解码 + I := bytes.NewReader(s) + O := transform.NewReader(I, simplifiedchinese.GBK.NewDecoder()) + d, e := ioutil.ReadAll(O) + if e != nil { + return nil, e + } + return d, nil +} diff --git a/README.md b/README.md index 052180a..f9597f0 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-G ## 最近更新 +[+] 2021/4/22 修改webtitle模块,加入gbk解码 [+] 2021/4/21 加入netbios探测、域控识别 [+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描 [+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml diff --git a/WebScan/lib/http.go b/WebScan/lib/http.go index 2c46821..2b38559 100644 --- a/WebScan/lib/http.go +++ b/WebScan/lib/http.go @@ -15,7 +15,7 @@ import ( var ( Client *http.Client - clientNoRedirect *http.Client + ClientNoRedirect *http.Client dialTimout = 5 * time.Second keepAlive = 15 * time.Second ) @@ -51,11 +51,11 @@ func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) err Transport: tr, Timeout: Timeout, } - clientNoRedirect = &http.Client{ + ClientNoRedirect = &http.Client{ Transport: tr, Timeout: Timeout, } - clientNoRedirect.CheckRedirect = func(req *http.Request, via []*http.Request) error { + ClientNoRedirect.CheckRedirect = func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse } return nil @@ -75,7 +75,7 @@ func DoRequest(req *http.Request, redirect bool) (*Response, error) { if redirect { oResp, err = Client.Do(req) } else { - oResp, err = clientNoRedirect.Do(req) + oResp, err = ClientNoRedirect.Do(req) } if err != nil { return nil, err diff --git a/go.mod b/go.mod index 4c3c040..3b1902d 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8 golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc golang.org/x/net v0.0.0-20210420072503-d25e30425868 + golang.org/x/text v0.3.6 google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b )