diff --git a/deanonymization/private_key.go b/deanonymization/private_key.go index d8b0ec4..3d35be5 100644 --- a/deanonymization/private_key.go +++ b/deanonymization/private_key.go @@ -1,42 +1,56 @@ package deanonymization import ( - "net/url" - - "encoding/base64" + "crypto/rsa" + "crypto/sha1" + "crypto/x509" + "encoding/asn1" + "encoding/base32" + "encoding/pem" + "fmt" "github.com/s-rah/onionscan/config" "github.com/s-rah/onionscan/report" + "net/url" "strings" + "regexp" ) -func ProcessKey(osreport *report.OnionScanReport, report *report.AnonymityReport, osc *config.OnionScanConfig, key string) { - _, err := base64.StdEncoding.DecodeString(key) - if err == nil { // Parses as base64 - could further check data as DER key, but this seems enough - report.PrivateKeyDetected = true - } -} - func PrivateKey(osreport *report.OnionScanReport, report *report.AnonymityReport, osc *config.OnionScanConfig) { for _, id := range osreport.Crawls { crawlRecord, _ := osc.Database.GetCrawlRecord(id) uri, _ := url.Parse(crawlRecord.URL) if crawlRecord.Page.Status == 200 && strings.HasSuffix(uri.Path, "/private_key") { - contents := crawlRecord.Page.Snapshot + privateKeyRegex := regexp.MustCompile("-----BEGIN RSA PRIVATE KEY-----((?s).*)-----END RSA PRIVATE KEY-----") + foundPrivateKey := privateKeyRegex.FindAllString(crawlRecord.Page.Snapshot, -1) + for _, keyString := range foundPrivateKey { + osc.LogInfo(fmt.Sprintf("Found Potential Private Key")) + block,_ := pem.Decode([]byte(keyString)) + if block == nil || block.Type != "RSA PRIVATE KEY" { + osc.LogInfo("Could not parse privacy key: no valid PEM data found") + continue + } + + privateKey,err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + osc.LogInfo("Could not parse private key") + continue + } + + // DER Encode the Public Key + publicKeyBytes,_ := asn1.Marshal(rsa.PublicKey{ + N: privateKey.PublicKey.N, + E: privateKey.PublicKey.E, + }) + + h := sha1.New() + h.Write(publicKeyBytes) + sha1bytes := h.Sum(nil) - key := "" - inKey := false - for _, line := range strings.Split(contents, "\n") { - line := strings.TrimSpace(line) - if line == "-----BEGIN RSA PRIVATE KEY-----" { - inKey = true - key = "" - } else if line == "-----END RSA PRIVATE KEY-----" { - ProcessKey(osreport, report, osc, key) - inKey = false - } else if inKey { - key += line - } + data := base32.StdEncoding.EncodeToString(sha1bytes) + hostname := strings.ToLower(data[0:16]) + osc.LogInfo(fmt.Sprintf("Found Private Key for Host %s.onion", hostname)) + report.PrivateKeyDetected = true } } } diff --git a/spider/onionspider.go b/spider/onionspider.go index c06728b..abfe267 100644 --- a/spider/onionspider.go +++ b/spider/onionspider.go @@ -112,12 +112,14 @@ func (os *OnionSpider) Crawl(hiddenservice string, osc *config.OnionScanConfig, // Grab Server Status if it Exists // We add it as a resource so we can pull any information out of it later. mod_status, _ := url.Parse("http://" + hiddenservice + "/server-status") + osc.LogInfo(fmt.Sprintf("Scanning URI: %s", mod_status.String())) id, err = os.GetPage(mod_status.String(), base, osc, true) addCrawl(mod_status.String(), id, err) // Grab Private Key if it Exists // This would be a major security fail private_key, _ := url.Parse("http://" + hiddenservice + "/private_key") + osc.LogInfo(fmt.Sprintf("Scanning URI: %s", private_key.String())) id, err = os.GetPage(private_key.String(), base, osc, true) addCrawl(private_key.String(), id, err)