跳到主要内容
博客计算防御登录 API 强制攻击

防御登录 API 强制攻击

一个红色块状符号,上面有如下文字"防御登录 API 强制攻击:因为偷工减料会让你瘫痪"

面对现实吧,当你急于在最后期限前完成发布任务时,你就会偷工减料。你的测试覆盖范围变得模糊不清,你的代码变得不那么 DRY,你的异常处理被送进了技术债务坟场--我的意思是,积压工作。我们都经历过这种情况。

但是,当需要偷工减料时,切勿放弃实施 "最大登录尝试失败次数 "保障措施。如果您的登录应用程序接口没有适当的保护措施,那么如今通过暴力手段获取用户账户的访问权限就相对容易了。

在本篇文章中,我们将向您展示攻击者是如何暴力破解登录 API 的。然后,我们将讨论您可以采取哪些应对措施来保护您的系统。

登录应用程序接口示例

为了演示,我们使用Node.js 和 Express 构建了一个非常基本的 API 服务器。它只监听一个端点的 POST 请求、 /login.请求正文应包含 username 和一个 password.如果成功提供了凭据,API 会返回 200 OK.否则返回 401 UNAUTHORIZED.

下面是我们简单的 Express 服务器的代码:

const express = require('express');
const users = require('./users.json');

const app = express();
const PORT = 3000;

// Middleware to parse JSON bodies
app.use(express.json());

app.post('/login', (req, res) => {
    const { username, password } = req.body;

    // Check if the username exists and the password matches
    if (users[username] && users[username] === password) {
        return res.status(200).send('OK');
    } else {
        return res.status(401).send('UNAUTHORIZED');
    }
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server is listening on port ${PORT}`);
});

在这个简单的演示中,我们将用户名和密码列表保存在一个名为 users.json.

我们将服务器部署在 Linode 上,监听端口为 3000.让我们试着提出一个请求:

~$ curl -i \        -X POST \        --header "Content-type:application/json" \        --data '{"username":"user08","password":"testpassword"}' \         172.233.153.34:3000/login

HTTP/1.1 401 UnauthorizedX-Powered-By: ExpressContent-Type: text/html; charset=utf-8Content-Length: 12ETag: W/"c-MvHJP5yPj49I/9tX+wGrvHWbTRk"Date: Sat, 25 May 2024 19:17:34 GMTConnection: keep-aliveKeep-Alive: timeout=5
UNAUTHORIZED

我们的登录应用程序接口已启动并运行!

现在,如果我们想暴力破解我们的 API,我们可以写这样一个脚本:

#!/bin/sh

API_ENDPOINT="http://172.233.153.34:3000/login"

USERNAME="user5"

echo "Attempting to login at $API_ENDPOINT as \"$USERNAME\""

for i in {1..8}
do
  PASS="password${i}"
  RESULT=$(curl --silent -X POST --header "Content-type:application/json" --data "{\"username\":\"$USERNAME\",\"password\":\"$PASS\"}" $API_ENDPOINT)
  echo "\"$PASS\": $RESULT"

  if [[ $RESULT == 'OK' ]]; then
    echo "!!! Password for \"$USERNAME\" found: \"$PASS\""
    break
  else
    sleep 1
  fi
done

当我们运行基本的暴力脚本时,它看起来像这样:

$ source bruteforce.sh
Attempting to login at http://172.233.153.34:3000/login as "user5"
"password1": UNAUTHORIZED
"password2": UNAUTHORIZED
"password3": UNAUTHORIZED
"password4": UNAUTHORIZED
"password5": OK
!!! Password for user5 found: "password5"

攻击者真的能猜出密码吗?

因此,我们已经看到了编写一个脚本是多么容易,它至少可以循环查看给定用户名的一些密码。你可能会说:"好吧,这是一个有趣的虚构例子。但攻击者真的能猜出密码吗?

这里列出了10,000 个最常见的密码。这对任何攻击者来说都是一个很好的开始。想想看,你有没有遇到过使用 "password123 "或 "qwerty "的人呢?说不定就是你!

如果攻击者知道您系统的几个用户名,并运行脚本循环查看这些常用密码,他们就有可能得手。

每尝试一次用户名和密码组合,账户被入侵的几率就会增加一次。

这是一个典型的身份验证失效案例,在 OWASP API 安全十大风险中排名第二。如果您的应用程序不能正确防范自动攻击,您就会自找麻烦。如果没有防护措施,用户的账户将面临巨大风险。

密码往往是系统安全中最薄弱的环节:

  • 用户在多个网站重复使用密码。
  • 用户选择易记(和易猜)的密码。
  • 用户很少更新密码。

所有这些因素都使暴力攻击变得非常有效。

让我们回到我们的问题上来:攻击者真的能猜到密码吗?当然可以。如果你没有采取正确的预防措施,它可能比你想象的更快发生。

如何保护我的 API?

有多种方法可以抵御对登录 API 的暴力破解攻击。

设定登录失败次数上限

为每个用户设置登录失败次数限制。在用户尝试登录时,记录登录失败的次数。如果达到上限,则暂时锁定账户或阻止来自发送者 IP 地址的后续请求。这样攻击者就很难强行进入了。

使用网络应用程序防火墙(WAF)

WAF 可以通过检测和阻止恶意活动来保护您的 API。

  • 僵尸活动:好的 WAF 可以区分合法用户和僵尸,阻止自动暴力攻击。
  • 来自 Tor 背后的可疑登录请求:许多攻击者使用 Tor 网络来隐藏身份。阻止或质疑来自 Tor 节点的请求可以降低攻击风险。

Haltdos 是 LinodeMarketplace 上提供的一种 WAF,可提供上述保护和更多保护。通过集成这些工具,可以大大增强 API 的防御能力。

实施速率限制

限制在给定时间内来自单个 IP 地址的 API 请求数量。这样可以降低暴力攻击的速度,减少攻击的可行性。对于所有 API 和端点,而不仅仅是登录 API,限制速率都是一种很好的做法。

启用多因素身份验证 (MFA)

如果添加额外的安全层(如 MFA),那么即使攻击者猜对了密码,也能挫败暴力攻击。成功通过整个身份验证流程需要用户知道的东西(密码)他们拥有的东西(手机或硬件令牌)。

监控和分析登录尝试

设置 API 请求监控解决方案,密切关注登录尝试。查找可能表明存在攻击的模式。这可以帮助您快速应对可疑活动。

实施这些措施有助于保护您的 API 免受暴力攻击,并确保用户账户的安全。

总结

保护您的登录 API 免受暴力攻击至关重要。猜测密码并不像你想象的那么困难,自动猜测密码更是小儿科。您的系统是否存在漏洞?我们已经介绍了几种可以加固系统的方法。这些步骤将大大增强您的安全态势。

在匆忙构建应用程序和应用程序接口的过程中,我们会原谅你在这里或那里偷工减料。每个人都会这样做。但不要让您的登录 API 不受保护!不要等到攻击发生时才行动,现在就采取行动保护您的系统和用户。有关日志记录和系统监控的更多详细指导,请查看Linode 文档。如果您计划使用Apache 为应用程序提供服务,可以查看本指南,了解如何配置 mod_evasive,以帮助您的服务器抵御 DoS/DDoS 攻击。

注意安全

注释

留下回复

您的电子邮件地址将不会被公布。 必须填写的字段被标记为*