
gosentry v0.4.1
Toolchain de Go orientado a la seguridad, centrado en capacidades de fuzzing de última generación.
gosentry
gosentry es un fork centrado en la seguridad de la cadena de herramientas de Go, que integra numerosas funciones para campañas de fuzzing de vanguardia en bases de código Go. Si antes usabas go test -fuzz, deberías usar gosentry como reemplazo.
Incluye varias mejoras de fuzzing y detectores de errores que no están presentes de forma nativa en la cadena de herramientas de Go. Consulta el TLDR; a continuación. También puedes leer el artículo de blog asociado aquí.
TLDR (funcionalidades y opciones):
- Fuzzear entradas de tipo
structdirectamente (sin necesidad de un parser personalizado). Añadir semillas conf.Add(Input{N: 7, S: "hi"})y luegof.Fuzz(func(t *testing.T, in Input) { ... }). - Entrar en pánico ante el desbordamiento de enteros y detectar problemas aritméticos
- Fuzzear con LibAFL para técnicas de fuzzing de vanguardia como la resolución de restricciones de ruta
- Generar/mutar entradas a partir de una gramática para evitar mutaciones inútiles. La mutación genera operaciones matemáticas válidas, por ejemplo
X + Y - Zpuede convertirse enX / U + Z - 14en lugar deX + Yè - Z - Entrar en pánico en funciones seleccionadas (como registradores de errores críticos) y abortar cuando se llama
- Enfocar el fuzzer en líneas modificadas recientemente Y en nueva cobertura para apuntar principalmente a commits nuevos
- Detectar condiciones de carrera en tiempo de fuzzing
- Detectar fugas de Go en tiempo de fuzzing
- Detectar ejecuciones bloqueadas con timeouts en tiempo de fuzzing
- Generar un informe de cobertura HTML a partir del corpus de una campaña de fuzzing con una única CLI
Tabla de contenidos
- Compilación
- Funcionalidad 1: Fuzzing orientado a structs (fuzz de structs como entradas)
- Funcionalidad 2: Detección de problemas de desbordamiento y truncamiento de enteros
- Funcionalidad 3: Pánico en funciones seleccionadas
- Funcionalidad 4: Fuzzing de vanguardia con LibAFL
- Funcionalidad 5: Fuzzing orientado a git blame (experimental)
- Funcionalidad 6: Detectar condiciones de carrera, fugas de goroutines y bloqueos en tiempo de fuzzing
- Funcionalidad 7: Fuzzing basado en gramáticas (Nautilus)
- Funcionalidad 8: Generar informes de cobertura de fuzzing a partir de la campaña
- Trofeos
- Créditos
Compilación```bash
cd src && ./make.bash # Produces ../bin/go. See GOFLAGS below.
> [!TIP]
> Documentación para contribuidores: lee `docs/gosentry/index.md` para ver un mapa del código, el bucle de desarrollo recomendado, los puntos de entrada de CI y los scripts de benchmark.
> Este fork utiliza la Pull GitHub App para abrir y fusionar automáticamente los PR desde `golang/go:master` hacia `master`, asegurando que nunca nos quedemos atrás de las últimas actualizaciones de la cadena de herramientas de Go.
## Característica 1: Fuzzing consciente de structs (fuzzing de structs como entradas)
#### Resumen
El fuzzing nativo de Go (`go test -fuzz=...`) solo admite un pequeño conjunto de tipos escalares como parámetros de fuzzing (`[]byte`, `string`, números, ...). En gosentry, también puedes someter a fuzzing **tipos compuestos** construidos a partir de esos escalares: structs, arrays, slices y punteros.
Esto es útil cuando tu código acepta de forma natural entradas estructuradas y no quieres construir un codificador/decodificador personalizado solo para sembrar y mutar el corpus.
Consulta `test/gosentry/examples/multiargs` y `test/gosentry/examples/composite` para ver ejemplos.
#### Ejemplo 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")
}
})
}
Cómo funcionan las semillas de structs (f.Add) y el fuzzing de structs (el pegamento creado)
El fuzzer nativo de Go no puede fuzzear un valor struct directamente (solo sabe mutar una pequeña lista de tipos escalares). gosentry añade una pequeña capa de pegamento: cuando tu objetivo de fuzzing usa tipos compuestos (como Input), gosentry fuzzea un único []byte entre bastidores. En cada ejecución, decodifica esos bytes en tu struct (campo por campo, recursivamente para slices/arrays/punteros) y luego llama a tu callback f.Fuzz con el valor decodificado. La misma codificación se usa para las semillas, por lo que f.Add(Input{...}) se convierte en una entrada de corpus []byte codificada que el fuzzer puede reutilizar y mutar como cualquier otra semilla.
Los fuzzers (incluido LibAFL) mutan bytes crudos, por lo que queremos un decodificador que pueda convertir cualquier slice de bytes en "algún" valor de struct y seguir adelante. JSON/gob rechazarían la mayoría de las entradas aleatorias (malo para la cobertura), y además no pueblan campos no exportados, mientras que el fuzzing a menudo se beneficia de romper invariantes. Este formato personalizado es pequeño, rápido, determinista y tolerante a datos malformados.
Bajo el capó, esto usa el propio formato binario simple de gosentry (ni gob, ni JSON). El código vive en src/testing/libafl.go:
- Codificar:
libaflMarshalInputs/libaflAppendValue - Decodificar:
libaflUnmarshalArgs/libaflDecodeValue
Reglas de codificación (alto nivel):
bool: 1 byte (0o1)- Enteros: bytes little-endian (
int/uintson 8 bytes) - Flotantes: bits IEEE-754 en little-endian (
float32= 4 bytes,float64= 8 bytes) string:uvarint(len)y luego bytes crudos de la cadena[]byte:uvarint(len)y luego bytes crudos- Otros slices:
uvarint(len)y luego cada elemento codificado - Structs: campos codificados en orden de declaración
- Punteros: 1 byte (
0= nil,1= presente) y luego el valor apuntado
Feature 2: Detección de problemas de desbordamiento de enteros y truncamiento
Descripción general
Este trabajo está inspirado en el go-panikint desarrollado anteriormente. Añade detección de desbordamiento/subdesbordamiento para operaciones aritméticas con enteros y (opcionalmente) detección de truncamiento de tipos para conversiones de enteros. Cuando se detecta un desbordamiento o truncamiento, se lanza un panic con un mensaje de error detallado, incluyendo el tipo de operación específico y los tipos de enteros implicados.
Operaciones aritméticas: Gestiona la suma +, la resta -, la multiplicación * y la división / para tipos de enteros tanto con signo como sin signo. Para enteros con signo, cubre int8, int16, int32. Para enteros sin signo, cubre uint8, uint16, uint32, uint64. El caso de la división detecta específicamente la condición de desbordamiento MIN_INT / -1 para enteros con signo. int64 y uintptr no se comprueban para operaciones aritméticas.