Skip to content

Commit 7ed4cd1

Browse files
add md5 hash support for favicon (#1799)
1 parent 4f035a7 commit 7ed4cd1

File tree

3 files changed

+29
-17
lines changed

3 files changed

+29
-17
lines changed

common/stringz/stringz.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package stringz
22

33
import (
44
"bytes"
5+
"crypto/md5"
56
"encoding/base64"
7+
"encoding/hex"
68
"errors"
79
"net/http"
810
"net/url"
@@ -121,12 +123,19 @@ func murmurhash(data []byte) int32 {
121123
return int32(hasher.Sum32())
122124
}
123125

124-
func FaviconHash(data []byte) (int32, error) {
126+
// md5Hash returns the md5 hash of the data
127+
func md5Hash(data []byte) string {
128+
hasher := md5.New()
129+
hasher.Write(data)
130+
return hex.EncodeToString(hasher.Sum(nil))
131+
}
132+
133+
func FaviconHash(data []byte) (int32, string, error) {
125134
if isContentTypeImage(data) {
126-
return murmurhash(data), nil
135+
return murmurhash(data), md5Hash(data), nil
127136
}
128137

129-
return 0, errors.New("content type is not image")
138+
return 0, "", errors.New("content type is not image")
130139
}
131140

132141
func InsertInto(s string, interval int, sep rune) string {

runner/runner.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,11 +1948,11 @@ retry:
19481948
builder.WriteRune(']')
19491949
}
19501950

1951-
var faviconMMH3, faviconPath, faviconURL string
1951+
var faviconMMH3, faviconMD5, faviconPath, faviconURL string
19521952
var faviconData []byte
19531953
if scanopts.Favicon {
19541954
var err error
1955-
faviconMMH3, faviconPath, faviconData, faviconURL, err = r.HandleFaviconHash(hp, req, resp.Data, true)
1955+
faviconMMH3, faviconMD5, faviconPath, faviconData, faviconURL, err = r.HandleFaviconHash(hp, req, resp.Data, true)
19561956
if err == nil {
19571957
builder.WriteString(" [")
19581958
if !scanopts.OutputWithNoColor {
@@ -2199,6 +2199,7 @@ retry:
21992199
Technologies: technologies,
22002200
FinalURL: finalURL,
22012201
FavIconMMH3: faviconMMH3,
2202+
FavIconMD5: faviconMD5,
22022203
FaviconPath: faviconPath,
22032204
FaviconURL: faviconURL,
22042205
Hashes: hashesMap,
@@ -2257,24 +2258,24 @@ func calculatePerceptionHash(screenshotBytes []byte) (uint64, error) {
22572258
return pHash.GetHash(), nil
22582259
}
22592260

2260-
func (r *Runner) HandleFaviconHash(hp *httpx.HTTPX, req *retryablehttp.Request, currentResp []byte, defaultProbe bool) (string, string, []byte, string, error) {
2261+
func (r *Runner) HandleFaviconHash(hp *httpx.HTTPX, req *retryablehttp.Request, currentResp []byte, defaultProbe bool) (string, string, string, []byte, string, error) {
22612262
// Check if current URI is ending with .ico => use current body without additional requests
22622263
if path.Ext(req.URL.Path) == ".ico" {
2263-
hash, err := r.calculateFaviconHashWithRaw(currentResp)
2264-
return hash, req.URL.Path, currentResp, "", err
2264+
MMH3Hash, MD5Hash, err := r.calculateFaviconHashWithRaw(currentResp)
2265+
return MMH3Hash, MD5Hash, req.URL.Path, currentResp, "", err
22652266
}
22662267

22672268
// search in the response of the requested path for element and rel shortcut/mask/apple-touch icon
22682269
// link with .ico extension (which will be prioritized if available)
22692270
// if not, any of link from other icons can be requested
22702271
potentialURLs, err := extractPotentialFavIconsURLs(currentResp)
22712272
if err != nil {
2272-
return "", "", nil, "", err
2273+
return "", "", "", nil, "", err
22732274
}
22742275

22752276
clone := req.Clone(context.Background())
22762277

2277-
var faviconHash, faviconPath, faviconURL string
2278+
var faviconMMH3, faviconMD5, faviconPath, faviconURL string
22782279
var faviconData []byte
22792280
errCount := 0
22802281
if len(potentialURLs) == 0 && defaultProbe {
@@ -2309,25 +2310,26 @@ func (r *Runner) HandleFaviconHash(hp *httpx.HTTPX, req *retryablehttp.Request,
23092310
errCount++
23102311
continue
23112312
}
2312-
hash, err := r.calculateFaviconHashWithRaw(resp.Data)
2313+
MMH3Hash, MD5Hash, err := r.calculateFaviconHashWithRaw(resp.Data)
23132314
if err != nil {
23142315
continue
23152316
}
23162317
faviconURL = clone.URL.String()
23172318
faviconPath = potentialURL
2318-
faviconHash = hash
2319+
faviconMMH3 = MMH3Hash
2320+
faviconMD5 = MD5Hash
23192321
faviconData = resp.Data
23202322
break
23212323
}
2322-
return faviconHash, faviconPath, faviconData, faviconURL, nil
2324+
return faviconMMH3, faviconMD5, faviconPath, faviconData, faviconURL, nil
23232325
}
23242326

2325-
func (r *Runner) calculateFaviconHashWithRaw(data []byte) (string, error) {
2326-
hashNum, err := stringz.FaviconHash(data)
2327+
func (r *Runner) calculateFaviconHashWithRaw(data []byte) (string, string, error) {
2328+
hashNum, md5Hash, err := stringz.FaviconHash(data)
23272329
if err != nil {
2328-
return "", errorutil.NewWithTag("favicon", "could not calculate favicon hash").Wrap(err)
2330+
return "", "", errorutil.NewWithTag("favicon", "could not calculate favicon hash").Wrap(err)
23292331
}
2330-
return fmt.Sprintf("%d", hashNum), nil
2332+
return fmt.Sprintf("%d", hashNum), md5Hash, nil
23312333
}
23322334

23332335
func extractPotentialFavIconsURLs(resp []byte) ([]string, error) {

runner/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type Result struct {
5959
Host string `json:"host,omitempty" csv:"host"`
6060
Path string `json:"path,omitempty" csv:"path"`
6161
FavIconMMH3 string `json:"favicon,omitempty" csv:"favicon"`
62+
FavIconMD5 string `json:"favicon_md5,omitempty" csv:"favicon"`
6263
FaviconPath string `json:"favicon_path,omitempty" csv:"favicon_path"`
6364
FaviconURL string `json:"favicon_url,omitempty" csv:"favicon_url"`
6465
FinalURL string `json:"final_url,omitempty" csv:"final_url"`

0 commit comments

Comments
 (0)