【问题标题】:Hiding API URLs and Prevent Brute Force Attacks隐藏 API URL 并防止暴力攻击
【发布时间】:2016-03-22 18:48:50
【问题描述】:

我刚刚在 node 中构建了一个 API。

我在我的 Angular 应用程序中调用此 API 来执行登录和注册等基本操作,例如:

self.register = function(username, password) {
  return $http.post(API + '/auth/register', {
      username: username,
      password: password
    })
}

所以我的问题是,任何人都可以看到该 API URL,所以是什么阻止他们“抨击”它以在那里创建用户。 (注意 API 在我的 JS 文件中是一个常量)。 登录也是如此,如何阻止某人暴力尝试数百万个用户名和密码组合。

你会推荐什么来保护这个?

谢谢。

【问题讨论】:

标签: angularjs node.js api security


【解决方案1】:

您可以使用一些 DDoS 保护,例如将 nginx 代理放在您的 nodejs API 前面并使用例如limit_req模块:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

对于蛮力,您可以实施一些锁定逻辑,在错误数量之后会阻止帐户一段时间,例如15-30 分钟甚至需要管理员操作。

对于需要登录的 API,您可以使用令牌保护。应在调用身份验证 API 时颁发令牌,并通过 HTTP 仅安全 cookie 进行设置作为响应。然后,您可以在 API 请求标头中传递此令牌,并且在 nodejs 中每个受保护的 API 执行之前检查它是否有效,如果不是则拒绝调用。

【讨论】:

【解决方案2】:

+1 惊吓龙。

如果您生活在云端,则有一个更好的基于云的替代方案来使用 nginx - 使用云 WAF(Web 应用程序防火墙)作为您的 DDoS 缓解层。例如查看 Incapsula 和 CloudFlare。

如果 DDoS 对您来说是一个严重的问题,并且您愿意为防御它付费,那么我肯定会将这一问题留给专家。

【讨论】:

    【解决方案3】:

    您基本上是在询问注册滥用和登录保护:

    1. 如何缓解帐户创建自动化?
    2. 如何减少用户/密码猜测?

    谢天谢地,这些问题大多已解决。

    为避免注册“抨击”,您需要中断自动化。这可以通过各种方法来实现,从宽松到严格:

    1. 如果 API 仅供特定应用/浏览器访问,您可以过滤掉所有其他访问者
    2. 按会话/IP 进行速率限制注册
    3. 需要通过验证码
    4. 验证电子邮件地址
    5. 要求提供私人敏感详细信息作为身份证明(例如电话号码、信用卡)

    这样做的好处是,1-3 是可以轻松卸载到现代Web Application Firewall 的任务,无需任何额外的服务器端编码或额外负载。

    对于“登录保护”,除了上述1-3种方法外,还有两种推荐:

    1. Two-Factor Authentication (2FA) - 这基本上意味着除了他的“常规”密码外,用户还需要输入另一个身份验证令牌。此令牌可以由 TOTP(参见 Google Authenticator)生成,也可以由服务器通过短信、电子邮件、电话等方式发送的代码生成。

    2. API Keys - 这被认为更安全,因为 API 密钥通常是非常长的唯一字符串,具有非常好的熵(与用户/密码组合相比)。有关 API 密钥的更多信息here

    在我走之前,有一个小评论:我看到一些以前的 cmets 提到 DDoS,我不能强调这一点 - 你不能靠自己来缓解 DDoS。但那是针对不同的线程。

    祝你好运!

    【讨论】:

      【解决方案4】:

      最好通过 IP 限制反向代理、负载均衡器或任何其他入口点的速率。

      如果你想在 nodejs 中做,我推荐rate-limiter-flexible

      const { RateLimiterRedis } = require('rate-limiter-flexible');
      const Redis = require('ioredis');
      
      const redisClient = new Redis({
        options: {
          enableOfflineQueue: false
        }
      });
      
      const opts = {
        redis: redisClient,
        points: 5, // 5 points
        duration: 15 * 60, // Per 15 minutes
        blockDuration: 15 * 60, // block for 15 minutes if more than points consumed 
      };
      
      const rateLimiter = new RateLimiterRedis(opts);
      
      self.register = async function(username, password) {
        let blocked = false;
        try {
          await rateLimiter.consume(clientIP, 1);
        } catch() {
          blocked = true;
        }
      
        if (blocked) {
          return false;
        }
      
        return $http.post(API + '/auth/register', {
            username: username,
            password: password
          })
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-05
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 2018-09-30
        • 1970-01-01
        相关资源
        最近更新 更多