-
Notifications
You must be signed in to change notification settings - Fork 1
/
gosurf.go
119 lines (104 loc) · 6.55 KB
/
gosurf.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
analysis "example.com/gosurf/libs"
)
var (
initOccurrences []*analysis.Occurrence
globalVarOccurrences []*analysis.Occurrence
execOccurrences []*analysis.Occurrence
pluginOccurrences []*analysis.Occurrence
goGenerateOccurrences []*analysis.Occurrence
goTestOccurrences []*analysis.Occurrence
unsafeOccurrences []*analysis.Occurrence
cgoOccurrences []*analysis.Occurrence
interfaceOccurrences []*analysis.Occurrence
reflectOccurrences []*analysis.Occurrence
constructorOccurrences []*analysis.Occurrence
assemblyOccurrences []*analysis.Occurrence
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run main.go <module_path>")
return
}
modulePath := os.Args[1]
asciiArt := `
,ad8888ba, ad88888ba ad88
d8"' '"8b d8" "8b d8"
d8' Y8, 88
88 ,adPPYba, 'Y8aaaaa, 88 88 8b,dPPYba, MM88MMM ,adPPYYba, ,adPPYba, ,adPPYba,
88 88888 a8" "8a '"""""8b, 88 88 88P' "Y8 88 "" '8 a8" "" a8P_____88
Y8, 88 8b d8 '8b 88 88 88 88 ,adPPPPP88 8b 8PP"""""""
Y8a. .a88 "8a, ,a8" Y8a a8P "8a, ,a88 88 88 88, ,88 "8a, ,aa "8b, ,aa
'"Y88888P" '"YbbdP"' "Y88888P" '"YbbdP'Y8 88 88 '"8bbdP"Y8 '"Ybbd8"' '"Ybbd8"'
"
`
fmt.Println(asciiArt)
fmt.Println("GoSurf is a tool that aims to analyze the potential attack surface of open-source Go packages and modules.")
fmt.Println("It looks for occurrences of various features and constructs that could potentially introduce security risks.")
fmt.Println()
// TODO: currently only fetches direct dependencies in the module, not external dependencies
// Get direct dependencies
direct_dependencies, err := analysis.GetDependencies(modulePath)
if err != nil {
fmt.Printf("Error getting files in module: %v\n", err)
return
}
// analysis.PrintDependencies(direct_dependencies)
// Analyze all the module direct dependencies
for _, dep := range direct_dependencies {
analysis.AnalyzePackage(dep, &initOccurrences, analysis.InitFuncParser{})
analysis.AnalyzePackage(dep, &globalVarOccurrences, analysis.GlobalVarParser{})
analysis.AnalyzePackage(dep, &execOccurrences, analysis.ExecParser{})
analysis.AnalyzePackage(dep, &pluginOccurrences, analysis.PluginParser{})
analysis.AnalyzePackage(dep, &goGenerateOccurrences, analysis.GoGenerateParser{})
analysis.AnalyzePackage(dep, &goTestOccurrences, analysis.GoTestParser{})
analysis.AnalyzePackage(dep, &unsafeOccurrences, analysis.UnsafeParser{})
analysis.AnalyzePackage(dep, &cgoOccurrences, analysis.CgoParser{})
analysis.AnalyzePackage(dep, &interfaceOccurrences, analysis.InterfaceParser{})
analysis.AnalyzePackage(dep, &reflectOccurrences, analysis.ReflectParser{})
analysis.AnalyzePackage(dep, &constructorOccurrences, analysis.ConstructorParser{})
analysis.AnalyzePackage(dep, &assemblyOccurrences, analysis.AssemblyParser{})
}
// Convert occurrences to JSON
occurrences := append(append(append(append(append(append(append(append(append(append(append(
initOccurrences,
globalVarOccurrences...),
execOccurrences...),
pluginOccurrences...),
goGenerateOccurrences...),
goTestOccurrences...),
unsafeOccurrences...),
cgoOccurrences...),
interfaceOccurrences...),
reflectOccurrences...),
constructorOccurrences...),
assemblyOccurrences...)
// Print occurrences
// analysis.PrintOccurrences(assemblyOccurrences)
// analysis.PrintOccurrences(occurrences)
// Count unique occurrences
initCount, globalVarCount, execCount, pluginCount, goGenerateCount, goTestCount, unsafeCount, cgoCount, interfaceCount, reflectCount, constructorCount, assemblyCount := analysis.CountUniqueOccurrences(occurrences)
fmt.Println()
fmt.Println()
fmt.Println("╔═════════════════════════════════════════════════════════════════════════╗")
fmt.Printf("║ Attack Surface Analysis: %s ║\n", filepath.Base(strings.TrimSuffix(modulePath, "/"+filepath.Base(modulePath))))
fmt.Println("╠═════════════════════════════════════════════════════════════════════════╣")
fmt.Printf("║ [P1] Static Code Generation: %10d ║\n", goGenerateCount)
fmt.Printf("║ [P2] Testing Functions: %10d ║\n", goTestCount)
fmt.Printf("║ [I1] Global Variable Initialization: %10d ║\n", globalVarCount)
fmt.Printf("║ [I2] init() Functions: %10d ║\n", initCount)
fmt.Printf("║ [E1] Constructor Methods: %10d ║\n", constructorCount)
fmt.Printf("║ [E2] Reflection: %10d ║\n", reflectCount)
fmt.Printf("║ [E3] Interfaces: %10d ║\n", interfaceCount) // TODO: define better
fmt.Printf("║ [E4] Unsafe Pointers: %10d ║\n", unsafeCount)
fmt.Printf("║ [E5] CGO Functions: %10d ║\n", cgoCount)
fmt.Printf("║ [E6] Assembly Functions: %10d ║\n", assemblyCount) // TODO: define better
fmt.Printf("║ [E7] Dynamic Plugins: %10d ║\n", pluginCount)
fmt.Printf("║ [E8] External Execution: %10d ║\n", execCount)
fmt.Println("╚═════════════════════════════════════════════════════════════════════════╝")
}