
Goot adalah kerangka analisis statis untuk GO. Goot mudah dipelajari, mudah digunakan dan sangat dapat diperluas, memungkinkan Anda untuk dengan mudah mengembangkan analisis baru di atasnya.
Saat ini, Goot menyediakan komponen analisis utama berikut (dan lebih banyak analisis sedang dalam perjalanan):
Intall Goot oleh
go get -u github.com/cokeBeer/goot
Tulis kode di bawah ini dalam proyek yang akan dianalisis, misalnya cmd/taint/main.go
package main
import "github.com/cokeBeer/goot/pkg/example/dataflow/taint"
func main () {
// if this file is cmd/taint/main.go
// and you want to analyse package pkg
// the path should be "../../pkg"
// or "../../pkg..." for all packages under pkg
runner := taint . NewRunner ( "relative/path/to/package" )
// for this project, is "github.com/cokeBeer/goot"
runner . ModuleName = "module-name"
runner . PassThroughDstPath = "passthrough.json"
runner . TaintGraphDstPath = "taintgraph.json"
runner . Run ()
} Jalankan kode, dan Anda akan mendapatkan passthrough.json di direktori yang sama, yang berisi informasi passthrough ternoda dari semua fungsi dalam proyek Anda
Anda dapat melihat kunci fmt.Sprintf memegang objek nilai
{
"fmt.Sprintf" : {
"Recv" : null ,
"Results" : [
[ 0 , 1 ]
],
"Params" : [
[ 0 , 1 ],
[ 1 ]
]
}
}Ini berarti tiga hal
Anda juga akan mendapatkan taintgraph.json di direktori yang sama
Anda dapat melihat file JSON berisi tepi ternoda dari satu parameter panggilan ke parameter panggilan lain
{
"(*github.com/example/runnner.Runner).RunCmd#0#(*os/exec.Cmd).StdoutPipe#0" : {
"From" : " (*github.com/example/runnner.Runner).RunCmd " ,
"FromIndex" : 0 ,
"To" : " (*os/exec.Cmd).StdoutPipe " ,
"ToIndex" : 0 ,
"ToIsMethod" : false ,
"ToIsSink" : true ,
"ToIsSignature" : false ,
"ToIsStatic" : true
}
} Ini berarti ada tepi noda dari posisi 0 RunCmd (dalam 0 exec.Cmd , parameternya adalah runner.Runner StdoutPipe .
Untuk melihat tepi ternoda lebih baik, Anda dapat memuatnya ke Neo4j dengan mengatur parameter ini (untuk opsi yang lebih rinci, lihat opsi Runner)
func main () {
runner := taint . NewRunner ( "../../internal..." )
runner . ModuleName = "gitlab.com/gitlab-org/gitlab-workhorse"
// parameters about neo4j
runner . PersistToNeo4j = true
runner . Neo4jURI = "bolt://localhost:7687"
runner . Neo4jUsername = "neo4j"
runner . Neo4jPassword = "password"
err := runner . Run ()
if err != nil {
log . Fatal ( err )
}
} Saat analisis berakhir, Anda dapat menemukan node dan tepi noda di database NEO4J Anda
Misalnya, kami menjalankan analisis taint di gitlab.com/gitlab-org/[email protected] yang memiliki kerentanan RCE CVE-2021-22225
Menggunakan kueri di bawah ini untuk menemukan jalur nakal
MATCH (source:Source),(sink:Sink {name:"os/exec.CommandContext"}),p=(source)-[*7]->(sink) RETURN p
Kita bisa mendapatkan grafik seperti ini: (node merah tenggelam, node coklat adalah fungsi intra dan node hijau adalah sumber)
Yang mengungkapkan dua jalur ternoda dari sumber ke sink os/exec.CommandContext , sama dengan CVE-2021-22225
Untuk menggunakan Goot sebagai kerangka kerja, pertama -tama buat dua struct yang menerapkan antarmuka pkg/toolkits/scalar.FlowAnalysis
// FlowAnalysis represents a flow analysis
type FlowAnalysis interface {
GetGraph () * graph. UnitGraph
IsForward () bool
Computations () int
FlowThrougth ( inMap * map [ any ] any , unit ssa. Instruction , outMap * map [ any ] any )
NewInitalFlow () * map [ any ] any
EntryInitalFlow () * map [ any ] any
Copy ( srcMap * map [ any ] any , dstMap * map [ any ] any )
MergeInto ( Unit ssa. Instruction , inout * map [ any ] any , in * map [ any ] any )
End ( universe [] * entry. Entry )
} dan antarmuka pkg/golang/switcher.Switcher terpisah
// Switcher represents a ssa instruction switcher
type Switcher interface {
CaseAlloc ( inst * ssa. Alloc )
CasePhi ( inst * ssa. Phi )
CaseCall ( inst * ssa. Call )
CaseBinOp ( inst * ssa. BinOp )
CaseUnOp ( inst * ssa. UnOp )
...
CaseGo ( inst * ssa. Go )
CaseDefer ( inst * ssa. Defer )
CaseSend ( inst * ssa. Send )
CaseStore ( inst * ssa. Store )
CaseMapUpdate ( inst * ssa. MapUpdate )
CaseDebugRef ( inst * ssa. DebugRef )
} Jangan khawatir untuk API ini. Cara mudah untuk mengimplementasikannya adalah dengan menggunakan komposisi seperti pkg/toolkits/scalar.BaseFlowAnalysis
// ConstantPropagationAnalysis represents a constant propagtion analysis
type ConstantPropagationAnalysis struct {
scalar. BaseFlowAnalysis
constantPropagationSwitcher * ConstantPropagationSwitcher
} dan pkg/golang/switcher.BaseSwitcher
// ConstantPropagationSwitcher represents a constant propagtion switcher
type ConstantPropagationSwitcher struct {
switcher. BaseSwitcher
constanctPropagationAnalysis * ConstantPropagationAnalysis
inMap * map [ any ] any
outMap * map [ any ] any
} Ini dapat membuat Anda fokus pada metode inti yang benar -benar Anda perlukan untuk merancang dengan cermat dalam analisis tertentu
Anda dapat mempelajari lebih banyak informasi tentang cara menggunakan Goot sebagai kerangka kerja dan cara menjalankan analisis dari contoh kecil yang saya persiapkan untuk Anda dalam cara menggunakan dan cara menjalankan yang menunjukkan constant propagation analysis
*map[any]any sebagai aliran dan ssa.Instruction