main.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package main
  2. import (
  3. "encoding/json"
  4. "flag"
  5. "fmt"
  6. "io/ioutil"
  7. "log"
  8. "os/exec"
  9. "path/filepath"
  10. "strings"
  11. "github.com/avct/uasurfer"
  12. "github.com/cloudflare/mitmengine"
  13. fp "github.com/cloudflare/mitmengine/fputil"
  14. )
  15. func main() {
  16. browserFileName := flag.String("browser", filepath.Join("reference_fingerprints", "mitmengine", "browser.txt"), "File containing browser signatures")
  17. mitmFileName := flag.String("mitm", filepath.Join("reference_fingerprints", "mitmengine", "mitm.txt"), "File containing mitm signatures")
  18. badHeaderFileName := flag.String("badheader", filepath.Join("reference_fingerprints", "mitmengine", "badheader.txt"), "File containing non-browser (bad) HTTP headers")
  19. handshakePcapFileName := flag.String("handshake", filepath.Join("reference_fingerprints", "pcaps", "misc", "ios5", "handshake.pcap"), "Pcap containing TLS Client Hello")
  20. headerJsonFileName := flag.String("header", filepath.Join("reference_fingerprints", "pcaps", "middleboxes", "barracuda", "barracuda-chrome48", "header.json"), "Json file containing HTTP headers")
  21. flag.Parse()
  22. // Load config
  23. var err error
  24. mitmProcessor, err := mitmengine.NewProcessor(&mitmengine.Config{
  25. BrowserFileName: *browserFileName,
  26. MitmFileName: *mitmFileName,
  27. BadHeaderFileName: *badHeaderFileName,
  28. })
  29. if err != nil {
  30. log.Fatal(err)
  31. }
  32. // Read in TLS Client Hello fingerprint
  33. requestFingerprintString, err := exec.Command(filepath.Join("scripts", "pcap_to_request_fingerprint.py"), *handshakePcapFileName).Output()
  34. if err != nil {
  35. log.Fatal(err)
  36. }
  37. requestFingerprint, err := fp.NewRequestFingerprint(strings.TrimSpace(string(requestFingerprintString)))
  38. if err != nil {
  39. log.Fatal(err)
  40. }
  41. // Read in HTTP request fingerprint
  42. jsonStr, err := ioutil.ReadFile(*headerJsonFileName)
  43. if err != nil {
  44. log.Fatal(err)
  45. }
  46. var decoded []struct {
  47. Source struct {
  48. Layers struct {
  49. RequestLines []string `json:"http.request.line"`
  50. } `json:"layers"`
  51. } `json:"_source"`
  52. }
  53. if err = json.Unmarshal(jsonStr, &decoded); err != nil {
  54. log.Fatal(err)
  55. }
  56. rawUa := ""
  57. for _, pkt := range decoded {
  58. for _, requestLine := range pkt.Source.Layers.RequestLines {
  59. if strings.Contains(requestLine, "User-Agent:") {
  60. rawUa = strings.TrimSpace(strings.TrimPrefix(requestLine, "User-Agent:"))
  61. break
  62. }
  63. }
  64. if len(rawUa) > 0 {
  65. break
  66. }
  67. }
  68. // Convert uasurfer.UserAgent to fp.UAFingerprint
  69. ua := uasurfer.Parse(rawUa)
  70. uaFingerprint := fp.UAFingerprint{
  71. BrowserName: int(ua.Browser.Name),
  72. BrowserVersion: fp.UAVersion(ua.Browser.Version),
  73. OSPlatform: int(ua.OS.Platform),
  74. OSName: int(ua.OS.Name),
  75. OSVersion: fp.UAVersion(ua.OS.Version),
  76. DeviceType: int(ua.DeviceType),
  77. }
  78. report := mitmProcessor.Check(uaFingerprint, rawUa, requestFingerprint)
  79. // Print out human-readable report
  80. if report.Error != nil {
  81. fmt.Printf("MITM results inconclusive: %v\n", report.Error)
  82. return
  83. }
  84. fmt.Printf("User agent fingerprint matched signature from database:\n\tua fp:\t%v\n\tua sig:\t%v\n", uaFingerprint, report.MatchedUASignature)
  85. fmt.Printf("Expect request fingerprint to match request signature from database:\n\trq fp:\t%v\n\trq sig:\t%v\n\tmatch:\t%v", requestFingerprint, report.BrowserSignature, report.BrowserSignatureMatch)
  86. if report.BrowserSignatureMatch == fp.MatchPossible {
  87. fmt.Printf("\n")
  88. } else {
  89. fmt.Printf("\n\treason:\t%v\n", report.Reason)
  90. }
  91. fmt.Printf("Security report:\n\tbrowser grade:\t%v\n\tactual grade:\t%v\n\tweak ciphers:\t%v\n\tloses pfs:\t%v\n", report.BrowserGrade, report.ActualGrade, report.WeakCiphers, report.LosesPfs)
  92. if len(report.MatchedMitmSignature) > 0 {
  93. fmt.Printf("Request fingerprint matched known MITM signature:\n\trq sig:\t%v\n\tname:\t%v\n\ttype:\t%v\n", report.MatchedMitmSignature, report.MatchedMitmName, report.MatchedMitmType)
  94. } else {
  95. fmt.Printf("Request fingerprint did not match any known MITM signatures\n")
  96. }
  97. }