paint-brush
保护您的 Web 应用程序:速率限制和暴力攻击预防指南经过@shad0wpuppet
27,347 讀數
27,347 讀數

保护您的 Web 应用程序:速率限制和暴力攻击预防指南

经过 Konstantin Sakhchinskiy4m2024/01/22
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

实施强大的速率限制措施对于 Web 应用程序防止暴力攻击和潜在的服务过载至关重要。速率限制技术以及对测试和绕过速率限制的见解。本文涵盖了自动化方法、标头操作、端点变化和登录相关策略。还探讨了使用 Cloudflare 恢复原始访问者 IP,并在实施之前谨慎彻底测试和评估对应用程序的潜在影响。
featured image - 保护您的 Web 应用程序:速率限制和暴力攻击预防指南
Konstantin Sakhchinskiy HackerNoon profile picture
0-item


如果您的应用程序包含登录、注册、密码重置/恢复、重新发送确认链接以及其他需要服务器请求的特定功能等基本功能,那么实施防止暴力攻击和在服务上产生大量负载的机制至关重要。如果没有此类机制,您的应用程序可能容易受到各种威胁,包括向用户发送过多的电子邮件/OTP,从而可能导致财务和声誉损失。


许多Web应用程序缺乏足够的速率限制措施,仅依赖于其业务逻辑施加的限制,例如基于支付模型限制请求数量。然而,某些应用程序确实包含速率限制,特别是对于登录尝试、注册和其他关键功能等操作。这些实现通常依赖于 X-Forwarded-For 标头来进行 IP 地址跟踪。


为了说明一个简单的例子,我在Flask上想出了这个代码片段


from flask import Flask, request, jsonify from flask_limiter import Limiter from flask_limiter.util import get_remote_address app = Flask(__name__) limiter = Limiter(    app,    key_func=get_remote_address,    storage_uri="memory://",) def get_ipaddr():    # Retrieve the client's IP address from the request    # X-Forwarded-For header is used to handle requests behind a proxy    ip_address = request.headers.get('X-Forwarded-For', request.remote_addr)    return ip_address # Rate limit to 5 requests per minute per IP @limiter.limit("5 per minute") @app.route('/') def index(): ip_address = get_ipaddr() return ip_address

在以下部分中,我将解释测试和尝试绕过应用程序中的速率限制的各种方法。


为了有效地测试您的应用程序是否存在此类漏洞,自动化是一个强大的工具。您可以通过使用脚本(例如 Python 中的脚本)(就像我经常做的那样)或使用 Burp Suite 等工具(顺便说一句,对于测试人员和网络安全专业人员来说是一个很棒的工具)来实现这一点。此外,像 Postman 这样的工具可以用来相对容易地实现自动化检查。

测试率限制

更改 X-Forwarded-For 标头中的 IP 值

X-Originating-IP: 127.0.0.1

在您发送的每个请求中使用不同的 IP 值。


使用双 X-Forwared-For 标头。

 X-Forwarded-For: X-Forwarded-For: 127.0.0.1

使用不同的标头尝试相同的操作。

 X-Originating-IP: 127.0.0.1 X-Remote-IP: 127.0.0.1 X-Remote-Addr: 127.0.0.1 X-Client-IP: 127.0.0.1 X-Host: 127.0.0.1 X-Forwared-Host: 127.0.0.1

更改其他标头

尝试更改用户代理、内容类型、接受语言等,或 cookie,任何可用作用户标识符的内容。


如果每个 IP 尝试 3 次的速率限制,则每 3 次尝试更改标头的 IP 值(或请求中的其他标头或参数)。

在params中添加空白字符

尝试添加到您发送的参数中

%00, %0d%0a, %0d, %0a, %09, %0C, %20

例如

param1=value1%%0d%0a param2=value2%00

例如,如果您请求 OTP 进行电子邮件验证,而您只有 3 次尝试,请使用这 3 次尝试

[email protected] [email protected]%00 [email protected]%0d%0a And so on

使用相似的端点

例如,如果您正在测试 /API/v1/signup 端点,请尝试对 /Signup、/SignUp、/sign-up 执行暴力破解。尝试将空白字符(从上面)添加到原始端点。

向请求的 API 端点添加额外参数

如果限制是针对 /api/v1/resetpassword 端点的请求,请尝试通过添加一些查询参数来强制执行 - 一旦达到速率限制,请尝试例如 /api/v1/resetpassword?param1=value1

登录很重要

应用程序可能存在逻辑缺陷 - 如果您在每次尝试/一系列尝试之前登录您的帐户,则您的 IP 的速率限制将被重置,并且您可以继续密码暴力攻击。如果您正在测试登录功能,则可以在 Burp Suit 中通过设置中的 Pitchfork 攻击(或者您可以为此编写自己的脚本)为每次尝试/一系列尝试执行此操作。


下面是我如何自动对 X-Forwarded-For 标头进行简单检查以获取 POW 的示例:


 from random import randint import requests import json url = "https://yourapp.net/api/v1/regconfirm-resend" data = {   "email": "[email protected]" } N = 100 def generate_random_ip():   return '.'.join(       str(randint(0, 255)) for _ in range(4)   ) for _ in range(N):   headers = {       "Host": "yourapp.net",       "Content-Type": "application/json",       "X-Forwarded-For": generate_random_ip()   }   response = requests.post(url, headers=headers, data=json.dumps(data))   print(headers)   print(f"Status Code: {response.status_code}, Response: {response.text}")

恢复原始访客IP

一个可能的解决方案可能是使用 Cloudflare 及其机制。详细的解释可以在这里找到restoring-original-visitor-ips 。我将仅简要概述其防御机制。


如果您使用的应用程序依赖于原始访问者的传入 IP 地址,则默认情况下会记录 Cloudflare IP 地址。原始访问者 IP 地址出现在名为 CF-Connecting-IP 的附加 HTTP 标头中。按照我们的网络服务器说明,您可以在源服务器上记录原始访问者 IP 地址。如果请求到达源服务器时此 HTTP 标头不可用,请检查您的转换规则和托管转换配置。


如果伪 IPv4 设置为覆盖标头 - Cloudflare 会使用伪 IPv4 地址覆盖现有的 Cf-Connecting-IP 和 X-Forwarded-For 标头,同时保留 CF-Connecting-IPv6 标头中的真实 IPv6 地址。


注意:请记住,在实施此类防御机制时,请执行彻底的测试。这种方法随后可能会应用于整个集群,并可能对某些不必要的功能和微服务产生不利影响。简而言之,在修复安全漏洞时要小心,因为它可能会影响整个应用程序。分析系统的哪个部分可能会受到负面影响,并在将更改发送到产品环境之前测试所有内容。


也发布在这里