
सुरक्षा-केंद्रित Go टूलचेन, अत्याधुनिक फ़ज़िंग क्षमताओं पर केंद्रित।
gosentry Go टूलचेन का एक सुरक्षा-केंद्रित फोर्क है, जो Go कोडबेस पर अत्याधुनिक फज़िंग अभियानों के लिए कई सुविधाओं को एकीकृत करता है। यदि आप पहले go test -fuzz का उपयोग कर रहे थे, तो आपको इसके विकल्प के रूप में gosentry का उपयोग करना चाहिए। इसमें कई फज़िंग सुधार और बग डिटेक्टर शामिल हैं जो Go टूलचेन में मूल रूप से मौजूद नहीं हैं। नीचे TLDR; देखें। आप संबंधित ब्लॉग लेख यहाँ भी पढ़ सकते हैं।
TLDR (विशेषताएं और विकल्प):
struct इनपुट को सीधे फज़ करें (कोई कस्टम पार्सर आवश्यक नहीं)। f.Add(Input{N: 7, S: "hi"}) के साथ सीड जोड़ें, फिर f.Fuzz(func(t *testing.T, in Input) { ... })।X + Y - Z X / U + Z - 14 बन सकता है, X + Yè - Z के बजायcd src && ./make.bash # Produces ../bin/go. See GOFLAGS below.
> [!TIP]
> योगदानकर्ता दस्तावेज़: कोड मैप, अनुशंसित डेव लूप, CI एंट्रीपॉइंट और बेंचमार्क स्क्रिप्ट के लिए `docs/gosentry/index.md` पढ़ें।
> यह फोर्क `golang/go:master` से `master` में PRs खोलने और ऑटो-मर्ज करने के लिए Pull GitHub App का उपयोग करता है, जिससे हम Go टूलचेन के नवीनतम अपडेट से कभी पीछे नहीं रहते हैं।
## फ़ीचर 1: स्ट्रक्चर-जागरूक फ़ज़िंग (स्ट्रक्चर को इनपुट के रूप में फ़ज़ करें)
#### अवलोकन
Go का नेटिव फ़ज़िंग (`go test -fuzz=...`) फ़ज़ पैरामीटर के रूप में केवल स्केलर प्रकारों के एक छोटे समूह का समर्थन करता है (`[]byte`, `string`, संख्याएँ, ...)। gosentry में, आप उन स्केलरों से निर्मित **कंपोज़िट प्रकारों** को भी फ़ज़ कर सकते हैं: स्ट्रक्चर, ऐरे, स्लाइस और पॉइंटर्स।
यह तब उपयोगी है जब आपका कोड स्वाभाविक रूप से संरचित इनपुट लेता है और आप कॉर्पस को सीड और म्यूटेट करने के लिए कस्टम एन्कोडर/डिकोडर नहीं बनाना चाहते हैं।
उदाहरणों के लिए `test/gosentry/examples/multiargs` और `test/gosentry/examples/composite` देखें।
#### सरल उदाहरण```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) और struct फज़िंग कैसे काम करते हैं (गोंद की परत)Go का native fuzzer किसी struct मान को सीधे फज़ नहीं कर सकता (यह केवल scalar प्रकारों की छोटी सूची को mutate करना जानता है)। gosentry एक छोटी गोंद-परत जोड़ता है: जब आपका fuzz target composite प्रकारों (जैसे Input) का उपयोग करता है, gosentry पर्दे के पीछे एक ही []byte फज़ करता है। हर निष्पादन पर, यह उन बाइट्स को आपके struct में डीकोड करता है (फ़ील्ड-दर-फ़ील्ड, slices/arrays/pointers के लिए पुनरावर्ती रूप से) और फिर डीकोड किए गए मान के साथ आपके f.Fuzz कॉलबैक को कॉल करता है। वही एन्कोडिंग seeds के लिए उपयोग होती है, इसलिए f.Add(Input{...}) एक एन्कोडेड []byte corpus entry बन जाता है जिसे fuzzer किसी भी अन्य seed की तरह पुनः उपयोग और mutate कर सकता है।
Fuzzers (LibAFL सहित) raw bytes mutate करते हैं, इसलिए हमें एक ऐसा decoder चाहिए जो किसी भी byte slice को "कुछ" struct मान में बदल सके और आगे बढ़ता रहे। JSON/gob अधिकांश रैंडम इनपुट अस्वीकार कर देंगे (कवरेज के लिए बुरा), और वे unexported फ़ील्ड्स को भी नहीं भरते, जबकि fuzzing अक्सर invariants को तोड़ने से लाभ उठाता है। यह custom format छोटा, तेज़, deterministic और malformed डेटा के प्रति सहिष्णु है।
अंदर से, यह gosentry का अपना simple binary format उपयोग करता है (gob नहीं, JSON नहीं)। कोड src/testing/libafl.go में स्थित है:
libaflMarshalInputs / libaflAppendValuelibaflUnmarshalArgs / libaflDecodeValueएन्कोडिंग नियम (high level):
bool: 1 बाइट (0 या 1)int/uint 8 बाइट्स होते हैं)float32 = 4 बाइट्स, float64 = 8 बाइट्स)string: uvarint(len) फिर raw string बाइट्स[]byte: uvarint(len) फिर raw बाइट्सuvarint(len) फिर प्रत्येक एलिमेंट एन्कोड होता है0 = nil, 1 = मौजूद) फिर pointed valueयह कार्य पहले विकसित go-panikint से प्रेरित है। यह पूर्णांक अंकगणितीय संक्रियाओं के लिए overflow/underflow का पता लगाना और (वैकल्पिक रूप से) पूर्णांक रूपांतरणों के लिए type truncation का पता लगाना जोड़ता है। जब overflow या truncation का पता चलता है, तो विस्तृत त्रुटि संदेश के साथ एक panic ट्रिगर होता है, जिसमें शामिल विशिष्ट संक्रिया प्रकार और पूर्णांक प्रकार शामिल होते हैं।
अंकगणितीय संक्रियाएँ: यह signed और unsigned दोनों प्रकार के पूर्णांकों के लिए जोड़ +, घटाव -, गुणा *, और भाग / को संभालती है। Signed पूर्णांकों के लिए, int8, int16, int32 शामिल हैं। Unsigned पूर्णांकों के लिए, uint8, uint16, uint32, uint64 शामिल हैं। भाग का मामला विशेष रूप से signed पूर्णांकों के लिए MIN_INT / -1 overflow स्थिति का पता लगाता है। int64 और uintptr की अंकगणितीय संक्रियाओं के लिए जाँच नहीं की जाती।
प्रकार truncation का पता लगाना: यह संभावित रूप से हानिपूर्ण (lossy) पूर्णांक प्रकार रूपांतरणों का पता लगाता है। सभी पूर्णांक प्रकारों को कवर करता है: int8, int16, int32, int64, uint8, uint16, uint32, uint64। uintptr को प्लेटफ़ॉर्म-निर्भर उपयोग के कारण बाहर रखा गया है। यह डिफ़ॉल्ट रूप से अक्षम है।
Overflow का पता लगाना डिफ़ॉल्ट रूप से सक्षम है। इसे अक्षम करने के लिए, अपने ./make.bash से पहले GOFLAGS='-gcflags=-overflowdetect=false' जोड़ें। आप truncation issues checker को भी इसके साथ सक्षम कर सकते हैं: -gcflags=-truncationdetect=true
यह फ़ीचर कंपाइलर की SSA जनरेशन को पैच करता है ताकि पूर्णांक अंकगणितीय संक्रियाओं और पूर्णांक रूपांतरणों को अतिरिक्त runtime जाँचें मिलें, जो किसी bug का पता चलने पर विस्तृत त्रुटि संदेश के साथ panic करने के लिए runtime में कॉल करती हैं। जाँचें source-location-आधारित फ़िल्टरिंग का उपयोग करके लागू की जाती हैं, ताकि उपयोगकर्ता कोड इंस्ट्रूमेंट किया जाए, जबकि मानक पुस्तकालय फ़ाइलें और निर्भरताएँ (module cache और vendor/) छोड़ दी जाती हैं।