update webtitle

This commit is contained in:
影舞者 2022-02-17 14:37:06 +08:00
parent ed99ee0fad
commit 2ebda8baa9
2 changed files with 115 additions and 171 deletions

View File

@ -1,16 +1,13 @@
package Plugins
import (
"bytes"
"compress/gzip"
"crypto/tls"
"fmt"
"github.com/saintfish/chardet"
"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"
"io/ioutil"
"net"
@ -19,98 +16,80 @@ import (
"regexp"
"strings"
"time"
)
var (
Charsets = []string{"utf-8", "gbk", "gb2312"}
"unicode/utf8"
)
func WebTitle(info *common.HostInfo) error {
err := GOWebTitle(info)
if err != nil {
err, CheckData := GOWebTitle(info)
info.Infostr = WebScan.InfoCheck(info.Url, &CheckData)
if common.IsWebCan == false && err == nil {
WebScan.WebScan(info)
} else {
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
common.LogError(errlog)
}
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
func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
if info.Url == "" {
if info.Ports == "80" {
switch info.Ports {
case "80":
info.Url = fmt.Sprintf("http://%s", info.Host)
} else if info.Ports == "443" {
case "443":
info.Url = fmt.Sprintf("https://%s", info.Host)
} else {
default:
host := fmt.Sprintf("%s:%s", info.Host, info.Ports)
protocol := GetProtocol(host, info.Timeout)
info.Url = fmt.Sprintf("%s://%s:%s", protocol, info.Host, info.Ports)
}
} else {
if !strings.Contains(info.Url, "://") {
protocol := GetProtocol(info.Url, info.Timeout)
host := strings.Split(info.Url, "/")[0]
protocol := GetProtocol(host, info.Timeout)
info.Url = fmt.Sprintf("%s://%s", protocol, info.Url)
}
}
err, result, CheckData := geturl(info, 1, CheckData)
if err != nil && !strings.Contains(err.Error(), "EOF") {
return err
return
}
if strings.Contains(result, "://") {
//有跳转
redirecturl, err := url.Parse(result)
if err == nil {
info.Url = redirecturl.String()
if strings.Contains(result, "://") {
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return err
}
return
}
}
if result == "https" && !strings.HasPrefix(info.Url, "https://") {
info.Url = strings.Replace(info.Url, "http://", "https://", 1)
err, result, CheckData = geturl(info, 1, CheckData)
if strings.Contains(result, "://") {
//有跳转
redirecturl, err := url.Parse(result)
if err == nil {
info.Url = redirecturl.String()
if strings.Contains(result, "://") {
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
if err != nil {
return err
return
}
}
} else {
if err != nil {
return err
}
}
} else if err != nil {
return err
}
err, _, CheckData = geturl(info, 2, CheckData)
if err != nil {
return err
return
}
info.Infostr = WebScan.InfoCheck(info.Url, CheckData)
if common.IsWebCan == false {
WebScan.WebScan(info)
}
return err
return
}
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
//flag 1 first try
//flag 2 /favicon.ico
//flag 3 302
//flag 4 400 -> https
Url := info.Url
if flag == 2 {
URL, err := url.Parse(Url)
@ -120,9 +99,10 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
Url += "/favicon.ico"
}
}
req, err := http.NewRequest("GET", Url, nil)
if err == nil {
if err != nil {
return err, "", CheckData
}
req.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")
req.Header.Set("Accept", "*/*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
@ -132,7 +112,6 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
req.Header.Set("Cookie", "rememberMe=1")
}
req.Header.Set("Connection", "close")
var client *http.Client
if flag == 1 {
client = lib.ClientNoRedirect
@ -141,106 +120,44 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
}
resp, err := client.Do(req)
if err == nil {
if err != nil {
return err, "https", CheckData
}
defer resp.Body.Close()
var title string
var text []byte
body, err := getRespBody(resp)
if err != nil {
return err, "https", CheckData
}
if !utf8.Valid(body) {
body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body)
}
CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)})
var reurl string
if flag != 2 {
re := regexp.MustCompile("(?ims)<title>(.*)</title>")
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)<meta.*?charset=['"]?([\w-]+)["']?.*?>`)
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 ""
}
encode := GetEncoding()
//_, encode1, _ := charset.DetermineEncoding(body, "")
var encode2 string
detector := chardet.NewTextDetector()
detectorstr, _ := detector.DetectBest(body)
if detectorstr != nil {
encode2 = detectorstr.Charset
}
if encode == "gbk" || encode == "gb2312" || strings.Contains(strings.ToLower(encode2), "gb") {
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, "&nbsp;", " ", -1)
if len(title) > 100 {
title = title[:100]
}
if title == "" {
title = "None"
}
title = gettitle(body)
length := resp.Header.Get("Content-Length")
if length == "" {
length = fmt.Sprintf("%v", len(body))
}
result := fmt.Sprintf("[*] WebTitle:%-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, 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
reurl = redirURL.String()
}
result := fmt.Sprintf("[*] WebTitle:%-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, title)
if reurl != "" {
result += fmt.Sprintf(" 跳转url: %s", reurl)
}
common.LogSuccess(result)
}
if reurl != "" {
return nil, reurl, CheckData
}
if resp.StatusCode == 400 && !strings.HasPrefix(info.Url, "https") {
return err, "https", CheckData
return nil, "https", CheckData
}
return err, "", CheckData
}
return err, "https", CheckData
}
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
return nil, "", CheckData
}
func getRespBody(oResp *http.Response) ([]byte, error) {
@ -272,14 +189,42 @@ func getRespBody(oResp *http.Response) ([]byte, error) {
return body, nil
}
func GetProtocol(host string, Timeout int64) string {
func gettitle(body []byte) (title string) {
re := regexp.MustCompile("(?ims)<title>(.*)</title>")
find := re.FindSubmatch(body)
if len(find) > 1 {
title = string(find[1])
title = strings.TrimSpace(title)
title = strings.Replace(title, "\n", "", -1)
title = strings.Replace(title, "\r", "", -1)
title = strings.Replace(title, "&nbsp;", " ", -1)
if len(title) > 100 {
title = title[:100]
}
}
if title == "" {
title = "None"
}
return
}
func GetProtocol(host string, Timeout int64) (protocol string) {
protocol = "http"
//如果端口是80或443,跳过Protocol判断
if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") {
return
} else if strings.HasSuffix(host, ":443") {
protocol = "https"
return
}
conn, err := tls.DialWithDialer(&net.Dialer{Timeout: time.Duration(Timeout) * time.Second}, "tcp", host, &tls.Config{InsecureSkipVerify: true})
defer func() {
if conn != nil {
conn.Close()
}
}()
protocol := "http"
if err == nil || strings.Contains(err.Error(), "handshake failure") {
protocol = "https"
}

View File

@ -13,11 +13,11 @@ type CheckDatas struct {
Headers string
}
func InfoCheck(Url string, CheckData []CheckDatas) []string {
func InfoCheck(Url string, CheckData *[]CheckDatas) []string {
var matched bool
var infoname []string
for _, data := range CheckData {
for _, data := range *CheckData {
for _, rule := range info.RuleDatas {
if rule.Type == "code" {
matched, _ = regexp.MatchString(rule.Rule, string(data.Body))
@ -67,4 +67,3 @@ func removeDuplicateElement(languages []string) []string {
}
return result
}