Stop deploying web application firewalls

I wanted to write this because I don’t hear enough real people discouraging the use of Web Application Firewalls (WAFs). Probably because the search results for “Web Application Firewall” are all written by WAF vendors. Anyone reading just that could conclude that WAFs are a good idea. I’m here to offer another perspective, after having suffered through using a WAF for two years.
我想写这篇文章,因为我没有听到足够的真实的人劝阻使用Web应用程序防火墙(WAF)。可能是因为“Web应用程序防火墙”的搜索结果都是由WAF供应商编写的。任何阅读到这一点的人都可以得出结论,WAF是一个好主意。我在这里提供另一种观点,在使用WAF两年之后。

Web Application Firewalls were created early in the Internet’s history, especially popularized by the ModSecurity project in 2002. WAFs essentially work by intercepting every single HTTP request (and sometimes responses too) and evaluating several hundred regular expressions over the URI, headers, and body, sometimes aided by machine learning. If the request kinda looks like SQL, shell code, etc., the server may block your request.
Web应用程序防火墙是在互联网历史的早期创建的,特别是在2002年的ModSecurity项目中普及。WAF基本上是通过拦截每个HTTP请求(有时也包括响应)并评估URI、头和正文上的数百个正则表达式来工作的,有时还需要机器学习的帮助。如果请求看起来有点像SQL、shell代码等,服务器可能会阻止您的请求。

In the infancy of the cybersecurity field, WAFs seemed like a good idea. HTTP requests were tiny, infrequent, and mostly contained mundane form data. But today, WAFs have overstayed their welcome in the security toolbelt. There are better techniques you can use that make even the most advanced WAFs entirely obsolete.
在网络安全领域的初期,WAF似乎是一个好主意。HTTP请求很小,不频繁,并且大多包含普通的表单数据。但是今天,WAF在安全工具带中已经不受欢迎了。你可以使用更好的技术,使最先进的WAF完全过时。

WAFs have Horrible Performance
WAF具有可怕的性能

Since WAFs run hundreds of regular expressions on every request, you may ask, “isn’t that super inefficient?” Yes, very.
由于WAF在每个请求上运行数百个正则表达式,您可能会问,“这不是超级低效吗?“是的,非常好。

WAF No WAF 无WAF
Average time taken to upload 9,462 text files
上传9,462个文本文件的平均时间
7.36 4.55
Average requests per second
每秒平均请求数
1285 2079
Number of requests blocked erroneously
错误阻止的请求数
5 0
Peak nginx CPU during trial
试用期间的nginx CPU峰值
73% 8%
Specifics about the benchmark
关于基准的细节

In addition to slowing down every request, you also need significant additional RAM for buffering requests. Since not a single byte in the buffer can be flushed to the backend server until the WAF completes its analysis, you need several gigabytes of RAM to store request bodies. Servers like nginx buffer requests by default, but enough large concurrent requests (like pushing a container image) can make a buffering web server run out of RAM. When using a WAF, every server becomes a buffering web server, which is simply incompatible with many types of applications.
除了减慢每个请求的速度之外,您还需要大量额外的RAM来缓冲请求。由于在WAF完成分析之前,缓冲区中的任何一个字节都不能刷新到后端服务器,因此需要几GB的RAM来存储请求体。默认情况下,像nginx这样的服务器缓冲请求,但是足够大的并发请求(比如推送容器镜像)会使缓冲的Web服务器耗尽RAM。当使用WAF时,每个服务器都变成了缓冲Web服务器,这与许多类型的应用程序不兼容。

I know computers are fast and hardware is cheap, but we shouldn’t be spending that kind of CPU and RAM on WAFs unless they’re a really effective security tool. But they aren’t, as you’ll see next.
我知道计算机速度快,硬件便宜,但我们不应该在WAF上花费这样的CPU和RAM,除非它们是一个真正有效的安全工具。但他们不是,正如你接下来会看到的。

WAFs are Easily Bypassed
WAF很容易被封装

WAF vendors and attackers are locked in a constant arms race, but it seems attackers are much better armed. How could they not be? Many of the attacks that a WAF purports to block involve complex grammars like SQL, shell code, and entire programming languages. They often include comments, character escaping, encoding issues, and more oddities. These oddities mean that attackers always have a significant advantage and can typically bypass any WAF rule if they are clever enough.
WAF供应商和攻击者陷入了持续的军备竞赛,但似乎攻击者的武装要好得多。怎么可能不是呢?WAF声称要阻止的许多攻击都涉及复杂的语法,如SQL,shell代码和整个编程语言。它们通常包括注释、字符转义、编码问题和更多的奇怪之处。这些奇怪的现象意味着攻击者总是有一个显著的优势,如果他们足够聪明,通常可以绕过任何WAF规则。

For example, you might think Log4shell is pretty easy to catch: just check for ${jndi, right? Unfortunately, Log4J supports nested “lookups“, including ones that convert letters to upper/lower case like ${lower:J}
例如,您可能认为Log 4shell很容易捕获:只需检查 ${jndi ,对吗?不幸的是,Log4J支持嵌套的“查找”,包括将字母转换为大写/小写的查找,如 ${lower:J}

That means an attacker can insert an arbitrary number of nested lookups around each letter and still perform the attack, like this: ${${lower:J}ndi:.... This lead CloudFlare to say “WAF vendors need to be looking at any occurrence of ${ and treating it as suspicious”, which is just another hilarious example of how WAFs can never live up to the expectations placed on them.
这意味着攻击者可以在每个字母周围插入任意数量的嵌套查找,并仍然执行攻击,如: ${${lower:J}ndi:... 。这导致CloudFlare说“WAF供应商需要关注 ${ 的任何事件并将其视为可疑”,这只是WAF如何永远无法达到对他们的期望的另一个滑稽的例子。

I just discussed the fairly simple grammar that is Log4J Lookups, but you can imagine how many more evasion tactics you could use in a language as complex as SQL or PHP, especially when considering encoding tricks. For an in-depth description of specific WAF bypass techniques, check out this awesome post.
我刚刚讨论了相当简单的语法,即Log4J Lookups,但是您可以想象在像SQL或PHP这样复杂的语言中可以使用多少规避策略,特别是在考虑编码技巧时。有关特定WAF旁路技术的深入描述,请查看这篇令人敬畏的文章。

Another way to bypass a WAF involves just padding your attack string to appear >8KB or so into the request body. Like I mentioned in the section on performance, request bodies must be buffered into RAM for analysis, so WAFs must choose some cut-off point to avoid spending infinite CPU and RAM on a single request. For some WAFs like AWS’s, that cutoff point is around 8KB. So if you just put 8192 innocuous characters before your Log4Shell attack string, you’ve rendered the WAF worthless.
另一种绕过WAF的方法是将攻击字符串填充到请求体中,使其显示为>8KB左右。就像我在性能一节中提到的,请求体必须缓冲到RAM中进行分析,因此WAF必须选择某个截止点,以避免在单个请求上花费无限的CPU和RAM。对于像AWS这样的一些WAF,这个截止点大约是8KB。因此,如果您只是在Log4Shell攻击字符串之前放置8192个无害字符,则会使WAF变得毫无价值。

WAFs are an Attack Vector
WAF是攻击向量

In 2019, CapitalOne experienced a breach of 100 million credit applications that was allegedly caused by a WAF misconfiguration. The attacker allegedly tricked the WAF into sending requests to the EC2 Metadata Service, which handed out a credential that allowed reading sensitive files from S3.
在2019年,CapitalOne经历了1亿个信贷申请的违规,据称是由于WAF配置错误造成的。据称,攻击者欺骗WAF向EC2元数据服务发送请求,后者分发了一个允许从S3阅读敏感文件的凭据。

While this is just one example, it illustrates the curious fact that WAFs actually have a large attack surface.
虽然这只是一个例子,但它说明了一个奇怪的事实,即WAF实际上具有很大的攻击面。

Most WAFs are giant, complex codebases that are usually closed-source and written in memory-unsafe languages. Since they’re expensive “enterprise” products, companies stuff them full of unnecessary features to make them stand out more than competitors. All of this adds up to make WAFs yet another example of a dangerous “security” tool, just like SolarWinds.
大多数WAF是巨大的、复杂的代码库,通常是闭源的,并且是用内存不安全的语言编写的。由于它们是昂贵的“企业”产品,公司会在它们身上塞满不必要的功能,使它们比竞争对手更突出。所有这些加起来使WAF成为另一个危险的“安全”工具的例子,就像SolarWinds一样。

No security officer would approve taking such a risky piece of software, putting it directly on the internet, making it parse mountains of untrusted input, and giving it access to all your backend servers, logging infra, SIEM, alerting systems, and even JIRA for some reason UNLESS it’s covered in security buzzwords and costs 5-6 figures per year.
没有安全官员会批准这样一个有风险的软件,直接把它放在互联网上,让它解析大量不受信任的输入,并让它访问所有的后端服务器,记录基础设施,SIEM,警报系统,甚至JIRA出于某种原因,除非它被安全术语所覆盖,每年花费5-6位数。

Somehow, companies that sell security products have gotten a pass on implementing foundational security principles like secure by default, secure by design, attack surface reduction, and the principle of least privilege. Don’t let them keep getting away with that.
不知何故,销售安全产品的公司在实现基本安全原则方面获得了通行证,如默认安全,设计安全,减少攻击面和最小特权原则。别让他们得逞

WAFs have a High False Positive Rate
WAF有很高的误报率

Over the last twenty years, open-source WAF rulesets have expanded considerably to detect more-recent types of attack. Apparently all those proprietary WAFs are doing the same. That means there are more and more possible strings that could trigger a WAF to block your request. If you want to write a comment on an article discussing Log4shell, you might be blocked for including the string ${jndi in your comment. So naturally the false positive rate continues to rise with every new rule, and it’s already quite high based on my experience maintaining a giant list of ModSecurity rule exceptions.
在过去的二十年里,开源WAF规则集已经大大扩展,以检测更新类型的攻击。显然,所有这些专有的WAF都在做同样的事情。这意味着有越来越多的可能字符串可以触发WAF阻止您的请求。如果你想在一篇讨论Log4shell的文章上写评论,你可能会因为在评论中包含字符串 ${jndi 而被阻止。因此,随着每一个新规则的出现,误报率自然会继续上升,根据我维护ModSecurity规则异常的巨大列表的经验,误报率已经相当高了。

So-called “next-generation” WAFs claim to solve this problem by looking at multiple requests or by using IP reputation systems. While these can improve false positive rates, they can never truly solve the problem. In some ways, less false positives can increase the impact of particular false positives since neither users nor support teams have a clear procedure for fixing it. CloudFlare’s algorithm can randomly decide to block you and you will have no recourse. Imagine that happening to someone less tech-savvy.
所谓的“下一代”WAF声称通过查看多个请求或使用IP信誉系统来解决这个问题。虽然这些可以提高假阳性率,但它们永远无法真正解决问题。在某些方面,误报减少会增加特定误报的影响,因为用户和支持团队都没有明确的修复程序。CloudFlare的算法可以随机决定阻止您,您将没有追索权。想象一下这种情况发生在一个不太懂技术的人身上。

This is the classic problem with using an outdated security tool like a WAF: defenders have to configure the tool absolutely perfectly to be safe and avoid false positives, but attackers just need to find a single weakness. Those are horrible odds. You should use alternatives that don’t require perfection from imperfect humans.
这是使用过时的安全工具(如WAF)的经典问题:防御者必须绝对完美地配置工具以确保安全并避免误报,但攻击者只需要找到一个弱点。几率太小了。你应该使用替代品,不需要完美的人类完美。

Alternatives to WAFs WAF的替代品

Since WAFs are resource-hungry, inneffective, unsafe, and noisy, how do I convince an auditor to not make me use one? The technical term would be to use “compensating controls”, but that sounds like such a weak term to describe the powerful and simple alternatives to WAFs I’m about to describe:
由于WAF是资源消耗型的、低效的、不安全的和嘈杂的,我如何说服审计员不要让我使用WAF?技术术语是使用“补偿控制”,但这听起来像是一个弱术语来描述我将要描述的WAF的强大而简单的替代品:

  • Isolation: Isolation involves ensuring that a breach in one component can not affect the rest of the system, and there are many technologies that provide isolation.
    隔离:隔离涉及确保一个组件中的漏洞不会影响系统的其余部分,并且有许多技术可以提供隔离。

    • Browsers do this by executing all code inside special sandboxed processes that don’t have carte blanch access to cookies, saved passwords, other tabs, etc. Imagine how slow the web would be if every piece of JavaScript needed to be analyzed by hundreds of regexes before being executed!
      浏览器通过在特殊的沙盒进程中执行所有代码来实现这一点,这些沙盒进程没有对cookie、保存的密码、其他选项卡等的carte blanch访问权限。想象一下,如果每一段JavaScript在执行之前都需要经过数百个正则表达式的分析,那么Web将有多慢!
    • Microservices are designed with isolation in mind, but you can also do it in a monolith with a variety of libraries and languages.
      微服务的设计考虑到了隔离,但您也可以在具有各种库和语言的单体中进行。
  • Immutability: Entire classes of attack can be eliminated by removing a few assumptions, like having a readOnlyRootFilesystem, a package manager that requires rebooting, or append-only/immutable backups.
    不变性:通过移除一些假设,例如具有readOnlyRootFilesource、需要重新引导的包管理器或仅追加/不可变备份,可以消除整个攻击类别。
  • Static Analysis: SQL injection has a miracle cure called “prepared statements”. The problem is that devs forget to use them. Static analysis checks in a CI pipeline can all but ensure that zero SQL injection vulnerabilities are in your codebase, at which point there is no need for any SQL injection WAF rules. No, “defense in depth” is not a valid excuse to use a WAF anyway, because it provides no real defense! Like surrounding Fort Knox with an army of guard guinea pigs.
    静态分析:SQL注入有一个神奇的治疗方法,称为“预处理语句”。问题是开发人员忘记使用它们。CI管道中的静态分析检查几乎可以确保代码库中没有SQL注入漏洞,此时不需要任何SQL注入WAF规则。不,“纵深防御”无论如何都不是使用WAF的有效借口,因为它不提供真实的防御!就像诺克斯堡周围的警卫豚鼠军队。
  • Capability-based security: Not every API endpoint needs to have unrestricted read/write access to your entire database and file system, but that is the normal way people build APIs today. By using capabilities, you can express exactly that “GET /api/v1/books” only needs read access to the “books” table. Or that “POST /api/v1/imageupload” needs write access to a specific folder, but doesn’t need the ability to spawn processes.
    基于能力的安全性:并非每个API端点都需要对整个数据库和文件系统具有不受限制的读/写访问权限,但这是当今人们构建API的正常方式。通过使用功能,您可以准确地表示“GET /API/v1/books”只需要对“books”表的读访问。或者“POST /API/v1/imageupload”需要对特定文件夹的写入权限,但不需要派生进程的能力。

Now I’ll admit these ideas are quite broad; you’ll need to adapt them to your particular app. WAF vendors offer a one-WAF-fits-all fantasy that I can’t match. But these secure-by-design strategies are the way that the security industry needs to be heading. Unfortunately, it’s a lot harder for the security industry to profit off of design-based techniques, so don’t hold your breath.
现在我承认这些想法是相当广泛的;您需要使它们适应您的特定应用程序。但这些安全的设计策略是安全行业需要走的路。不幸的是,安全行业很难从基于设计的技术中获利,所以不要屏住呼吸。

原文始发于Mac’s Tech Blog:Stop deploying web application firewalls

版权声明:admin 发表于 2024年2月8日 上午8:34。
转载请注明:Stop deploying web application firewalls | CTF导航

相关文章