mitminfo.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package fp
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. // Sources:
  8. // - https://jhalderm.com/pub/papers/interception-ndss17.pdf
  9. const (
  10. TypeEmpty uint8 = iota
  11. TypeAntivirus
  12. TypeFakeBrowser
  13. TypeMalware
  14. TypeParental
  15. TypeProxy
  16. )
  17. // MitmInfo contains information about mitm software.
  18. type MitmInfo struct {
  19. NameList StringList
  20. Type uint8
  21. Grade Grade
  22. }
  23. // String returns a string representation of the mitm info.
  24. func (a MitmInfo) String() string {
  25. return fmt.Sprintf("%s:%d:%d", a.NameList, a.Type, a.Grade)
  26. }
  27. // NewMitmInfo returns a new MitmInfo struct parsed from a string.
  28. func NewMitmInfo(s string) (MitmInfo, error) {
  29. var a MitmInfo
  30. err := a.Parse(s)
  31. return a, err
  32. }
  33. // Parse info from a string and return an error on failure.
  34. func (a *MitmInfo) Parse(s string) error {
  35. var i int
  36. var err error
  37. fields := strings.Split(s, ":")
  38. if len(fields) != 3 {
  39. return fmt.Errorf("invalid mitm info: '%s'", s)
  40. }
  41. if err := a.NameList.Parse(fields[0]); err != nil {
  42. return err
  43. }
  44. // simplify mitm names
  45. for idx, elem := range a.NameList {
  46. elem = strings.ToLower(strings.Replace(elem, "-", "", -1))
  47. for _, mitmName := range mitmNames {
  48. if strings.Contains(elem, mitmName) {
  49. elem = mitmName
  50. break
  51. }
  52. }
  53. a.NameList[idx] = elem
  54. }
  55. i, err = strconv.Atoi(fields[1])
  56. if err != nil {
  57. return err
  58. }
  59. a.Type = uint8(i)
  60. i, err = strconv.Atoi(fields[2])
  61. if err != nil {
  62. return err
  63. }
  64. a.Grade = Grade(i)
  65. return nil
  66. }
  67. // Merge mitm info a and b.
  68. func (a MitmInfo) Merge(b MitmInfo) MitmInfo {
  69. var merged MitmInfo
  70. if a.NameList == nil && b.NameList == nil {
  71. merged.NameList = nil
  72. } else {
  73. merged.NameList = (a.NameList.Set().Union(b.NameList.Set())).List()
  74. }
  75. if a.Type == b.Type {
  76. merged.Type = a.Type
  77. } else {
  78. merged.Type = TypeEmpty
  79. }
  80. merged.Grade = a.Grade.Merge(b.Grade)
  81. return merged
  82. }
  83. // Match returns MatchPossible if the lists of mitm names are exactly the same
  84. // or share a common mitm name, and returns MatchImpossible otherwise.
  85. func (a MitmInfo) Match(b MitmInfo) Match {
  86. if a.NameList.String() == b.NameList.String() || len(a.NameList.Set().Inter(b.NameList.Set())) > 0 {
  87. return MatchPossible
  88. }
  89. return MatchImpossible
  90. }
  91. // known HTTPS interception software vendors
  92. var mitmNames = []string{
  93. "avast",
  94. "avg",
  95. "barracuda",
  96. "bitdefender",
  97. "bluecoat",
  98. "bullguard",
  99. "chromodo",
  100. "ciscows",
  101. "citrix",
  102. "cybersitter",
  103. "drweb",
  104. "eset",
  105. "forcepoint",
  106. "fortigate",
  107. "gdata",
  108. "hidemyip",
  109. "junipersrx",
  110. "kaspersky",
  111. "keepmyfamilysecure",
  112. "hidemyip",
  113. "kindergate",
  114. "komodiasuperfish",
  115. "microsofttmg",
  116. "netnanny",
  117. "pcpandora",
  118. "privdog",
  119. "qustodio",
  120. "sophos",
  121. "staffcop",
  122. "untangle",
  123. "wajam",
  124. "webtitan",
  125. "adguard",
  126. }