express.js
采取7个步骤来确保您的应用无敌 (Take 7 steps to make sure that your app is invincible)
Is your phone locked? Do you have a pin-code, password, fingerprint, or FaceID? I am 99 percent sure that you do. And it is clear why – you care about your safety. Nowadays, keeping your phone protected is as important as brushing your teeth in the morning.
手机被锁定了吗? 您有个人密码,密码,指纹或FaceID吗? 我有99%的肯定您会这样做。 很明显,为什么–您关心您的安全。 如今,保护手机就像早上刷牙一样重要。
For diligent and mindful software developers, keeping their app secure is equally important to protecting their phones. If you are a developer and you choose to neglect it – please, reconsider your approach. If you are a project owner and your development team says that data safety can wait, please, reconsider your team.
对于勤奋而有思想的软件开发人员而言,保护其应用程序安全对保护手机同样重要。 如果您是开发人员而选择忽略它–请重新考虑您的方法。 如果您是项目所有者,并且您的开发团队说数据安全可以等待,请重新考虑您的团队。
In this article, I want to talk about how to make sure that your Express.js project is safe and invincible to malicious attacks.
在本文中,我想谈谈如何确保Express.js项目安全且不受恶意攻击。
There are 7 simple and not very simple measures to take for the purpose of data security:
为了数据安全,可以采取7种简单但不是非常简单的措施:
Use reliable versions of Express.js
使用Express.js的可靠版本
Secure the connection and data
保护连接和数据
Protect your cookies
保护您的Cookie
Secure your dependencies
保护您的依赖
Validate the input of your users
验证用户的输入
Protect your system against brute force
保护您的系统免受暴力侵害
Control user access
控制用户访问
Let’s have a closer look at each.
让我们仔细看看每个。
1.使用Express.js的可靠版本 (1. Use reliable versions of Express.js)
Deprecated or outdated versions of Express.js are a no go. The 2nd and 3rd versions of Express are no longer supported. In these, safety or performance issues are not fixed anymore.
不赞成或不赞成使用Express.js版本。 Express的第二和第三版本不再受支持。 其中,安全或性能问题不再得到解决。
As a developer, you absolutely have to migrate to Express 4. This version is a revolution! It is quite different in terms of the routing system, middleware, and other minor aspects.
作为开发人员,您绝对必须迁移到Express 4 。 这个版本是一场革命! 就路由系统,中间件和其他次要方面而言,它是完全不同的。
2.保护连接和数据 (2. Secure the connection and data)
To secure HTTP headers, you can make use of Helmet.js – a helpful Node.js module. It is a collection of 13 middleware functions for setting HTTP response headers. In particular, there are functions for setting Content Security Policy, handling Certificate Transparency, preventing clickjacking, disabling client-side caching, or adding some small XSS protections.
为了保护HTTP标头,可以使用Helmet.js –一个有用的Node.js模块。 它是13个中间件函数的集合,用于设置HTTP响应标头。 特别是,具有设置内容安全策略,处理证书透明性,防止点击劫持,禁用客户端缓存或添加一些小的XSS保护的功能。
npm install helmet --save
Even if you do not want to use all the functions of Helmet, the absolute minimum that you must do is to disable X-Powered-By header:
即使您不想使用头盔的所有功能,您绝对要做的绝对最低操作是禁用X-Powered-By标头:
app.disable('x-powered-by')
This header can be used to detect that the application is powered by Express, which lets hackers conduct a precise attack. Surely, X-Powered-By header is not the only way to identify an Express-run application, but it is probably the most common and simple one.
此标头可用于检测应用程序是否由Express驱动,从而使黑客能够进行精确的攻击。 当然,X-Powered-By标头不是识别Express运行的应用程序的唯一方法,但它可能是最常见和最简单的方法。
To protect your system from HTTP parameter pollution attacks, you can use HPP. This middleware puts aside such parameters as req.query and req.body and selects the latest parameter value instead. The installation command looks as follows:
为了保护系统免受HTTP参数污染攻击,可以使用HPP 。 该中间件搁置了诸如req.query和req.body之类的参数,并选择了最新的参数值。 安装命令如下所示:
npm install hpp --save
To encrypt data which is being sent from the client to the server, use Transport Layer Security (TLS). TLS is a cryptographic protocol for securing the computer network, the descendant of the Secure Socket Layer (SSL) encryption. TLS can be handled with Nginx – a free but effective HTTP server – and Let’s Encrypt – a free TLS certificate.
要加密从客户端发送到服务器的数据,请使用传输层安全性(TLS)。 TLS是一种加密协议,用于保护计算机网络(安全套接字层(SSL)加密的后代)。 可以使用Nginx (一个免费但有效的HTTP服务器)和“加密” (一个免费的TLS证书)来处理TLS。
3.保护您的Cookie (3. Protect your cookies)
In Express.js 4, there are two cookie session modules:
在Express.js 4中,有两个cookie会话模块:
- express-session (in Express.js 3, it was express.session) express-session(在Express.js 3中是express.session)
- cookie-session (in Express.js 3, it was express.cookieSession) cookie-session(在Express.js 3中,它是express.cookieSession)
The express-session module stores session ID in the cookie and session data on the server. The cookie-session stores all the session data to the cookie.
express-session模块将会话ID存储在cookie中,并在服务器上存储会话数据。 cookie会话将所有会话数据存储到cookie。
In general, cookie-session is more efficient. Yet, if the session data you need to store is complex and likely to exceed 4096 bytes per cookie, use express-session. Another reason to use express-session is when you need to keep the cookie data invisible to the client.
通常,cookie会话效率更高。 但是,如果您需要存储的会话数据很复杂并且每个cookie可能超过4096字节,请使用express-session。 使用Express-Session的另一个原因是当您需要使cookie数据对客户端不可见时。
Besides, you should set cookie security options, namely:
此外,您应该设置cookie安全选项,即:
- secure 安全
- httpOnly httpOnly
- domain 域
- path 路径
- expires 过期
If “secure” is set to “true”, the browser will send cookies only via HTTPS. If “httpOnly” is set to “true”, the cookie will be sent not via client JS but via HTTP(S). The value of “domain” indicates the domain of the cookie. If the cookie domain matches the server domain, “path” is used to indicate the cookie path. If the cookie path matches the request path, the cookie will be sent in the request. Finally, as the name itself suggests, the value of “expires” stands for the time when the cookies will expire.
如果将“安全”设置为“真”,则浏览器将仅通过HTTPS发送cookie。 如果将“ httpOnly”设置为“ true”,则将不通过客户端JS,而是通过HTTP(S)发送cookie。 “ domain”的值表示cookie的域。 如果cookie域与服务器域匹配,则使用“路径”来表示cookie路径。 如果cookie路径与请求路径匹配,则cookie将在请求中发送。 最后,顾名思义,“过期”的值表示cookie过期的时间。
Another important recommendation is not to use the default session cookie name. It may enable hackers to detect the server and to run a targeted attack. Instead, use generic cookie names.
另一个重要的建议是不要使用默认的会话cookie名称。 它可能使黑客能够检测到服务器并进行有针对性的攻击。 而是使用通用Cookie名称。
4.保护您的依赖 (4. Secure your dependencies)
No doubt, npm is a powerful web development tool. However, to ensure the highest level of security, consider using only the 6th version of it – npm@6. The older ones may contain some serious dependency safety vulnerabilities, which will endanger your entire app. Also, to analyze the tree of dependencies, use the following command:
毫无疑问,npm是功能强大的Web开发工具。 但是,为了确保最高级别的安全性,请考虑仅使用其第六个版本– npm @ 6 。 较旧的可能包含一些严重的依赖安全漏洞,这将危害整个应用程序。 另外,要分析依赖关系树,请使用以下命令:
npm audit
npm audit can help to fix real problems in your project. It checks all your dependencies in dependencies, devDependencies, bundledDependencies, and optionalDependencies, but not your peerDependencies. Here you can read about all current vulnerabilities in any npm packages.
npm审核可以帮助解决项目中的实际问题。 它检查依赖项,devDependencies,bundledDependencies和optionalDependencies中的所有依赖项,但不检查peerDependencies。 在这里,您可以了解任何npm软件包中的所有当前漏洞。
Another tool to ensure dependency safety is Snyk. Snyk runs the application check to identify whether it contains any vulnerability listed in Snyk’s open-source database. To conduct the check, run three simple steps.
确保依赖关系安全的另一种工具是Snyk 。 Snyk运行应用程序检查,以确定它是否包含Snyk的开源数据库中列出的任何漏洞。 要进行检查,请运行三个简单步骤。
步骤1.安装Snyk (Step 1. Install Snyk)
npm install -g snyk
cd your-app
步骤2.运行测试 (Step 2. Run a test)
snyk test
步骤3.了解如何解决问题 (Step 3. Learn how to fix the issue)
snyk wizard
Wizard is a Snyk method, which explains the nature of the dependency vulnerability and offers ways of fixing it.
向导是一种Snyk方法,它解释了依赖项漏洞的性质并提供了解决方法。
5.验证用户的输入 (5. Validate the input of your users)
Controlling user input is an extremely important part for server-side development. This is a no less important problem than unauthorized requests, which will be described in the seventh part of this article.
控制用户输入是服务器端开发中极为重要的部分。 这与未授权的请求一样重要,这将在本文的第七部分中进行描述。
First of all, wrong user input can break your server when some values are undefined and you do not have error handling for a specific endpoint. However, different ORM systems can have unpredictable behavior when you try to set undefined, null, or other data types in the database.
首先,当某些值未定义并且您没有针对特定端点的错误处理时,错误的用户输入可能会破坏您的服务器。 但是,当您尝试在数据库中设置未定义,空值或其他数据类型时,不同的ORM系统可能具有不可预测的行为。
For example, destroyAll method in Loopback.js ORM (Node.js framework) can destroy all data in a table of the database: when it does not match any records it deletes everything as described here. Imagine that you can lose all data in a production table just because you have ignored input validation.
例如,Loopback.js ORM(Node.js框架)中的destroyAll方法可以破坏数据库表中的所有数据:当它与任何记录都不匹配时,它将删除此处描述的所有内容。 想象一下,由于忽略了输入验证,您可能会丢失生产表中的所有数据。
使用身体/物体验证进行中间检查 (Use body/object validation for intermediate inspections)
To start with, you can use body/object validation for intermediate inspections. For example, we use ajv validator which is the fastest JSON Schema validator for Node.js.
首先,您可以将身体/对象验证用于中间检查。 例如,我们使用ajv验证器,它是Node.js最快的JSON模式验证器。
const Ajv = require('ajv');
const ajv = new Ajv({allErrors: true});
const speaker = {
'type': 'object',
'required': [
'id',
'name'
],
'properties': {
'id': {
'type': 'integer',
},
'name': {
'type': 'string',
},
},
};
const conversation = {
type: 'object',
required: [
'duration',
'monologues'
],
properties: {
duration: {
type: 'integer',
},
monologues: {
type: 'array',
items: monolog,
},
},
};
const body = {
type: 'object',
required: [
'speakers',
'conversations'
],
properties: {
speakers: {
type: 'array',
items: speaker,
},
conversations: {
type: 'array',
items: conversation,
},
},
};
const validate = ajv.compile(body);
const isValidTranscriptBody = transcriptBody => {
const isValid = validate(transcriptBody);
if (!isValid) {
console.error(validate.errors);
}
return isValid;
};
处理错误 (Handle errors)
Now, imagine that you forgot to check a certain object and you do some operations with the undefined property. Or you use a certain library and you get an error. It can break your instance, and the server will crash. Then, the attacker can ping a specific endpoint where there is this vulnerability and can stop your server for a long time.
现在,假设您忘了检查某个对象,而对undefined属性进行了一些操作。 或者,您使用某个库,则会出现错误。 它可能破坏您的实例,并且服务器将崩溃。 然后,攻击者可以ping通存在此漏洞的特定端点,并可以长时间停止服务器。
The simplest way to do an error handling is to use try-catch construction:
执行错误处理的最简单方法是使用try-catch构造:
try {
const data = body;
if (data.length === 0) throw new Error('Client Error');
const beacons = await this.beaconLogService.filterBeacon(data);
if (beacons.length > 0) {
const max = beacons.reduce((prev, current) => (prev.rssi > current.rssi) ? prev : current);
await this.beaconLogService.save({
...max,
userId: headers['x-uuid']
});
return {
data: {
status: 'Saved',
position: max
},
};
}
return {
data: {
status: 'Not valid object,
},
};
}
catch(err) {
this.logger.error(err.message, err.stack);
throw new HttpException('Server Error', HttpStatus.INTERNAL_SERVER_ERROR);
}
Feel free to use a new Error(‘message’) constructor for error handling or even extend this class for your own purpose!
可以随意使用新的Error('message')构造函数进行错误处理,甚至可以出于自己的目的扩展此类!
使用JOI (Use JOI)
The main lesson here is that you should always validate user input so you don't fall victim to man-in-the-middle attacks. Another way to do it is with the help of @hapi/joi – a part of the hapi ecosystem and a powerful JS data validation library.
这里的主要教训是,您应始终验证用户输入,以免成为中间人攻击的受害者。 另一种方法是在@ hapi / joi的帮助下–这是hapi生态系统的一部分,并且具有强大的JS数据验证库。
Pay attention here that the module joi has been deprecated. For this reason, the following command is a no go:
请注意此处模块joi已被弃用。 因此,以下命令是不可行的:
npm install joi
Instead, use this one:
而是使用以下命令:
npm install @hapi/joi
使用快递验证器 (Use express-validator)
One more way to validate user input is to use express-validator – a set of express.js middlewares, which comprises validator.js and function sanitizer. To install it, run the following command:
验证用户输入的另一种方法是使用express-validator –一组express.js中间件,其中包括validator.js和函数清除程序。 要安装它,请运行以下命令:
npm install --save express-validator
清理用户输入 (Sanitize user input)
Also, an important measure to take is to sanitize user input to protect the system from a MongoDB operator injection. For this, you should install and use express-mongo-sanitize:
另外,要采取的一项重要措施是清理用户输入,以保护系统免受MongoDB操作员注入。 为此,您应该安装并使用express-mongo-sanitize:
npm install express-mongo-sanitize
保护您的应用免受CSRF攻击 (Protect your app against CSRF)
Besides, you should protect your app against cross-site request forgery (CSRF). CSRF is when unauthorized commands are sent from a trusted user. You can do this with the help of csurf. Prior to that, you need to make sure that session middleware for cookies is configured as described earlier in this article. To install this Node.js module, run the command:
此外,您应该保护您的应用程序免受跨站点请求伪造(CSRF)的侵害。 CSRF是指从受信任的用户发送未经授权的命令时。 您可以在csurf的帮助下进行此操作 。 在此之前,您需要确保已按照本文前面所述配置cookie的会话中间件。 要安装此Node.js模块,请运行以下命令:
npm install csurf
6.保护您的系统免受暴力侵害 (6. Protect your system against brute force)
A brute force attack is the simplest and most common way to get access to a website or a server. The hacker (in most cases automatically, rarely manually) tries various usernames and passwords repeatedly to break into the system.
暴力攻击是访问网站或服务器的最简单,最常见的方法。 黑客(大多数情况下是自动的,很少是手动的)反复尝试使用各种用户名和密码来闯入系统。
These attacks can be prevented with the help of rate-limiter-flexible package. This package is fast, flexible, and suitable for any Node framework.
可以使用速率限制器灵活包来防止这些攻击。 该软件包快速,灵活,并且适用于任何Node框架。
To install, run the following command:
要安装,请运行以下命令:
npm i --save rate-limiter-flexible
yarn add rate-limiter-flexible
This method has a simpler but more primitive alternative: express-rate-limit. The only thing it does is limiting repeated requests to public APIs or to password reset.
此方法有一个更简单但更原始的替代方法: express-rate-limit 。 它唯一要做的就是将重复请求限制为公共API或密码重置。
npm install --save express-rate-limit
7.控制用户访问 (7. Control user access)
Among the authentication methods, there are tokens, Auth0, and JTW. Let’s focus on the third one! JTW (JSON Web Tokens) are used to transfer authentication data in client-server applications. Tokens are created by the server, signed with a secret key, and transferred to a client. Then, the client uses these tokens to confirm identity.
在身份验证方法中,有令牌,Auth0和JTW。 让我们专注于第三个! JTW(JSON Web令牌)用于在客户端服务器应用程序中传输身份验证数据。 令牌由服务器创建,用密钥签名,然后传输到客户端。 然后,客户端使用这些令牌来确认身份。
Express-jwt-permissions is a tool used together with express-jwt to check permissions of a certain token. These permissions are an array of strings inside the token:
Express-jwt-permissions是与express-jwt一起使用的工具,用于检查特定令牌的权限。 这些权限是令牌内的字符串数组:
"permissions": [
"status",
"user:read",
"user:write"
]
To install the tool, run the following command:
要安装该工具,请运行以下命令:
npm install express-jwt-permissions --save
总结 (To Wrap Up)
Here, I have listed the essential Express.js security best practices and some tools that can be used along the way.
在这里,我列出了基本的Express.js安全最佳实践和一些可以沿途使用的工具。
只是审查: (Just to review:)
I strongly recommend that you make sure that your application is resistant to malicious attacks. Otherwise, your business and your users may suffer significant losses.
我强烈建议您确保您的应用程序能够抵抗恶意攻击。 否则,您的企业和用户可能遭受重大损失。
您对Express.js项目有想法吗? (Do you have an idea for Express.js project?)
My company KeenEthics is experienced in express js development. In case you need a free estimate of a similar project, feel free to get in touch.
我的公司KeenEthics在Express js开发方面经验丰富。 如果您需要对类似项目的免费估算,请随时与我们联系 。
If you have enjoyed the article, you should definitely continue with a piece on data safety in outsourcing to Ukraine: KeenEthics Team on Guard: Your Data is Safe in Ukraine. The original article posted on KeenEthics blog can be found here: express js security tips.
如果您喜欢这篇文章,那么在向乌克兰外包时,您绝对应该继续阅读有关数据安全的文章: KeenEthics Guard卫队:您的数据在乌克兰是安全的 。 可以在此处找到发布在KeenEthics博客上的原始文章: express js安全提示 。
聚苯乙烯 (P.S.)
A huge shout-out to Volodia Andrushchak, Full-Stack Software Developer @KeenEthics for helping me with the article.
一个巨大的呼喊出来博洛迪亚Andrushchak ,帮助我的文章全栈软件开发@KeenEthics。
The original article posted on KeenEthics blog can be found here: Express.js Security Tips: Save Your App!
可以在以下位置找到发布在KeenEthics博客上的原始文章: Express.js安全提示:保存您的应用程序!
翻译自: https://www.freecodecamp.org/news/express-js-security-tips/
express.js