
Goot - это статическая структура анализа для GO. Goot-это простой в использовании, простой в использовании и очень расширяется, что позволяет легко разработать новые анализы.
В настоящее время Goot предоставляет следующие основные компоненты анализа (и больше анализа уже в пути):
Intal Goot By
go get -u github.com/cokeBeer/goot
Записать код ниже в проекте, который будет проанализирован, например, 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 ()
} Запустите код, и вы получите passthrough.json в одном и том же каталоге, который содержит Taint Passtorgh Information обо всех функциях в вашем проекте
Вы можете увидеть, как fmt.Sprintf содержит объект значения
{
"fmt.Sprintf" : {
"Recv" : null ,
"Results" : [
[ 0 , 1 ]
],
"Params" : [
[ 0 , 1 ],
[ 1 ]
]
}
}Это означает три вещи
Кроме того, вы получите taintgraph.json в том же каталоге
Вы можете увидеть, что файл JSON содержит распаковки от одного параметра вызова к другому параметру вызова
{
"(*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
}
} Это означает, 0 существует неподвижный край из положения 0 RunCmd (в данном случае параметр является runner.Runner StdoutPipe exec.Cmd Сам сами
Чтобы лучше просмотреть порочные края, вы можете загрузить их в NEO4J, установив эти параметры (для более подробных вариантов см. Параметры бегуна)
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 )
}
} Когда анализ окончен, вы можете найти узлы и портные края в базе данных NEO4J
Например, мы проводим анализ Taint на gitlab.com/gitlab-org/[email protected], который имеет уязвимость RCE CVE-2021-22225
Использование запроса ниже, чтобы найти порочные пути
MATCH (source:Source),(sink:Sink {name:"os/exec.CommandContext"}),p=(source)-[*7]->(sink) RETURN p
Мы можем получить график, как это: (красные узлы раковины, коричневые узлы являются внутри функциями, а зеленые узлы - источник)
Который раскрывает два пути от источника до Sine os/exec.CommandContext , так же, как CVE-2021-22225
Чтобы использовать Goot в качестве структуры, сначала создайте две структуры, внедряющие pkg/toolkits/scalar.FlowAnalysis interface.
// 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 )
} и pkg/golang/switcher.Switcher интерфейс отдельно
// 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 )
} Не волнуйтесь за эти API. Простой способ их реализации - это использование сочинения, такого как pkg/toolkits/scalar.BaseFlowAnalysis
// ConstantPropagationAnalysis represents a constant propagtion analysis
type ConstantPropagationAnalysis struct {
scalar. BaseFlowAnalysis
constantPropagationSwitcher * ConstantPropagationSwitcher
} и 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
} Они могут заставить вас сосредоточиться на основных методах, которые вам действительно необходимы для тщательного проектирования в конкретных анализах
Вы можете узнать больше информации о том , как использовать Goot в качестве рамки и как запустить анализ из крошечного примера, который я подготовил для вас в том, как использовать и как запустить, что демонстрирует constant propagation analysis
*map[any]any как поток и ssa.Instruction в качестве единицы, поэтому, пожалуйста, будьте осторожны с утверждением типа