Analysis of Six Common Web Security Attacks and Defenses
Foreword
In the Internet era, data security and personal privacy have been challenged unprecedentedly, and various novel attack techniques have emerged one after another. How can we better protect our data? This article mainly focuses on the analysis of several common types of attacks and methods of defense.
1. XSS
XSS (Cross-Site Scripting), a cross-site scripting attack, can only be called XSS because the abbreviation and CSS overlap. Cross-site scripting attack refers to an attack carried out by running illegal HTML tags or JavaScript in the browsers of registered users of web sites with security vulnerabilities.
Cross-site scripting attacks may have the following effects:
- Use fake input forms to defraud users of personal information.
- Using the script to steal the user's cookie value, the victim can help the attacker send malicious requests without knowing it.
- Display fake articles or images.
The principle of XSS is that a malicious attacker inserts malicious executable webpage script code into a Web page. When the user browses the page, the script code embedded in the Web will be executed, so that the attacker can steal user information or other violations. The purpose of user security and privacy .
XSS attack methods are ever-changing, but they can be roughly subdivided into several types.
1. Non-persistent XSS (Reflected XSS)
Non-persistent XSS vulnerabilities are generally sent to others by sending URLs with malicious script code parameters . When the URL address is opened, the unique malicious code parameters are parsed and executed by HTML.
For example, if the page contains the following code:
<select>
<script>
document.write(''
+ '<option value=1>'
+ location.href.substring(location.href.indexOf('default=') + 8)
+ '</option>'
);
document.write('<option value=2>English</option>');
</script>
</select>
An attacker can https://xxx.com/xxx?default=<script>alert(document.cookie)</script>
inject executable script code directly through a URL (similar to: ). However, some browsers such as Chrome have built-in XSS filters that can prevent most reflected XSS attacks.
Non-persistent XSS exploits have the following characteristics:
- Immediate, without server storage, an attack can be completed directly through HTTP GET and POST requests to obtain user privacy data.
- The attacker needs to trick the click, and it must be initiated by the user clicking on the link
- Low feedback rate, making it harder to spot and respond to fixes
- Steal user sensitive and confidential information
To prevent non-persistent XSS vulnerabilities, you need to ensure a few things:
- All content or rendered data rendered by a web page must come from the server.
- Try not to get data directly from the DOM API such as URL, document.referrer, document.formsetc.
- Try not to use eval, new Function(), document.write(), document.writeln(), window.setInterval(), window.setTimeout(), innerHTML, and document.createElement()other methods that execute strings.
- If you can't do the above points, you must also escape the string parameters passed in to methods involving DOM rendering.
- When front-end rendering, any field needs to be escaped and encoded.
2. Persistent XSS (Stored XSS)
Persistent XSS vulnerabilities generally exist in interactive functions such as form submission, such as article comments, submission of text information, etc. XSS vulnerabilities exploited by hackers submit the content to the database for persistent storage through normal functions, and the current-end page obtains the back-end from the database. When the injected code is read, it happens to be rendered and executed.
For example, for the comment function, it is necessary to protect against persistent XSS attacks, because I can enter the following in the comment
The main injection method is similar to the non-persistent XSS vulnerability, except that the persistent type does not come from URL, referer, forms, etc., but from the data read from the database by the backend . Persistent XSS attacks do not need to trick clicks, hackers only need to complete the injection where the form is submitted, but the cost of this XSS attack is relatively high.
A successful attack requires the following conditions to be met at the same time:
- The backend of the POST request to submit the form is directly stored without escaping.
- The backend retrieves data from the database without escaping and directly outputs it to the frontend.
- The front-end gets the back-end data and renders it directly into DOM without escaping.
Persistent XSS has the following characteristics:
- Persistence, embedded in the database
- Steal users' sensitive private information
- Wide range of hazards
3. How to defend
There are usually two ways to defend against XSS attacks.
1) CSP
CSP essentially establishes a whitelist, and the developer explicitly tells the browser which external resources can be loaded and executed. We only need to configure the rules, how to intercept is implemented by the browser itself. We can minimize XSS attacks in this way.
There are usually two ways to enable CSP:
- Set Content-Security-Policy in HTTP Header
- How to set meta tags
Here is an example of setting HTTP Header:
- Only allow loading of resources from this site
Content-Security-Policy: default-src 'self'
- Only allow HTTPS protocol images to be loaded
Content-Security-Policy: img-src https://*
- Allow any source frame to be loaded
Content-Security-Policy: child-src 'none'
For more properties, see the Content-Security-Policy documentation
In this way, as long as the developer configures the correct rules, even if the website has vulnerabilities, the attacker cannot execute its attack code, and the compatibility of CSP is also good.
2) Escape character
User input can never be trusted. The most common practice is to escape the content of input and output, and escape quotation marks, angle brackets, and slashes.
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;')
str = str.replace(/'/g, ''')
str = str.replace(/`/g, '`')
str = str.replace(/\//g, '/')
return str
}
But for displaying rich text, obviously all characters cannot be escaped by the above method, because this will also filter out the required format. In this case, the whitelist filtering method is usually used, and of course, the blacklist filtering method can also be used. However, considering that there are too many tags and tag attributes to be filtered, the whitelist method is more recommended.
const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1><script>alert("xss");</script>
console.log(html)
The above example uses js-xss to implement, you can see that the h1 tag is preserved in the output and the script tag is filtered.
3) HttpOnly Cookie
This is the most effective defense against XSS attacks from stealing user cookies. When a web application sets a cookie, set its attribute to HttpOnly to prevent the web page's cookie from being stolen by malicious JavaScript on the client side and protect the user's cookie information.
2. CSRF
CSRF (Cross Site Request Forgery), that is, Cross Site Request Forgery, is a common web attack that uses the user's logged-in identity to complete illegal operations in the user's name without the user's knowledge.
1. The principle of CSRF attack
Let's first introduce the principle of CSRF attack:
Three conditions must be met to complete a CSRF attack:
- The user has logged into site A and the cookie is recorded locally
- In the case that the user does not log out of site A (that is, when the cookie is in effect), the user visits a dangerous site B (site B requires access to site A) provided by a malicious attacker.
- Site A does not do any CSRF defense
Let's look at an example: When we log in to the transfer page, we suddenly see the link "XXX private photos, don't look at it, regret it for a lifetime" , we can't bear the restlessness, and immediately click on the dangerous website (the page code is as shown in the figure below) shown), but as soon as the page loads, submitForm
this method is executed to submit a transfer request, thereby transferring 10 blocks to the hacker.
2. How to defend
The following rules can be followed to prevent CSRF attacks:
- Get requests do not modify the data
- Prevent third-party websites from accessing user cookies
- Block third-party website request interface
- The request is accompanied by verification information, such as verification code or Token
1) SameSite
The SameSite attribute can be set on cookies. This attribute indicates that cookies are not sent with cross-domain requests, which can greatly reduce CSRF attacks, but this attribute is not currently compatible with all browsers.
2) Referer Check
HTTP Referer is part of the header. When the browser sends a request to the web server, it usually brings the Referer information to tell the server which page it is linked from, and the server can obtain some information for processing. CSRF attacks can be defended against by examining the origin of the request. The referer of a normal request has certain rules. For example, the referer that submits the form must be the request initiated on the page. So by checking whether the value of the http header referer is this page, it is judged whether it is a CSRF attack.
However, in some cases, such as jumping from https to http, the browser will not send the referer due to security considerations, and the server will not be able to check. If other websites in the same domain as the website have XSS vulnerabilities, the attacker can inject malicious scripts into other websites, and the victim will also be attacked if the victim enters such a website in the same domain. For the above reasons, Referer Check cannot be completely relied upon as the main means of defending against CSRF. However, the occurrence of CSRF attacks can be monitored through Referer Check.
3) Anti CSRF Token
The more complete solution at present is to join Anti-CSRF-Token. That is, when sending a request, a randomly generated token is added as a parameter to the HTTP request, and an interceptor is established on the server to verify the token. The server reads the token value in the browser's current domain cookie, and checks whether the token in the request and the token value in the cookie both exist and are equal, and it considers this to be a legitimate request. Otherwise, the request is considered illegal and the service is refused.
This method is much safer than the Referer check . The token can be generated after the user logs in and placed in the session or cookie, and then the server takes the token out of the session or cookie every time a request is made, which is the same as the token in this request. Compare. Due to the existence of the token, the attacker can no longer construct a complete URL to implement CSRF attack. However, when dealing with the coexistence of multiple pages, when a page consumes the token, the forms on other pages still save the consumed token, and a token error occurs when the forms on other pages are submitted.
4) Verification code
During the interaction between the application and the user, especially the core step of account transaction, the user is forced to enter the verification code to complete the final request. In general, CAPTCHA is good enough to contain CSRF attacks. However, adding verification codes reduces the user experience, and the website cannot add verification codes to all operations . Therefore, the verification code can only be used as an auxiliary means to set the verification code at the key business points.
3. Click Hijacking
Clickjacking is a visual deception attack. The attacker embeds the website to be attacked into his own web page through iframe nesting, and sets the iframe to be transparent, revealing a button in the page to induce users to click.
1. Features
- High concealment, defrauding users to operate
- "UI-overlay attack"
- Use iframe or other tag attributes
2. The principle of clickjacking
After the user logs into the system of website A, the attacker is tempted to open a third-party website, and the third-party website introduces the page content of website A through iframe. Above is the click of the button for A's website.
Next, let's take an example: I have posted a lot of videos on Youku, and if I want more people to pay attention to it, I can do it through clickjacking.
iframe {
width: 1440px;
height: 900px;
position: absolute;
top: -0px;
left: -0px;
z-index: 2;
-moz-opacity: 0;
opacity: 0;
filter: alpha(opacity=0);
}
button {
position: absolute;
top: 270px;
left: 1150px;
z-index: 1;
width: 90px;
height:40px;
}
</style>
......
<button>Click to undress</button>
<img src="http://pic1.win4000.com/wallpaper/2018-03-19/5aaf2bf0122d2.jpg">
<iframe src="http://i.youku.com/u/UMjA0NTg4Njcy" scrolling="no"></iframe>
As can be seen from the above figure, the attacker hides the real interface of the user operation by using the picture as the background of the page. When you click the button with curiosity, the real click is actually the subscribe button of the hidden page, and then it will be displayed on the page. You subscribed without your knowledge.
3. How to defend
1)X-FRAME-OPTIONS
X-FRAME-OPTIONS
is an HTTP response header that has a good support in modern browsers. This HTTP response header is for defense against clickjacking attacks nested with iframes.
The response header has three optional values, which are
- DENY, means that the page is not allowed to be displayed through iframe
- SAMEORIGIN, which means that the page can be displayed in an iframe under the same domain name
- ALLOW-FROM, indicating that the page can be displayed in an iframe of the specified source
2) JavaScript defense
For some ancient browsers, the above method cannot be supported, so we can only defend against click hijacking through JS.
<head>
<style id="click-jack">
html {
display: none !important;
}
</style>
</head>
<body>
<script>
if (self == top) {
var style = document.getElementById('click-jack')
document.body.removeChild(style)
} else {
top.location = self.location
}
</script>
</body>
The function of the above code is that when the page is loaded by iframe, the attacker's web page does not display all the content directly.
4. URL Jump Vulnerability
Definition: A security problem caused by directing an application to an unsafe third-party area with the help of unauthenticated URL redirection.
1. The principle of URL jump vulnerability
Hackers use URL jumping vulnerabilities to induce users with low security awareness to click, resulting in user information leakage or loss of funds. The principle is that hackers build malicious links (links need to be disguised to be as confusing as possible) and post them in QQ groups or post bars/forums with a lot of pageviews.
After a user with low security awareness clicks, it is parsed by the server or browser and then jumps to a malicious website.
Malicious links need to be disguised, and a common practice is to add a malicious URL behind a familiar link to confuse users.
For example, if you disguise the URL like the following, can you identify it as a malicious URL?
http://gate.baidu.com/index?act=go&url=http://t.cn/RVTatrd
http://qt.qq.com/safecheck.html?flag=1&url=http://t.cn/RVTatrd
http://tieba.baidu.com/f/user/passport?jumpUrl=http://t.cn/RVTatrd
2. Implementation:
- Header jump
- Javascript jump
- META tag jump
Here we give a Header jump implementation method:
<?php
$url=$_GET['jumpto'];
header("Location: $url");
?>
http://www.rendc.org/login.php?jumpto=http://www.evil.com
Here the user will think it www.rendc.org
is credible, but clicking on the above link will lead the user to finally visit www.evil.comthis malicious URL.
3. How to defend
1) Limitation of referer
If the source of passing URL parameters is determined, we can implement security restrictions in this way to ensure the validity of the URL and prevent malicious users from generating jump links by themselves
2) Add validity verification Token
We guarantee that all generated links are from our trusted domain. By adding uncontrollable Tokens to the generated links to verify the generated links, users can avoid generating their own malicious links and being exploited, but if The function itself requires more openness, which may lead to certain restrictions.
5. SQL injection
SQL injection is a common web security vulnerability that allows attackers to access or modify data, or to exploit potential database vulnerabilities.
1. The principle of SQL injection
Let's take an example of a master key to illustrate its principle:
<form action="/login" method="POST">
<p>Username: <input type="text" name="username" /></p>
<p>Password: <input type="password" name="password" /></p>
<p><input type="submit" value="login" /></p>
</form>
The back-end SQL statement may look like this:
let querySQL = `
SELECT *
FROM user
WHERE username='${username}'
AND psw='${password}'
`;
// The next step is to execute the sql statement...
This is the login page we often see, but if a malicious attacker enters the username admin' --and password arbitrarily, they can log in directly to the system. why! ----This is SQL injection
The SQL statement we envisioned earlier was:
SELECT * FROM user WHERE username='admin' AND psw='password'
But malicious attackers use strange usernames to change your SQL statement into the following form:
SELECT * FROM user WHERE username='admin' --' AND psw='xxxx'
In SQL, it ' --means closing and commenting, and -- means the content behind the comment, so the query statement becomes:
SELECT * FROM user WHERE username='admin'
The so-called universal password is essentially a way of using SQL injection.
The process of a SQL injection includes the following processes:
- Get user request parameters
- spliced into the code
- The SQL statement was successfully executed according to the semantics of our constructed parameters
Prerequisites for SQL injection:
1. The input data can be controlled
2. The code to be executed by the server is spliced with the controlled data . We will find that the SQL injection process is similar to the normal request server, but the hacker controls the data and constructs the SQL query, while the normal request does not perform the SQL query step. The essence of SQL injection: the data and the code are not separated, that is, the data is treated as code to execute.
2. Hazard
- Get database information
- Administrator backend username and password
- Obtain other database sensitive information: username, password, mobile phone number, ID card, bank card information...
- The Entire Database: Take Off Your Pants
- Get server permissions
- Implant Webshell to obtain server backdoor
- Read server sensitive files
3. How to defend
- Strictly limit the operation authority of the database of the web application , and provide this user with the minimum authority that can only satisfy his work, thereby minimizing the harm to the database caused by injection attacks
- The back-end code checks whether the input data is as expected , strictly restricts the type of variables, such as using regular expressions for some matching processing.
- Escape or encode special characters (', ", \, <, >, &, *, ;, etc.) that enter the database . Basically, all back-end languages have the ability to escape strings. methods, such as lodash's lodash._escapehtmlchar library.
- It is recommended to use the parameterized query interface provided by the database for all query statements . Parameterized statements use parameters instead of embedding user input variables into SQL statements, that is, do not directly concatenate SQL statements. For example, the ? placeholder parameter in the query method of the mysqljs library in Node.js.
6. OS command injection attack
OS command injection is similar to SQL injection, except that SQL injection is for the database, and OS command injection is for the operating system. OS command injection attacks refer to the execution of illegal operating system commands through web applications to achieve the purpose of attacks. As long as you can call shell functions, there is a risk of being attacked. If there is an omission in invoking the shell, the inserted illegal command can be executed.
Command injection attacks can send commands to the shell to have the Windows or Linux operating system's command line launch programs. That is, various programs installed on the operating system can be executed by command injection attacks.
1. Principle
The hacker constructs the command and submits it to the web application. The web application extracts the command constructed by the hacker and splices it into the executed command. Because the command injected by the hacker breaks the original command structure, the web application executes additional commands. Finally, the web application The program outputs the result of execution to the response page.
We use an example to illustrate the principle. If you need to implement a requirement: the user submits some content to the server, and then executes some system commands on the server to return a result to the user
// Take Node.js as an example, if the user-specified repo needs to be downloaded from github in the interface
const exec = require('mz/child_process').exec;
let params = {/* user input parameters */};
exec(`git clone ${params.repo} /some/path`);
If it is params.repo
passed in, https://github.com/admin/admin.github.io.git
the desired code can be downloaded from the specified git repo.
But it's bad if you params.repo
pass in that https://github.com/xx/xx.git && rm -rf /* &&
your service happens to be started with root privileges.
2. How to defend
- The backend imposes rules (such as regular expressions) on the content submitted by the frontend.
- Perform command line parameter escape filtering on all incoming parameters before calling system commands.
- Do not splicing command statements directly, use some tools for splicing and escaping preprocessing, such as Node.js
shell-escape npm
packages