实现自己的应用防火墙

199 阅读6分钟

1 前言

中小型应用的安全是个头疼的问题。买大型厂家的产品不划算,裸奔在公网又不现实。 那么就让我们来实现自己的应用防火墙吧。

应用防火墙(WAF)是一种专门用于保护Web应用的安全解决方案,能够过滤、监控并阻止对Web应用的恶意HTTP流量。

WAF的主要目标是防止应用层攻击,如SQL注入、跨站脚本攻击 (XSS)、跨站请求伪造 (CSRF)、文件包含漏洞等。通过分析HTTP流量,WAF可以识别并阻止恶意请求,确保Web服务的正常运行和数据的安全性。

入侵检测系统 (IDS) 监控网络上的流量,分析该流量中与已知攻击匹配的签名,并在发生可疑情况时向您发出警报。与此同时,流量继续流动。

它还监控流量。但是当发生异常情况时,通信会完全停止,直到您调查并决定再次打开闸门。

入侵防御系统 (IPS) 或入侵检测和防御系统 (IDPS) 是网络安全应用程序,专注于识别可能的恶意活动、记录信息、报告尝试并尝试阻止它们。IPS 系统通常直接位于防火墙后面。

这里实现一个简单Web应用防火墙 (WAF) 和一个简单的入侵检测系统 (IDS) 与入侵防御系统 (IPS) 示例代码。

本文将演示如何在服务中设置中间件来检测并过滤常见攻击,如SQL注入和XSS攻击,展示如何实时检测并阻止Web应用中的可疑行为或恶意流量。。

2 实现思路

中间件检测:在请求到达处理器之前,通过web框架的中间件对请求参数进行过滤和检查,在请求进入处理器之前,通过框架的中间件检查请求的可疑行为。

规则匹配:定义一系列常见的恶意行为特征(如暴力登录、恶意爬取、异常请求频率等)。 SQL注入检测:检查请求参数中是否包含常见的SQL注入关键字(如SELECT、DROP、INSERT等)。

XSS检测:检测参数中是否包含潜在的XSS代码(如script标签、javascript:协议等)。 日志记录:记录可疑请求信息,便于后续审查和分析。 阻止策略:当检测到恶意行为时,可以记录并拦截请求,同时限制相关IP或用户。

  • IPS的实现

     // 可疑IP的请求次数限制
     const requestLimit = 10
     const blockDuration = time.Minute * 10
     
     // 存储IP请求统计信息
     var ipRequestCount = make(map[string]int)
     var blockedIPs = make(map[string]time.Time)
     var mu sync.Mutex
     
     
     // IDS/IPS中间件函数,用于实时检测和阻止可疑行为
     func IPSMiddleware() gin.HandlerFunc {
         return func(c *gin.Context) {
             clientIP := c.ClientIP()
    
             mu.Lock()
             defer mu.Unlock()
    
             // 检查IP是否在封禁列表中
             if blockTime, exists := blockedIPs[clientIP]; exists {
                     if time.Now().Before(blockTime) {
                             log.Printf("Blocked IP %s trying to access", clientIP)
                             c.JSON(http.StatusForbidden, gin.H{"error": "Your IP has been temporarily blocked due to suspicious activity"})
                             c.Abort()
                             return
                     } else {
                             // 解封已到期的IP
                             delete(blockedIPs, clientIP)
                     }
             }
    
             // 增加IP的请求计数
             ipRequestCount[clientIP]++
             log.Printf("IP %s request count: %d", clientIP, ipRequestCount[clientIP])
    
             // 检测是否达到请求限制,若达到则封禁
             if ipRequestCount[clientIP] > requestLimit {
                     log.Printf("IP %s has been blocked due to too many requests", clientIP)
                     blockedIPs[clientIP] = time.Now().Add(blockDuration)
                     delete(ipRequestCount, clientIP) // 重置计数
                     c.JSON(http.StatusForbidden, gin.H{"error": "Your IP has been temporarily blocked due to suspicious activity"})
                     c.Abort()
                     return
             }
    
             // 设置请求完成后的钩子来减少计数
             c.Next()
             ipRequestCount[clientIP]--
     }
    

应用防火墙WAF的实现

    // WAF中间件函数,用于过滤SQL注入和XSS攻击
func WAFMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取请求参数(查询参数和表单数据)
		params := c.Request.URL.Query()
		if err := c.Request.ParseForm(); err == nil {
			for key, values := range c.Request.PostForm {
				params[key] = values
			}
		}

		// 遍历所有请求参数,检测潜在的攻击行为
		for key, values := range params {
			for _, value := range values {
				// 检测SQL注入
				if isSQLInjection(value) {
					log.Printf("SQL Injection detected in parameter '%s' with value '%s'", key, value)
					c.JSON(http.StatusForbidden, gin.H{"error": "SQL Injection detected"})
					c.Abort()
					return
				}

				// 检测XSS攻击
				if isXSSAttack(value) {
					log.Printf("XSS detected in parameter '%s' with value '%s'", key, value)
					c.JSON(http.StatusForbidden, gin.H{"error": "XSS detected"})
					c.Abort()
					return
				}
			}
		}

		// 若未检测到异常,继续处理请求
		c.Next()
	}
}
    


// 判断是否存在SQL注入攻击
func isSQLInjection(value string) bool {
	sqlInjectionPattern := `(?i)(\b(SELECT|INSERT|UPDATE|DELETE|DROP|ALTER|UNION|--|;|'|")\b)`
	matched, _ := regexp.MatchString(sqlInjectionPattern, value)
	return matched
}

// 判断是否存在XSS攻击
func isXSSAttack(value string) bool {
	xssPattern := `(?i)(<script.*?>|</script>|javascript:|on\w+\s*=)`
	matched, _ := regexp.MatchString(xssPattern, value)
	return matched
}
  • 服务绑定和应用

          func main() {
                  // 创建Gin路由
                  r := gin.Default()
    
                   // 注册IPS中间件
                  r.Use(IPSMiddleware())
    
                  // 注册WAF中间件
                  r.Use(WAFMiddleware())
    
                  // 示例路由
                  r.GET("/hello", func(c *gin.Context) {
                          name := c.Query("name")
                          c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("Hello, %s!", name)})
                  })
    
                  // 启动服务器
                  if err := r.Run(":8080"); err != nil {
                          log.Fatalf("Server failed to start: %v", err)
                  }
          }
    
  • 函数说明

ipRequestCount用于跟踪每个IP的请求次数。

blockedIPs记录被暂时封禁的IP及其解封时间。

IPSMiddleware:这是IPS的核心中间件,用于实时检测和阻止过多请求的IP。

请求次数检查:每次请求时,根据IP计数,若请求次数超过指定限制(requestLimit),则该IP被暂时封禁blockDuration。

解封逻辑:当封禁时间过期后,IP会自动从封禁列表中移除。 减少计数:请求完成后,将请求计数减少,以防止偶然的高频请求导致误封。 示例路由:应用程序提供一个简单的/hello路由,可以用来测试IPS功能。

WAFMiddleware:这是主WAF中间件,用于检查请求参数中的潜在攻击特征。对每个参数执行SQL注入和XSS检查。

isSQLInjection:使用正则表达式检测SQL注入攻击。匹配常见的SQL关键字和特殊字符,如SELECT、INSERT、–等。

isXSSAttack:使用正则表达式检测XSS攻击,匹配常见的XSS特征,如

路由设置:应用程序设置了一个简单的路由/hello,用于测试。若访问路径中带有潜在的攻击参数(例如/hello?name=),请求会被拦截。

3 运行和测试

启动服务器,运行以下命令:

go run main.go

测试SQL注入攻击:

curl "http://localhost:8080/hello?name=' OR 1=1--"

应该返回:

{"error": "SQL Injection detected"}

测试XSS攻击:

curl "http://localhost:8080/hello?name=<script>alert(1)</script>"

应该返回:

{"error": "XSS detected"}

使用以下命令模拟多次请求以触发防护系统:

        for i in {1…15}; do curl -s “http://localhost:8080/hello”; done

在达到请求次数限制后,应该收到如下消息:

        {“error”: “Your IP has been temporarily blocked due to suspicious activity”}

4 小结

许多人将入侵防御系统视为入侵检测系统的扩展,因为它们都监控网络流量和/或系统活动是否存在恶意活动。IPS 解决方案还可用于识别安全策略问题、记录现有威胁以及阻止个人违反安全策略。要阻止攻击,IPS 可以通过重新配置防火墙或更改攻击内容来更改安全环境。

此简单WAF与IDS/IPS实现可用于快速检测异常流量,为实际生产系统提供基础防护。它们具备以下基本功能:

多维度检测:除了请求频率,还可以根据请求内容(如SQL注入和XSS特征)进一步识别恶意流量。
分布式计数器:在分布式系统中,可以将IP计数存储在Redis中,方便共享数据。
告警和日志系统:将检测到的可疑行为记录到专门的日志系统,结合告警机制进行实时监控。