New Protocols Scans, SSH Fingerprinting
* SSH Fingerprint * Page Snapshot * A few new Protocol Tests (FTP, SMTP, Ricochet, IRC)
This commit is contained in:
parent
a0ae46ca31
commit
44e6d5c955
|
@ -84,7 +84,7 @@ or their users at risk of deanonymization.
|
|||
## Server Fingerprint
|
||||
|
||||
Sometimes, even without mod_status we can determine if two sites are hosted on
|
||||
the sam infrastructure. We can use the following attributes to make this distinction:
|
||||
the same infrastructure. We can use the following attributes to make this distinction:
|
||||
|
||||
* Server HTTP Header
|
||||
* Technology Stack (e.g. php, jquery version etc.)
|
||||
|
|
16
onionscan.go
16
onionscan.go
|
@ -42,5 +42,21 @@ func (os *OnionScan) Scan(hiddenService string) (*report.OnionScanReport, error)
|
|||
rps := new(protocol.RicochetProtocolScanner)
|
||||
rps.ScanProtocol(hiddenService, os.TorProxyAddress, report)
|
||||
|
||||
// Bitcoin
|
||||
bps := new(protocol.BitcoinProtocolScanner)
|
||||
bps.ScanProtocol(hiddenService, os.TorProxyAddress, report)
|
||||
|
||||
//IRC
|
||||
ips := new(protocol.IRCProtocolScanner)
|
||||
ips.ScanProtocol(hiddenService, os.TorProxyAddress, report)
|
||||
|
||||
//FTP
|
||||
fps := new(protocol.FTPProtocolScanner)
|
||||
fps.ScanProtocol(hiddenService, os.TorProxyAddress, report)
|
||||
|
||||
//SMTP
|
||||
smps := new(protocol.SMTPProtocolScanner)
|
||||
smps.ScanProtocol(hiddenService, os.TorProxyAddress, report)
|
||||
|
||||
return report, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"github.com/s-rah/onionscan/report"
|
||||
"h12.me/socks"
|
||||
"log"
|
||||
)
|
||||
|
||||
type BitcoinProtocolScanner struct {
|
||||
|
||||
}
|
||||
|
||||
func (rps *BitcoinProtocolScanner) ScanProtocol(hiddenService string, proxyAddress string, report *report.OnionScanReport) {
|
||||
// Bitcoin
|
||||
log.Printf("Checking %s Bitcoin(8333)\n", hiddenService)
|
||||
_, err := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)("", hiddenService+":8333")
|
||||
if err != nil {
|
||||
log.Printf("Failed to connect to service on port 8333\n")
|
||||
} else {
|
||||
log.Printf("Detected possible Bitcoin instance\n")
|
||||
// TODO: Actual Analysis
|
||||
report.BitcoinDetected = true
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"github.com/s-rah/onionscan/report"
|
||||
"h12.me/socks"
|
||||
"log"
|
||||
)
|
||||
|
||||
type FTPProtocolScanner struct {
|
||||
|
||||
}
|
||||
|
||||
func (sps *FTPProtocolScanner) ScanProtocol(hiddenService string, proxyAddress string, report *report.OnionScanReport) {
|
||||
// FTP
|
||||
log.Printf("Checking %s FTP(22)\n", hiddenService)
|
||||
_, err := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)("", hiddenService+":21")
|
||||
if err != nil {
|
||||
log.Printf("Failed to connect to service on port 21\n")
|
||||
} else {
|
||||
// TODO FTP Checking
|
||||
report.FTPDetected = true
|
||||
}
|
||||
|
||||
}
|
|
@ -22,6 +22,7 @@ func (hps * HTTPProtocolScanner) ScanProtocol(hiddenService string, proxyAddress
|
|||
log.Printf("Failed to connect to service on port 80\n")
|
||||
} else {
|
||||
log.Printf("Found potential service on http(80)\n")
|
||||
report.WebDetected = true
|
||||
dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)
|
||||
transportConfig := &http.Transport{
|
||||
Dial: dialSocksProxy,
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"github.com/s-rah/onionscan/report"
|
||||
"h12.me/socks"
|
||||
"log"
|
||||
)
|
||||
|
||||
type IRCProtocolScanner struct {
|
||||
|
||||
}
|
||||
|
||||
func (rps *IRCProtocolScanner) ScanProtocol(hiddenService string, proxyAddress string, report *report.OnionScanReport) {
|
||||
// IRC
|
||||
log.Printf("Checking %s IRC(6667)\n", hiddenService)
|
||||
_, err := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)("", hiddenService+":6667")
|
||||
if err != nil {
|
||||
log.Printf("Failed to connect to service on port 6667\n")
|
||||
} else {
|
||||
log.Printf("Detected possible IRC instance\n")
|
||||
// TODO: Actual Analysis
|
||||
report.IRCDetected = true
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ func (rps *RicochetProtocolScanner) ScanProtocol(hiddenService string, proxyAddr
|
|||
} else {
|
||||
log.Printf("Detected possible ricochet instance\n")
|
||||
// TODO: Actual Analysis
|
||||
report.RicochetDetected = true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"github.com/s-rah/onionscan/report"
|
||||
"h12.me/socks"
|
||||
"log"
|
||||
)
|
||||
|
||||
type SMTPProtocolScanner struct {
|
||||
|
||||
}
|
||||
|
||||
func (sps *SMTPProtocolScanner) ScanProtocol(hiddenService string, proxyAddress string, report *report.OnionScanReport) {
|
||||
// SMTP
|
||||
log.Printf("Checking %s SMTP(25)\n", hiddenService)
|
||||
_, err := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)("", hiddenService+":25")
|
||||
if err != nil {
|
||||
log.Printf("Failed to connect to service on port 25\n")
|
||||
} else {
|
||||
// TODO SMTP Checking
|
||||
report.SMTPDetected = true
|
||||
}
|
||||
|
||||
}
|
|
@ -4,6 +4,11 @@ import (
|
|||
"github.com/s-rah/onionscan/report"
|
||||
"h12.me/socks"
|
||||
"log"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"net"
|
||||
"errors"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type SSHProtocolScanner struct {
|
||||
|
@ -13,11 +18,35 @@ type SSHProtocolScanner struct {
|
|||
func (sps *SSHProtocolScanner) ScanProtocol(hiddenService string, proxyAddress string, report *report.OnionScanReport) {
|
||||
// SSH
|
||||
log.Printf("Checking %s ssh(22)\n", hiddenService)
|
||||
_, err := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)("", hiddenService+":22")
|
||||
conn, err := socks.DialSocksProxy(socks.SOCKS5, proxyAddress)("", hiddenService+":22")
|
||||
if err != nil {
|
||||
log.Printf("Failed to connect to service on port 22\n")
|
||||
} else {
|
||||
// TODO SSH Checking
|
||||
report.SSHDetected = true
|
||||
|
||||
config := &ssh.ClientConfig {
|
||||
HostKeyCallback : func (hostname string, addr net.Addr, key ssh.PublicKey) error {
|
||||
h := md5.New()
|
||||
h.Write(key.Marshal())
|
||||
|
||||
fBytes := h.Sum(nil)
|
||||
fingerprint := string("")
|
||||
for i := 0; i < len(fBytes); i++ {
|
||||
if i+1 != len(fBytes) {
|
||||
fingerprint = fmt.Sprintf("%s%0.2x:", fingerprint, fBytes[i])
|
||||
} else {
|
||||
fingerprint = fmt.Sprintf("%s%0.2x", fingerprint, fBytes[i])
|
||||
}
|
||||
}
|
||||
report.SSHKey = fingerprint
|
||||
log.Printf("Found SSH Key %s\n", fingerprint)
|
||||
// We don't want to continue
|
||||
return errors.New("error")
|
||||
},
|
||||
}
|
||||
ssh.NewClientConn(conn,hiddenService+":22",config)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package report
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"github.com/s-rah/onionscan/utils"
|
||||
)
|
||||
|
||||
type ExifTag struct {
|
||||
|
@ -15,18 +17,43 @@ type ExifImage struct {
|
|||
}
|
||||
|
||||
type OnionScanReport struct {
|
||||
|
||||
WebDetected bool `json:"webDetected"`
|
||||
SSHDetected bool `json:"sshDetected"`
|
||||
RicochetDetected bool `json:"ricochetDetected"`
|
||||
IRCDetected bool `json:"ircDetected"`
|
||||
FTPDetected bool `json:"ftpDetected"`
|
||||
SMTPDetected bool `json:"smtpDetected"`
|
||||
|
||||
BitcoinDetected bool `json:"bitcoinDetected"`
|
||||
|
||||
HiddenService string `json:"hiddenService"`
|
||||
ServerPoweredBy string `json:"serverPoweredBy"`
|
||||
ServerVersion string `json:"serverVersion"`
|
||||
FoundApacheModStatus bool `json:"foundApacheModStatus"`
|
||||
RelatedOnionServices []string `json:"relatedOnionServices"`
|
||||
RelatedClearnetDomains []string `json:"relatedOnionDomains"`
|
||||
LinkedSites []string `json:"linkedSites"`
|
||||
IP []string `json:"ipAddresses"`
|
||||
OpenDirectories []string `json:"openDirectories"`
|
||||
ExifImages []ExifImage `json:"exifImages"`
|
||||
InterestingFiles []string `json:"interestingFiles"`
|
||||
Hashes []string `json:"hashes"`
|
||||
SSHKey string `json:"sshKey"`
|
||||
Snapshot string `json:"snapshot"`
|
||||
}
|
||||
|
||||
func LoadReportFromFile(filename string) (OnionScanReport, error) {
|
||||
dat, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return OnionScanReport{}, err
|
||||
}
|
||||
res := OnionScanReport{}
|
||||
err = json.Unmarshal(dat, &res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
|
||||
func NewOnionScanReport(hiddenService string) *OnionScanReport {
|
||||
return &OnionScanReport{HiddenService: hiddenService}
|
||||
}
|
||||
|
@ -51,6 +78,11 @@ func (osr *OnionScanReport) AddIPAddress(ip string) {
|
|||
osr.IP = append(osr.IP, ip)
|
||||
}
|
||||
|
||||
func (osr *OnionScanReport) AddLinkedSite(site string) {
|
||||
osr.LinkedSites = append(osr.LinkedSites, site)
|
||||
utils.RemoveDuplicates(&osr.LinkedSites)
|
||||
}
|
||||
|
||||
func (osr *OnionScanReport) Serialize() (string, error) {
|
||||
report,err := json.Marshal(osr)
|
||||
if err != nil {
|
||||
|
|
|
@ -3,9 +3,12 @@ package scans
|
|||
import (
|
||||
"github.com/s-rah/onionscan/report"
|
||||
"github.com/s-rah/onionscan/utils"
|
||||
"net/url"
|
||||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func StandardPageScan(scan Scanner, page string, status int, contents string, report *report.OnionScanReport) {
|
||||
|
@ -13,6 +16,10 @@ func StandardPageScan(scan Scanner, page string, status int, contents string, re
|
|||
if status == 200 {
|
||||
log.Printf("\tPage %s%s is Accessible\n", report.HiddenService, page)
|
||||
|
||||
hash := sha1.Sum([]byte(contents))
|
||||
report.Hashes = append(report.Hashes, hex.EncodeToString(hash[:]))
|
||||
report.Snapshot = contents
|
||||
|
||||
domains := utils.ExtractDomains(contents)
|
||||
|
||||
for _,domain := range domains {
|
||||
|
@ -22,8 +29,11 @@ func StandardPageScan(scan Scanner, page string, status int, contents string, re
|
|||
// * Links to standard sites - google / bitpay etc.
|
||||
// * Links to other onion sites
|
||||
// * Links to obscure clearnet sites.
|
||||
baseUrl,_ := url.Parse(domain)
|
||||
report.AddLinkedSite(baseUrl.Host)
|
||||
} else {
|
||||
// * Process Internal links
|
||||
log.Printf("Found Internal URL %s\n", domain)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,3 +50,5 @@ func StandardPageScan(scan Scanner, page string, status int, contents string, re
|
|||
log.Printf("\tPage %s%s is Does Not Exist\n", report.HiddenService, page)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue