
Chaîne d'outils Go orientée sécurité, axée sur des capacités de fuzzing de pointe.
gosentry est un fork de la chaîne d'outils Go axé sur la sécurité, intégrant de nombreuses fonctionnalités pour des campagnes de fuzzing de pointe sur des codebases Go. Si vous utilisiez go test -fuzz auparavant, vous devriez utiliser gosentry comme remplacement.
Il est fourni avec diverses améliorations de fuzzing et détecteurs de bogues qui ne sont pas présents nativement dans la chaîne d'outils Go. Voir TLDR ; ci-dessous. Vous pouvez également lire l'article de blog associé ici.
TLDR (fonctionnalités et options) :
struct (aucun analyseur personnalisé n'est nécessaire). Ajoutez des graines avec f.Add(Input{N: 7, S: "hi"}) puis f.Fuzz(func(t *testing.T, in Input) { ... }).X + Y - Z peut devenir X / U + Z - 14 au lieu de X + Yè - Zcd src && ./make.bash # Produces ../bin/go. See GOFLAGS below.
> [!TIP]
> Documentation contributeur : consultez `docs/gosentry/index.md` pour une carte du code, une boucle de développement recommandée, les points d'entrée CI et les scripts de benchmark.
> Ce fork utilise l'application GitHub Pull pour ouvrir et fusionner automatiquement les PR de `golang/go:master` vers `master`, garantissant que nous ne restons jamais en retard sur les dernières mises à jour de la chaîne d'outils Go.
## Fonctionnalité 1 : Fuzzing conscient des structures (fuzzer des structures en entrée)
#### Aperçu
Le fuzzing natif de Go (`go test -fuzz=...`) ne prend en charge qu'un petit ensemble de types scalaires comme paramètres de fuzzing (`[]byte`, `string`, nombres, ...). Dans gosentry, vous pouvez également fuzzer des **types composites** construits à partir de ces scalaires : structures, tableaux, slices et pointeurs.
Cela est utile lorsque votre code prend naturellement des entrées structurées et que vous ne souhaitez pas créer un encodeur/décodeur personnalisé uniquement pour amorcer et muter le corpus.
Voir `test/gosentry/examples/multiargs` et `test/gosentry/examples/composite` pour des exemples.
#### Exemple simple```go
type Input struct {
Data []byte
S string
N int
OK bool
}
func FuzzStructInput(f *testing.F) {
// Seed the initial corpus with a Go struct (gosentry feature).
f.Add(Input{Data: []byte("A"), S: "B", N: 7, OK: true})
f.Fuzz(func(t *testing.T, in Input) {
if in.OK && in.N == 1337 && in.S == "BOOMMOOB" && bytes.Equal(in.Data, []byte("A")) {
t.Fatalf("boom")
}
})
}
f.Add) et le fuzzing de structs (le lien ainsi créé)Le fuzzer natif de Go ne peut pas fuzzer une valeur struct directement (il ne sait muter qu'une petite liste de types scalaires). gosentry ajoute une petite couche de liaison : lorsque votre cible de fuzzing utilise des types composites (comme Input), gosentry fuzz un simple []byte en coulisses. À chaque exécution, il décode ces octets dans votre struct (champ par champ, récursivement pour les slices/tableaux/pointeurs), puis appelle votre rappel f.Fuzz avec la valeur décodée. Le même encodage est utilisé pour les seeds, de sorte qu'un f.Add(Input{...}) devient une entrée de corpus []byte encodée que le fuzzer peut réutiliser et muter comme n'importe quelle autre seed.
Les fuzzers (y compris LibAFL) mutent des octets bruts, nous voulons donc un décodeur capable de transformer n'importe quelle tranche d'octets en une valeur de struct « quelconque » et de continuer. JSON/gob rejetteraient la plupart des entrées aléatoires (mauvais pour la couverture) et ne rempliraient pas non plus les champs non exportés, alors que le fuzzing bénéficie souvent de la rupture des invariants. Ce format personnalisé est petit, rapide, déterministe et tolérant aux données malformées.
Sous le capot, cela utilise le propre format binaire simple de gosentry (pas gob, pas JSON). Le code se trouve dans src/testing/libafl.go :
libaflMarshalInputs / libaflAppendValuelibaflUnmarshalArgs / libaflDecodeValueRègles d'encodage (niveau haut) :
bool : 1 octet (0 ou 1)int/uint font 8 octets)float32 = 4 octets, float64 = 8 octets)string : uvarint(len) puis les octets bruts de la chaîne[]byte : uvarint(len) puis les octets brutsuvarint(len) puis chaque élément encodé0 = nil, 1 = présent) puis la valeur pointéeCe travail s'inspire du go-panikint développé précédemment. Il ajoute la détection des débordements/sous-dépassements pour les opérations arithmétiques sur les entiers et (optionnellement) la détection des troncatures de type pour les conversions d'entiers. Lorsqu'un débordement ou une troncature est détecté, une panique avec un message d'erreur détaillé est déclenchée, incluant le type d'opération spécifique et les types d'entiers impliqués.