
سلسلة أدوات Go موجّهة نحو الأمن، تركّز على قدرات Fuzzing على أحدث مستوى.
gosentry هو فرع (fork) من سلسلة أدوات Go تركّز على الأمان، يدمج العديد من الميزات لحملات التضمين (fuzzing) المتطورة على قواعد أكواد 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è - Zcd src && ./make.bash # Produces ../bin/go. See GOFLAGS below.
> [!TIP]
> وثائق المساهمين: اقرأ `docs/gosentry/index.md` للحصول على خريطة الكود، وحلقة التطوير الموصى بها، ونقاط دخول CI، وسكربتات القياس.
> يستخدم هذا الفرع تطبيق Pull GitHub لفتح ودمج PRs تلقائيًا من `golang/go:master` إلى `master`، مما يضمن ألا نتخلف أبدًا عن أحدث تحديثات سلسلة أدوات Go.
## الميزة 1: الاختبار التلقائي المبني على البنى (fuzz structs كمدخلات)
#### نظرة عامة
الاختبار التلقائي الأصلي في Go (`go test -fuzz=...`) يدعم فقط مجموعة صغيرة من الأنواع العددية كوسائط للاختبار التلقائي (`[]byte`, `string`, أرقام, ...). في gosentry، يمكنك أيضًا اختبار **الأنواع المركبة** المبنية من تلك الأنواع العددية: البنى (structs)، المصفوفات، الشرائح، والمؤشرات.
هذا مفيد عندما يتلقى الكود الخاص بك مدخلات منظمة بشكل طبيعي ولا تريد بناء مُرمِّز/مُفكِّك ترميز مخصص فقط لتزويد المجموعة (corpus) وتغييرها.
انظر `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) والتفزيز البنيوي (اللاصق المُصنَّع)لا يمكن للمفزز الأصلي في Go تفزيز قيمة struct مباشرة (فهو يعرف فقط كيفية تحوير قائمة صغيرة من الأنواع العددية). يضيف gosentry طبقة لاصقة صغيرة: عندما يستهدف المفزز أنواعًا مركّبة (مثل Input)، يقوم gosentry بتفزيز []byte واحدة خلف الكواليس. في كل تنفيذ، يقوم بفك ترميز تلك البايتات إلى البنية الخاصة بك (حقلًا بحقل، وبشكل تكراري للمقاطع/المصفوفات/المؤشرات) ثم يستدعي رد اتصال f.Fuzz بالقيمة المفكوكة. يُستخدم نفس الترميز للبذور، لذا فإن f.Add(Input{...}) يصبح إدخال مجموعة بايتات مشفّرة يمكن للمفزز إعادة استخدامها وتحويرها مثل أي بذرة أخرى.
تقوم المفززات (بما فيها LibAFL) بتحوير البايتات الخام، لذلك نريد وحدة فك ترميز يمكنها تحويل أي شريحة بايتات إلى قيمة بنية "ما" والاستمرار. JSON/gob سترفض معظم المدخلات العشوائية (أمر سيء للتغطية)، كما أنها لا تملأ الحقول غير المُصدَّرة، بينما غالبًا ما يستفيد التفزيز من كسر القيود الثابتة. هذا التنسيق المخصص صغير وسريع وحتمي ومتسامح مع البيانات التالفة.
في الكواليس، يستخدم هذا تنسيق gosentry الثنائي البسيط الخاص (ليس gob وليس JSON). الكود موجود في src/testing/libafl.go:
libaflMarshalInputs / libaflAppendValuelibaflUnmarshalArgs / libaflDecodeValueقواعد الترميز (بشكل عام):
bool: 1 بايت (0 أو 1)int/uint حجمها 8 بايتات)float32 = 4 بايتات، float64 = 8 بايتات)string: uvarint(len) ثم بايتات السلسلة الخام[]byte: uvarint(len) ثم البايتات الخامuvarint(len) ثم ترميز كل عنصر0 = فارغ، 1 = موجود) ثم القيمة المُشار إليهاهذا العمل مستوحى من الأداة المطورة سابقًا go-panikint. يضيف كشفًا للتجاوز (overflow) والتجاوز السفلي (underflow) في العمليات الحسابية على الأعداد الصحيحة، و(اختياريًا) كشفًا لاقتطاع الأنواع في تحويلات الأعداد الصحيحة. عند اكتشاف تجاوز أو اقتطاع، يُطلق panic برسالة خطأ مفصلة، تشمل نوع العملية المحدد والأنواع الصحيحة المعنية.
العمليات الحسابية: تتعامل مع الجمع + والطرح - والضرب * والقسمة / لكل من الأنواع الصحيحة الموقّعة وغير الموقّعة. للأعداد الموقّعة، تشمل int8 وint16 وint32. للأعداد غير الموقّعة، تشمل uint8 وuint16 وuint32 وuint64. حالة القسمة تكشف تحديدًا حالة التجاوز MIN_INT / -1 للأعداد الموقّعة. int64 وuintptr لا يتم فحصهما في العمليات الحسابية.
كشف اقتطاع النوع: يكشف تحويلات الأنواع الصحيحة التي قد تسبب فقدانًا للبيانات. يشمل جميع الأنواع الصحيحة: int8 وint16 وint32 وint64 وuint8 وuint16 وuint32 وuint64. يستبعد uintptr بسبب استخدامه المعتمد على المنصة. هذا معطّل افتراضيًا.
كشف التجاوز مفعّل افتراضيًا. لتعطيله، أضف GOFLAGS='-gcflags=-overflowdetect=false' قبل تنفيذ ./make.bash. يمكنك أيضًا تفعيل فاحص الاقتطاع بإضافة: -gcflags=-truncationdetect=true
تقوم هذه الميزة بتعديل توليد SSA في المترجم بحيث تحصل العمليات الحسابية على الأعداد الصحيحة وتحويلات الأعداد الصحيحة على فحوصات إضافية في زمن التشغيل تستدعي بيئة التشغيل لإطلاق panic برسالة خطأ مفصلة عند اكتشاف خطأ. تُطبَّق الفحوصات باستخدام تصفية مبنية على موقع المصدر بحيث يتم تزويد كود المستخدم بالفاحصات بينما يتم تخطي ملفات المكتبة القياسية والتبعيات (ذاكرة الوحدات وvendor/).
يمكنك قراءة مقالة المدونة المرتبطة بهذا الموضوع هنا.
أضف علامة على نفس سطر العملية أو السطر الذي يسبقه مباشرة لكبت تقرير محدد:
overflow_false_positivetruncation_false_positive