أمان تطبيقات Go: أهم 10 ثغرات للمبتدئين
\n\nGo (Golang) هي واحدة من أشهر اللغات لإنشاء خدمات الويب عالية التحميل، والخدمات المصغرة، وتطبيقات الشبكات. ومع ذلك، مثل أي لغة أخرى، تتطلب Go نهجًا دقيقًا تجاه الأمان. إذا كنت قد بدأت للتو في تعلم Go، فمن المهم معرفة الثغرات الأساسية التي قد تهدد تطبيقك. في هذه المقالة، سنستعرض أكثر 10 تهديدات شيوعًا ونوضح كيفية تجنبها.
\n\n1. حقن SQL (SQL Injection)
\n\nحقن SQL هي واحدة من أقدم وأخطر الثغرات. تحدث عندما يتم إدخال إدخال المستخدم مباشرةً في استعلام SQL.
\n\nمثال على تعليمات برمجية ضعيفة:
\nfunc getUser(db *sql.DB, id string) (*User, error) {\n row := db.QueryRow("SELECT * FROM users WHERE id = " + id)\n // ...\n}\n\nكيفية الإصلاح:
\nاستخدم الاستعلامات المعلمة:
\nfunc getUser(db *sql.DB, id string) (*User, error) {\n row := db.QueryRow("SELECT * FROM users WHERE id = $1", id)\n // ...\n}\n\n2. البرمجة النصية عبر المواقع (XSS)
\n\nتحدث XSS عندما يتم عرض إدخال المستخدم غير المُنقّى على صفحة الويب. في Go، يحدث هذا غالبًا عند استخدام html/template بدلاً من text/template.
مثال على تعليمات برمجية ضعيفة:
\nfmt.Fprintf(w, "<p>مرحبًا، %s</p>", r.URL.Query().Get("name"))\n\nكيفية الإصلاح:
\nاستخدم html/template للتنقية التلقائية:
tmpl := template.Must(template.New("").Parse("<p>مرحبًا، {{.}}</p>"))\ntmpl.Execute(w, r.URL.Query().Get("name"))\n\n3. تزوير الطلبات عبر المواقع (CSRF)
\n\nهجمات CSRF تجبر المستخدم على تنفيذ إجراء غير مرغوب فيه على موقع حيث هو مُسجّل الدخول. غالبًا ما تنسى تطبيقات Go الحماية من CSRF.
\n\nالحل:
\nاستخدم مكتبة gorilla/csrf أو نفذ middleware خاص بك:
import "github.com/gorilla/csrf"\n\nfunc main() {\n r := mux.NewRouter()\n r.Use(csrf.Protect([]byte("مفتاح-32-بايت")))\n // ...\n}\n\n4. معالجة غير آمنة للأخطاء
\n\nخطأ شائع هو إرجاع رسائل خطأ النظام للمستخدم، والتي قد تكشف عن البنية الداخلية للتطبيق.
\n\nمثال على تعليمات برمجية ضعيفة:
\nif err != nil {\n http.Error(w, err.Error(), http.StatusInternalServerError)\n}\n\nكيفية الإصلاح:
\nif err != nil {\n log.Printf("خطأ: %v", err)\n http.Error(w, "خطأ داخلي في الخادم", http.StatusInternalServerError)\n}\n\n5. تسريب المعلومات عبر الرؤوس
\n\nافتراضيًا، قد يكشف خادم Go عن إصدار Go، ونوع الخادم، ومعلومات خدمة أخرى.
\n\nالحل:
\ntype secureHandler struct {\n next http.Handler\n}\n\nfunc (h *secureHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n w.Header().Set("X-Content-Type-Options", "nosniff")\n w.Header().Set("X-Frame-Options", "DENY")\n w.Header().Set("X-XSS-Protection", "1; mode=block")\n h.next.ServeHTTP(w, r)\n}\n\n6. التعامل غير الصحيح مع الـ Goroutines
\n\nالـ Goroutines هي أداة قوية في Go، لكن استخدامها غير الصحيح قد يؤدي إلى سباقات البيانات (race conditions) وتسريبات الذاكرة.
\n\nمثال على تعليمات برمجية ضعيفة:
\nvar counter int\nfor i := 0; i < 1000; i++ {\n go func() {\n counter++ // سباق بيانات!\n }()\n}\n\nكيفية الإصلاح:
\nvar mu sync.Mutex\nvar counter int\nfor i := 0; i < 1000; i++ {\n go func() {\n mu.Lock()\n counter++\n mu.Unlock()\n }()\n}\n\n7. تخزين غير آمن لكلمات المرور
\n\nتخزين كلمات المرور بنص واضح أو باستخدام تجزئات ضعيفة (MD5, SHA1) هو خطأ فادح.<