İçeriğe geç

Güvenlik En İyi Uygulamaları

Web uygulamaları saldırganlar için birincil hedeftir. Kullanıcı girdisi işleyen, veri depolayan veya ters proxy arkasında çalışan bir Gin uygulaması, üretime geçmeden önce bilinçli güvenlik yapılandırmasına ihtiyaç duyar. Bu kılavuz, en önemli savunmaları kapsar ve her birinin Gin ara katmanı ve standart Go kütüphaneleriyle nasıl uygulanacağını gösterir.

CORS yapılandırması

Cross-Origin Resource Sharing (CORS), hangi harici alanların API’nize istek yapabileceğini kontrol eder. Yanlış yapılandırılmış CORS, kötü niyetli web sitelerinin kimliği doğrulanmış kullanıcılar adına sunucunuzdan yanıtları okumasına izin verebilir.

İyi test edilmiş bir çözüm için gin-contrib/cors paketini kullanın.

package main
import (
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.Use(cors.New(cors.Config{
AllowOrigins: []string{"https://example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
MaxAge: 12 * time.Hour,
}))
r.GET("/api/data", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "ok"})
})
r.Run()
}

CSRF koruması

Cross-Site Request Forgery, kimliği doğrulanmış bir kullanıcının tarayıcısını uygulamanıza istenmeyen istekler göndermeye yönlendirir. Kimlik doğrulama için çerezlere dayanan herhangi bir durum değiştiren uç nokta (POST, PUT, DELETE) CSRF korumasına ihtiyaç duyar.

Token tabanlı koruma eklemek için gin-contrib/csrf ara katmanını kullanın.

package main
import (
"github.com/gin-contrib/csrf"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
store := cookie.NewStore([]byte("session-secret"))
r.Use(sessions.Sessions("mysession", store))
r.Use(csrf.Middleware(csrf.Options{
Secret: "csrf-token-secret",
ErrorFunc: func(c *gin.Context) {
c.String(403, "CSRF token mismatch")
c.Abort()
},
}))
r.GET("/form", func(c *gin.Context) {
token := csrf.GetToken(c)
c.JSON(200, gin.H{"csrf_token": token})
})
r.POST("/form", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "submitted"})
})
r.Run()
}

Hız sınırlama

Hız sınırlama, kötüye kullanımı, kaba kuvvet saldırılarını ve kaynak tükenmesini önler. Ara katman olarak basit bir istemci başına hız sınırlayıcı oluşturmak için standart kütüphanenin golang.org/x/time/rate paketini kullanabilirsiniz.

package main
import (
"net/http"
"sync"
"github.com/gin-gonic/gin"
"golang.org/x/time/rate"
)
func RateLimiter() gin.HandlerFunc {
type client struct {
limiter *rate.Limiter
}
var (
mu sync.Mutex
clients = make(map[string]*client)
)
return func(c *gin.Context) {
ip := c.ClientIP()
mu.Lock()
if _, exists := clients[ip]; !exists {
// Allow 10 requests per second with a burst of 20
clients[ip] = &client{limiter: rate.NewLimiter(10, 20)}
}
cl := clients[ip]
mu.Unlock()
if !cl.limiter.Allow() {
c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{
"error": "rate limit exceeded",
})
return
}
c.Next()
}
}
func main() {
r := gin.Default()
r.Use(RateLimiter())
r.GET("/api/resource", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "ok"})
})
r.Run()
}

Girdi doğrulama ve SQL enjeksiyonu önleme

Her zaman Gin’in model bağlamasını struct etiketleriyle kullanarak girdiyi doğrulayın ve bağlayın. Kullanıcı girdisini birleştirerek asla SQL sorguları oluşturmayın.

Struct etiketleriyle girdi doğrulama

type CreateUser struct {
Username string `json:"username" binding:"required,alphanum,min=3,max=30"`
Email string `json:"email" binding:"required,email"`
Age int `json:"age" binding:"required,gte=1,lte=130"`
}
func createUserHandler(c *gin.Context) {
var req CreateUser
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// req is now validated; proceed safely
}

Parametreli sorgular kullanın

// DANGEROUS -- SQL injection vulnerability
row := db.QueryRow("SELECT id FROM users WHERE username = '" + username + "'")
// SAFE -- parameterized query
row := db.QueryRow("SELECT id FROM users WHERE username = $1", username)

Bu, her veritabanı kütüphanesi için geçerlidir. database/sql, GORM, sqlx veya başka bir ORM kullanın, her zaman parametre yer tutucuları kullanın ve asla dize birleştirme yapmayın.

XSS önleme

Cross-Site Scripting (XSS), bir saldırganın diğer kullanıcıların tarayıcılarında çalışan kötü amaçlı betikler enjekte etmesi durumunda gerçekleşir. Buna karşı birden fazla katmanda savunma yapın.

HTML çıktısını kaçışlama

HTML şablonları işlerken, Go’nun html/template paketi çıktıyı varsayılan olarak kaçışlar. Kullanıcı tarafından sağlanan verileri JSON olarak döndürüyorsanız, Content-Type başlığının doğru ayarlandığından emin olun, böylece tarayıcılar JSON’u HTML olarak yorumlamaz.

// Gin sets Content-Type automatically for JSON responses.
// Use c.JSON, not c.String, when returning structured data.
c.JSON(200, gin.H{"input": userInput})

JSONP koruması için SecureJSON kullanın

Gin, JSON ele geçirmesini önlemek için while(1); ekleyen c.SecureJSON sağlar.

c.SecureJSON(200, gin.H{"data": userInput})

Gerektiğinde Content-Type’ı açıkça ayarlayın

// For API endpoints, always return JSON
c.Header("Content-Type", "application/json; charset=utf-8")
c.Header("X-Content-Type-Options", "nosniff")

X-Content-Type-Options: nosniff başlığı, tarayıcıların MIME türü koklamasını önler ve sunucu başka bir şey olarak bildirdiğinde yanıtı HTML olarak yorumlamalarını engeller.

Güvenlik başlıkları ara katmanı

Güvenlik başlıkları eklemek, en basit ve en etkili sağlamlaştırma adımlarından biridir. Ayrıntılı bir örnek için Güvenlik Başlıkları sayfasına bakın. Aşağıda temel başlıkların hızlı bir özeti bulunmaktadır.

func SecurityHeaders() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("X-Frame-Options", "DENY")
c.Header("X-Content-Type-Options", "nosniff")
c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
c.Header("Content-Security-Policy", "default-src 'self'")
c.Header("Referrer-Policy", "strict-origin")
c.Header("Permissions-Policy", "geolocation=(), camera=(), microphone=()")
c.Next()
}
}
BaşlıkNeyi önler
X-Frame-Options: DENYiframe’ler aracılığıyla clickjacking
X-Content-Type-Options: nosniffMIME türü koklama saldırıları
Strict-Transport-SecurityProtokol düşürme ve çerez ele geçirme
Content-Security-PolicyXSS ve veri enjeksiyonu
Referrer-PolicyHassas URL parametrelerinin üçüncü taraflara sızması
Permissions-PolicyTarayıcı API’lerinin yetkisiz kullanımı (kamera, mikrofon vb.)

Güvenilir proxy’ler

Uygulamanız bir ters proxy veya yük dengeleyici arkasında çalışıyorsa, Gin’e hangi proxy’lere güveneceğini söylemelisiniz. Bu yapılandırma olmadan, saldırganlar IP tabanlı erişim kontrollerini ve hız sınırlamayı atlamak için X-Forwarded-For başlığını taklit edebilir.

// Trust only your known proxy addresses
router.SetTrustedProxies([]string{"10.0.0.1", "192.168.1.0/24"})

Tam açıklama ve yapılandırma seçenekleri için Güvenilir Proxy’ler sayfasına bakın.

HTTPS ve TLS

Tüm üretim Gin uygulamaları trafiği HTTPS üzerinden sunmalıdır. Gin, Let’s Encrypt aracılığıyla otomatik TLS sertifikalarını destekler.

import "github.com/gin-gonic/autotls"
func main() {
r := gin.Default()
// ... routes ...
log.Fatal(autotls.Run(r, "example.com"))
}

Özel sertifika yöneticileri dahil olmak üzere eksiksiz kurulum talimatları için Let’s Encrypt Desteği sayfasına bakın.

Ayrıca bakınız