أمان تطبيقات Go: أهم 10 ثغرات وطرق الحماية
لغة Go (Golang) اكتسبت شعبية بفضل أدائها العالي، وبساطتها، وآليات الأمان المدمجة. ومع ذلك، مثل أي لغة أخرى، فهي لا تحمي المطور من جميع التهديدات المحتملة. يمكن أن تؤدي أخطاء التصميم، وعدم الانتباه عند التعامل مع البيانات الخارجية، والاستخدام غير الصحيح للمكتبات القياسية إلى ثغرات خطيرة. في هذه المقالة، سنستعرض أهم 10 ثغرات حرجة في تطبيقات Go، ونقدم أمثلة على الكود، ونشرح كيفية تجنبها.
1. حقن SQL (SQL Injection)
على الرغم من وجود حزمة database/sql، غالبًا ما يقع المطورون في خطأ دمج السلاسل النصية عند بناء استعلامات SQL. هذه ثغرة كلاسيكية تسمح للمهاجم بتنفيذ كود SQL عشوائي.
كود غير آمن:
// خطير: دمج السلاسل النصيةfunc getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") query := "SELECT * FROM users WHERE username = '" + username + "'" rows, err := db.Query(query) // ...}كود آمن باستخدام المعلمات:
func getUser(w http.ResponseWriter, r *http.Request) { username := r.URL.Query().Get("username") // نستخدم العناصر النائبة query := "SELECT * FROM users WHERE username = $1" rows, err := db.Query(query, username) // ...}توصية: استخدم دائمًا الاستعلامات المعلمة. لا تقم أبدًا بدمج إدخال المستخدم في سلاسل SQL.
2. البرمجة النصية عبر المواقع (XSS)
إذا كان تطبيق Go الخاص بك يقوم بعرض HTML على الخادم (على سبيل المثال، باستخدام html/template)، فيجب عليك ترميز المخرجات. الحزمة المدمجة text/template لا تقوم بذلك.
كود غير آمن:
// استخدام text/template خطيرtmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})كود آمن:
// استخدم دائمًا html/template لقالب HTMLimport "html/template"tmpl, _ := template.New("test").Parse("<h1>{{.Name}}</h1>")tmpl.Execute(w, map[string]string{"Name": "<script>alert('XSS')</script>"})// المخرجات: <script>alert('XSS')</script>توصية: للعمل مع HTML، استخدم فقط html/template. قم دائمًا بالتحقق من صحة وترميز إدخال المستخدم، خاصة إذا تم إخراجه في سمات العلامات أو JavaScript.
3. حالة السباق (Race Condition)
Go هي لغة متزامنة، وحالة السباق هي واحدة من أكثر المشاكل شيوعًا. يمكن أن تؤدي إلى تلف البيانات، وتسرب الذاكرة، وأعطال غير متوقعة.
كود غير آمن:
var counter int
func increment() { for i := 0; i < 1000; i++ { counter++ // عملية غير ذرية }}
func main() { go increment() go increment()}كود آمن باستخدام الميوتكس (Mutex):
var ( counter int mu sync.Mutex)
func increment() { for i := 0; i < 1000; i++ { mu.Lock() counter++ mu.Unlock() }}
func main() { go increment() go increment()}توصية: استخدم sync.Mutex أو sync.RWMutex أو العمليات الذرية (sync/atomic). قم بتشغيل الاختبارات مع العلم -race لاكتشاف حالات السباق.
4. اجتياز المسار (Path Traversal)
تنشأ الثغرة عندما يستخدم التطبيق إدخال المستخدم لتكوين مسار ملف دون التحقق المناسب.
كود غير آمن:
func serveFile(w http.ResponseWriter, r *http.Request) { f