Whether you’re a React.js, Angular, Vue.js, or simply a front-end developer, your code can be an inviting door for hackers.
无论您是React.js,Angular,Vue.js还是仅仅是前端开发人员,您的代码都可以成为黑客的诱人之门。
As a front-end developer, we’re mostly concern about performance, SEO, and UI/UX — security is often overlooked.
作为前端开发人员,我们主要关注性能,SEO和UI / UX-安全性经常被忽略。
You might be surprised to know how big frameworks let you open yourself up to cross-site scripting (XSS) attacks. There are risky operations names like dangerouslySetInnerHTML
in React or the bypassSecurityTrust
APIs in Angular.
您可能会惊讶地知道,大型框架如何使您轻松应对跨站点脚本(XSS)攻击。 有一些危险的操作名称,例如React中的dangerouslySetInnerHTML
地设置bypassSecurityTrust
或Angular中的bypassSecurityTrust
API。
We should keep in mind that the front end now shares equal responsibilities as the back end or DevOps in terms of security. There are thousands of malicious attacks that can happen from a front end.
我们应该记住,就安全性而言,前端现在与后端或DevOps承担同等的责任。 前端可能会发生数千种恶意攻击。
Let’s understand the most common — these will cover a great portion of these types of attacks.
让我们了解最常见的情况-这些将涵盖这类攻击的很大一部分。
1. 不受限制的文件上传 (1. Unrestricted File Upload)
This is an attack in which malicious files are uploaded to the server and then executed, to attack the system. The attack may include: an overloaded file system or database, complete system takeover, client-side attacks, forwarding attacks to back-end systems, or simple defacement.
这是一种将恶意文件上传到服务器然后执行的攻击,以攻击系统。 攻击可能 包括:文件系统或数据库超载,完整的系统接管,客户端攻击,将攻击转发到后端系统或简单的破坏。
2. 点击劫持 (2. Clickjacking)
This is is an attack where the user is trick to click on a webpage or an element that does not belong to the site. This attack may cause users to unwittingly provide credentials or sensitive information, download malware, visit malicious web pages, purchase products online, or transfer money.
这是一种攻击,用户诱骗用户单击网页或不属于该站点的元素。 这种攻击可能导致用户不经意间提供凭据或敏感信息,下载恶意软件,访问恶意网页,在线购买产品或转移资金。
3. XSS攻击 (3. XSS Attack)
This is an attack in which malicious scripts are injected in the form of a browser-side script into the webpage. Flaws on the websites allow these attacks to succeed and become widespread.
这是一 攻击,其中恶意脚本以浏览器端脚本的形式注入到网页中。 网站上的缺陷使这些攻击得以成功并广泛传播。
4. SQL注入 (4. SQL injection)
This is an attack in which malicious code in SQL statements are injected to destroy your database via input fields.
这是一种攻击,其中注入SQL语句中的恶意代码以通过输入字段破坏数据库。
5.拒绝服务攻击 ( DoS攻击 ) (5. Denial-of-service attack (DoS attack))
This is an attack in which the server or its resources are made unavailable to the intended user by bombarding your server with traffic.
这是一种攻击,其中通过用流量轰炸服务器来使目标用户无法使用服务器或其资源。
6. 中间人攻击或会话劫持 (6. Man in the middle attack or session hijacking)
This is an attack in which communications between client and server are intercepted to steal passwords, account numbers, or any personal details.
这是一种攻击,其中客户端与服务器之间的通信被拦截,以窃取密码,帐号或任何个人详细信息。
The attacker will always try to find some loophole in the frontend to reach the server and do his work. In this article, we will see some of the common best practices to always keep in mind while coding the frontend.
攻击者将始终尝试在前端发现一些漏洞以到达服务器并进行工作。 在本文中,我们将看到编码前端时要牢记的一些常见最佳实践。
1.严格的用户输入(第一个攻击点) (1. Strict User Input (the First Point of Attack))
User input should always be strict in nature, to avoid vulnerabilities like SQL injection, clickjacking, etc. So it’s important to validate or sanitize user input before sending it to the back end.
用户输入在本质上应始终严格,以避免诸如SQL注入,点击劫持等漏洞。因此,在将用户输入发送到后端之前,先对其进行验证或清除很重要。
Sanitizing data can be done by removing or replacing contextually-dangerous characters, such as by using a whitelist and escaping the input data.
可以通过删除或替换上下文相关的危险字符来对数据进行消毒,例如使用白名单并转义输入数据。
However, I realize that sanitizing and encoding is not an easy task for all existing possibilities, so we may use the following open-source libraries:
但是,我意识到对所有现有的可能性进行清理和编码并不是一件容易的事,因此我们可以使用以下开源库:
DOMPurify
. This is the most simple to use and has one method to sanitize the user’s input. It has an option to customize the rules and it supports HTML5, SVG, and MathML.DOMPurify
。 这是最简单的使用方法,并且有一种方法可以清除用户的输入。 它具有自定义规则的选项,并且支持HTML5,SVG和MathML。secure-filters
. A Salesforce library that provides methods to sanitize HTML, JavaScript, inline CSS styles, and other contexts. It’s especially useful if you want to make use of user input in other places, for example generating CSS or JavaScript.secure-filters
。 一个Salesforce库,其中提供了清理HTML,JavaScript,内联CSS样式和其他上下文的方法。 如果您想在其他地方使用用户输入,例如生成CSS或JavaScript,则特别有用。
In the case of file upload always check the file type and use a file filter function and allow only certain file types to get upload. Refer to this for more.
如果是文件上传,请务必检查文件类型并使用文件过滤器功能,并且仅允许某些文件类型上载。 请参阅此为多。
2.当心隐藏字段或浏览器内存中存储的数据 (2. Beware Of Hidden Fields or Data Stored in Browser Memory)
If we add input type="hidden"
to hide sensitive data in pages or add them in the browser localStorage
, sessionStorage
, cookies
and think that’s safe, we need to think again.
如果我们添加输入type="hidden"
来隐藏页面中的敏感数据,或者将它们添加到浏览器的localStorage
, sessionStorage
和cookies
并且认为这是安全的,则需要重新考虑。
Everything added to the browser can be accessed by the attacker easily. An attacker can open the dev tools and change all the in-memory variables. And what if you had hidden the auth page depending upon the localStorage
, sessionStorage
, and cookies
values?
攻击者可以轻松访问添加到浏览器中的所有内容。 攻击者可以打开开发工具并更改所有内存变量。 如果您根据localStorage
, sessionStorage
和cookies
值隐藏了auth页面,该怎么办?
There are tools like ZapProxy and even inspection tools in the browser that can expose those values to attackers if they find a way to inject a script, and they can then can use them to attack further.
浏览器中有ZapProxy之类的工具,甚至是检查工具,它们可以在攻击者找到注入脚本的方式后将这些值暴露给攻击者,然后他们可以使用它们进行进一步的攻击。
Hence avoid using type="hidden"
and avoid storing keys, auth tokens, etc, in the browser in-memory storage as much as possible.
因此,请避免使用type="hidden"
并尽可能避免将密钥,身份验证令牌等存储在浏览器的内存中。
3.使用强大的内容安全策略(CSP) (3. Use a Strong Content Security Policy (CSP))
Never trust everything that the server sends — always define a strong Content-Security-Policy HTTP header which only allows certain trusted content to be executed on the browser or render more resources.
永远不要信任服务器发送的所有内容-始终定义一个强大的Content-Security-Policy HTTP标头,该标头仅允许某些受信任的内容在浏览器上执行或提供更多资源。
It’s good practice to have a whitelist — a list of allowed sources. Now, even if an attacker injects script, the script won’t match the whitelist and won’t be executed.
最好有一个白名单-允许的来源清单。 现在,即使攻击者注入了脚本,该脚本也不会与白名单匹配,也不会被执行。
For example:
例如:
content-security-policy: script-src ‘self’ https://apis.xyz.com
Here the application trusts only the scripts coming from apis.xyz.com
and ourselves (self
). For the rest of the sources, an error in the console is thrown.
在这里,应用程序仅信任来自apis.xyz.com
和我们自己的脚本( self
)。 对于其余的源,控制台中将引发错误。
Note: A strong content security policy does not solve the problem of inline scripts execution, hence XSS attack is still valid.
注意:强大的内容安全策略不能解决内联脚本执行的问题,因此XSS攻击仍然有效。
You can read a full list of CSP directives on the MDN website.
您可以在MDN网站上阅读CSP指令的完整列表。
4.启用XSS保护模式 (4. Enable XSS Protection Mode)
If somehow an attacker injects malicious code from the user input, we can instruct the browser to block the response by supplying the "X-XSS-Protection": "1; mode=block"
header.
如果攻击者以某种方式从用户输入中注入了恶意代码,我们可以通过提供"X-XSS-Protection": "1; mode=block"
标头来指示浏览器阻止响应。
Most modern browsers have XSS protection mode enabled by default but it’s still recommended to include the X-XSS-Protection
header. This helps to ensure better security for older browsers that don't support CSP headers.
大多数现代浏览器默认情况下都启用了XSS保护模式,但仍建议包含X-XSS-Protection
标头。 这有助于确保不支持CSP标头的旧版浏览器的安全性更高。
5.避免典型的XSS错误 (5. Avoid Typical XSS Mistakes)
An XSS attack is usually traced to the DOM API’s innerHTML.
For instance:
XSS攻击通常可追溯到DOM API的innerHTML.
例如:
document.querySelector('.tagline').innerHTML = nameFromQueryString
Any attacker is able to inject malicious code with the line above.
任何攻击者都可以使用上面的代码行注入恶意代码。
Consider using textContent
instead of innerHTML
to prevent generating HTML output altogether. If you don’t generate HTML, there’s no way to insert JavaScript — you may see the content but nothing will happen.
考虑使用textContent
而不是innerHTML
来防止完全生成HTML输出。 如果不生成HTML,则无法插入JavaScript,您可能会看到其中的内容,但是什么也不会发生。
Keep an eye out for a new Trusted Types specification which aims to prevent all DOM-based cross-site scripting attacks made by googlers.
请密切注意新的Trusted Types规范 ,该规范旨在防止Google员工进行所有基于DOM的跨站点脚本攻击。
In the case of react.js, dangerouslySetInnerHTML
is unambiguous and cautionary and can have a similar impact as innerHTML
.
在react.js的情况下, dangerouslySetInnerHTML
是明确的和警告,并且可以具有相似的影响,因为innerHTML
。
Note: Don't Set the innerHTML
value-based on user input and use textContent instead of innerHTML
as much as possible.
注意:请勿 基于用户输入 设置 innerHTML
值,并 尽可能 使用textContent而不是 innerHTML
。
Also, HTTP responses headers Content-Type
and X-Content-Type-Options
should be set properly, with their intended behavior. For example, JSON data should never be encoded as text/HTML, to prevent accidental execution.
另外,应正确设置HTTP响应标头Content-Type
和X-Content-Type-Options
及其预期行为。 例如,请勿将JSON数据编码为文本/ HTML,以防止意外执行。
6.禁用iframe嵌入 (6. Disable iframe Embedding)
The disabling iframe can project us from a clickjacking attack. We should always use the "X-Frame-Options": "DENY"
header in the request that prohibits the rendering of the website in a frame.
禁用的iframe可以使我们免受点击劫持攻击。 我们应该始终在请求中使用"X-Frame-Options": "DENY"
标头,以禁止在框架中呈现网站。
Also, we can use frame-ancestors
CSP directive, which provides more control over which parents can embed the page in an iframe.
另外,我们可以使用frame-ancestors
CSP指令,该指令可以更好地控制哪些父项可以将页面嵌入iframe。
7.保持错误通用 (7. Keep Errors Generic)
An error like “Your password is incorrect,” may be helpful to the user but also to the attackers. They may figure out information from these errors that helps them to plan their next action.
诸如“您的密码不正确”之类的错误可能对用户有所帮助,对攻击者也有帮助。 他们可能会从这些错误中找出信息,以帮助他们计划下一步行动。
When dealing with accounts, emails, and PII, we should try to use ambiguous errors like “Incorrect login information.”
在处理帐户,电子邮件和PII时,我们应尝试使用诸如“错误的登录信息”之类的模棱两可的错误。
8.使用验证码 (8. Use Captcha)
Using Captcha at public-facing endpoints (login, registration, contact). A Captcha is a computer program or system intended to distinguish humans from bots and can help stop DoS (Denial Of Service) attacks.
在面向公众的端点(登录,注册,联系)上使用验证码。 验证码是一种旨在区分人与机器人的计算机程序或系统,可以帮助阻止DoS(拒绝服务)攻击。
9.始终设置Referrer-Policy
(9. Always Set Referrer-Policy
)
Whenever we use anchor tag or a link that navigates away from the website, make sure you use a header policy "Referrer-Policy": "no-referrer"
or, in case of the anchor tag, set rel = noopener or noreferrer
.
每当我们使用定位标记或导航到远离网站的链接时,请确保使用标头策略"Referrer-Policy": "no-referrer"
或者在使用定位标记的情况下,设置rel = noopener or noreferrer
。
When we don’t set these headers and rel, the destination website can obtain data like session tokens and database IDs.
如果我们不设置这些标头和相关性,则目标网站可以获得会话令牌和数据库ID之类的数据。
10.使用受限的浏览器功能和API (10. Use Limited Browser Features & APIs)
As in CSP, the limited domain can connect to the website, the same principle can also be applied to browser features & APIs. We can add a Feature-Policy
header to deny access to certain features and APIs. Read more.
与CSP中一样,受限域可以连接到网站,同样的原理也可以应用于浏览器功能和API。 我们可以添加一个Feature-Policy
标头来拒绝对某些功能和API的访问。 阅读更多 。
Tip: Set none
for all features that you don't use.
提示:设置 none
所有的功能,你不使用。
11.定期审核依赖性 (11. Audit Dependencies Regularly)
Run npm audit
regularly to get a list of vulnerable packages and upgrade them to avoid security issues.
定期运行npm audit
以获得易受攻击的软件包的列表,并对其进行升级以避免安全问题。
GitHub now flags vulnerable dependencies. We can also use Snyk that checks your source code automatically and opens pull requests to bump versions.
GitHub现在标记易受攻击的依赖项。 我们还可以使用Snyk来自动检查您的源代码,并打开对凹凸版本的请求。
12.分隔您的应用程序 (12. Compartmentalize Your Application)
As in the back end, we have a microservice architecture where monolithic applications are split into smaller self-contained components, each running individually.
与后端一样,我们拥有微服务架构,其中单片应用程序被拆分为较小的自包含组件,每个组件单独运行。
The same principle can be applied to the frontend. For instance, an application can be split into the public, authenticated, and admin parts, each hosted on separate subdomains, like https://public.example.com
, https://users.example.com
and https://admin.example.com
.
相同的原理可以应用于前端。 例如,一个应用程序可以被划分为公共,认证和管理部分,每个托管在单独的子域,像https://public.example.com
, https://users.example.com
和https://admin.example.com
。
This will ensure fewer client-side vulnerabilities.
这将确保减少客户端漏洞。
Note: Proper compartmentalization would also prevent an XSS vulnerability in the public part of the application, preventing it from automatically compromising user information.
注意:适当的分隔还可以防止在应用程序的公共部分出现XSS漏洞,从而防止它自动破坏用户信息。
13.避免第三方服务 (13. Avoid Third-Party Services)
One line of code third-party services like Google Analytics, Google Tag Manager, Intercom, Mixpanel, can make your web app vulnerable. Think of a situation when these third party services are compromised.
一行代码第三方服务(例如Google Analytics(分析),Google跟踪代码管理器,对讲机,Mixpanel)会使您的Web应用容易受到攻击。 想一想这些第三方服务受到损害的情况。
It’s important to have a strong CSP policy. Most third-party services have a defined CSP directive, so always add them.
拥有强大的CSP政策很重要。 大多数第三方服务都有定义的CSP指令,因此请务必添加它们。
Also, be sure to include integrity
attribute when possible when adding a script tag. Subresource Integrity feature can validate the cryptographic hash of the script and make sure it hasn’t been tampered with.
另外,添加脚本标签时,请确保在可能的情况下包括integrity
属性。 子资源完整性功能可以验证脚本的加密哈希,并确保它未被篡改。
仔细考虑自动填充字段 (Carefully Consider Autofill Fields)
Personal identification information stored in the autofill of a browser can be convenient for both users and attackers.
存储在浏览器自动填充中的个人标识信息对于用户和攻击者都可以很方便。
Attackers add third-party scripts to exploit browsers’ built-in autofill to extract email addresses for building tracking identifiers. They can use these to build user browsing history profiles which they can sell to the bad guys. Read more on this here.
攻击者添加了第三方脚本,以利用浏览器的内置自动填充功能提取电子邮件地址以构建跟踪标识符。 他们可以使用它们来构建用户浏览历史记录配置文件,然后将其出售给坏人。 在这里阅读更多内容。
Many of us aren’t even aware of what information their browser’s autofill has stored.
我们许多人甚至都不知道他们的浏览器自动填充存储了哪些信息。
Tip: Disable auto-filled forms for sensitive data.
提示:对敏感数据禁用自动填写的表单。
Thank you.
谢谢。
翻译自: https://medium.com/better-programming/frontend-app-security-439797f57892