Most of the penetration tests that I did so far, are
Web Applications, since even if it is a thick client application, the functionality of it is heavily based on HTTP communication, using API calls or some times, even just having the mobile view of the website inside a WebView.
LocalStorage, that if I’m not wrong, every browser does it.
Below I will explain all the issues, listed on this checklist.
Note: This list of issues is still
WIP. More items will be added soon.
Crawling / File EnumerationAfter a scope is specified for a Web Application pentest, fire up your favourite directory brute-force tool and feed it a list in order to identify files and folder for your in-scope domain. After some folders are found, it can help you identify the technology in use. In case you use Burp Suite you can use its crawler that is great, also the functionality for content discovery. You can read further information about Burp Suite and tips here.
Identify Technologies in Use
This part can be easily using automated tools an extension. This part helps you understand, what possible issues can be identified. For example if an application uses
Some times, if you have nothing to report, findings those headers helps (a bit). Although, if there is exploit or an actual issue, I believe it is pointless to report it, but at least you can find some information about what type of Web Server is in use. Just intercept the request with your favourite proxy and check for the response. If the
Server header is there, then probably you got some extra info.
- Any web proxy of your choice
Information Disclosure through Error Messages
Although the title is pretty self explanatory, the goal of this part is to give the application input that would result in some form of error. This error, if there is no proper error handling, can return paths, filenames, names of users, help you with an XSS, disclose the architecture of the application and more. In order to trigger those error, try to break the syntax of the application, or specify some characters that are “blacklisted”. A lot of time, if you will request for a file with random name, containing special symbols will result in a 500 error. In case this 500 error prints the requested page, this could lead on an XSS. Of course this is an example, and errors can be found with way way to many ways.
Try manually different payloads.
Outdated Software / Libraries
Finding libraries with known vulnerabilities can be helpful for web applications, only if the vulnerable function is in use. A lot of times, there are reports for vulnerabilities in functions of libraries that are never used. In case the vulnerable function is not used, this vulnerability will be almost impossible to trigger on its own. But of course, this does not mean that if the library or the software stays the same, the vulnerable function will not be used in newer releases of the application.
Directory Listing Enabled
Nowadays, directory listing is not enabled by default for most of the public software. It is not so common (but it still happens) to find inside directories files, that can contain helpful information like credentials from the application development period. Even if the files do not contain any passwords, you can almost always extract useful information and also save time from your file enumeration process.
All the applications have different user roles. Those roles usually are:
- Unauthenticated User
- Registered User
- User with elevated privileges
Unauthenticated users are all the users that are not registered to the application and normally should have the lowest possible access. When a user is
registered, his access should be only for the files that he owns. Users with
elevated privileges are users that can have permissions to moderate one part of the application, like for example a moderator on a Facebook page. His permissions are clearly higher that a simple user, but he does not have full permissions on the application. Finally,
administrators are the users that can change the configuration of the application. Usually administrators have full control on the application, including its users and data (but this does not mean that they can read or modify them).
Once again, those users role can be identified by exploring manually the application.
In order to find a way to bypass something (authentication, processes etc.) or exploit an issue, the first thing to do is to understand how the application works, and what is the
goal of the application. The applications usually follow some patterns that are specific. for example an online market applications, the steps will be like that.
- You put your items in your basket
- Finalise your order and proceed to payment
- Complete the payment and get redirected back to the application
- When the main application loads you get the confirmation of sucess.
But what will happen if you skip step 3 and load directly step 4. Will the application accept the order as complete? Will it tell you that you don’t have the token that it expected?
Once again manually browse the application. But for inspiration you can take a look on the report below:
Input Validation / Injections
Cross-Site Scripting (XSS)
Cross-Site Scripting occurs when users’ input is not escaped and it is getting shown back to the end user. HackerOne lists XSS as number vulnerability reported with quiet high rewards. XSS can be split in 3 main categories that is
User interaction is required and usually it can be exploited by sending a link to the victim. This interaction is required because the payload is not stored anywhere. An example that a reflected XSS can be found is on a
Modern applications load its content dynamically. In this case a DOM-Based XSS occurs when the printed text is taken from the URL (for example). Let’s say you have a page that displays the temperature in a city and the URL looks like that
In this case london will be parsed from the URL and get printed inside the HTML code. The page will load the URL, split it in parts using the
? as a separator and on the second part it will parse
city=london. Then it will split that in half using the
= to identify as item the variable name and item the value of it. In case an attacker uses something like that
city=<script>alert('xss')</script>, the application will parse the malicious payload as a city name, that will then print on the page, resulting on a XSS. Of course modern browsers protect users from those easily guessable payloads, but you can always find a bypass based on the characters allowed.
Note: For me, the best way to do it is manually, just by sending a list of characters that you need for your XSS and try to create a valid payload using only characters that are not escaped.
SQL / NoSQL Injections
Databases are used to store information needed for the application. Most databases use SQL type
queries to add/delete/modify the content. Of course there are some languages that do not use the SQL language for queries, like MongoDB.
An SQL injection occurs when developers do not validate users’ input, by adding the input directly to the database query. This way attackers are able to break the SQL syntax and inject SQL commands of their choice. The impact of this vulnerability varies depending on the configuration of the database. Sometimes attackers are able to temper data of the database and in some cases they are able just to read a part of it. Like XSS, there are multiple types of SQL Injections.
- Classic SQL injection
In NoSQL injection the idea is the same, inject content on a query done to the database, with the difference that the payload is the same. A single quote
', will not break the syntax. The syntax for NoSQL is different since operators like
gt are used. Of course, you can inject complete statements and not just comparisons, using a
$, that it can be used as an operator.
Server Side Includes
This issue is not so common, but in case
SSI is enabled and misconfigured, it is highly possible that will end up with a Remote Code Execution. SSI is a technology used by the web server to update content dynamically. this can be a date, an IP of the server, or sometimes it can be a command that will return all the files inside a folder of the server. In order to test for it, try to insert a test payload like
<!--#printenv -->. In case the SSI works, after the page is printed back to you, the environment variables should be visible. Keep in mind, that if SSI works, then probably there is also an XSS on this field and vice versa.
Server Side Request Forgery
This vulnerability is also probably a not so commonly seen vulnerability, but definitely a highly paid one. Using this vulnerability, it is possible to retrieve files, access internal networks and more. This is done by inserting a
URI different than the one the server expected. For example let’s say there is an application that allows it’s users to download a YouTube video and save it to mp3 format. The Application has to connect to a URL supplied by the user in order to get the video. Let’s say that the application, shows a preview of the video while downloading the content, so there is a way to see the impact of the attack.
An attacker can use a URI that looks like that
file:///etc/password and test if the application will actually return the content of the passwd file. Additionally, there are multiple type of URI schemes that are supported. Let’s say that this only allows http/s and nothing else. What an attacker can do is request for a website like
http://localhost. Will the application serve localhost’s content to him? Finally, SSRF can be used for
Port Scanning, by measuring the response time or an error message. For example, using something like
http://localhost:5555. In case the error messages are different you can understand if a port is open or not.
Cross Side Request Forgery
The internet is built on the same principal of exchanging messages (requests), in order to retrieve information about a website. When CSRF occurs, an attacker can force his victim, do something unintentional like change his password, or make a post. This happens because the server receives a request on behalf of the victim, but it does not validate if the request was sent actually from the user. Exploiting CSRF is simple as also as identifying it. If the request does not contain a token that is dynamic, then probably the application is affected by a CSRF. In case the application uses JSON and validates the content type, you can use flash in order to send a valid request on behalf of the victim, more info can be found here.
Cross-Origin Resource Sharing (CORS)
CORS is a mechanism that instructs a web browser is a web application should run on a specific domain or not. Of course this can be more complicated when the authentication happens on other domains. CORS header is shown as
Origin: on requests and the first thing to do is try to change the origin from the actual site to something malicious. In case the response contains the following
Access-Control-Allow-Origin: * and
Access-Control-Allow-Credentials: true then it is highly possible that some valuable information can be retrieved. Additionally, some applications allow only domains that are
*.example.com. Of course if you have no valid subdomain then it is impossible to exploit it, but it can be chained with a subdomain takeover, resulting in full exploit capabilities.
XML / LDAP / Command Injection
At this moment you need to validate if your input is handled properly or now. It is common for developers to be lazy or have strict timelines, making them develop functionalities in a clumsy way, resulting in introduction of injection attacks. Vulnerabilities like XSS and SQL injections are also injection attacks, but XML, LDAP and command injection are not so common, so they have for me a different category.
XML stands for Extensible Markup Language, and it is commonly used in web applications, mainly in API tests with form of SOAP requests. A lot of applications also use it on the back end while the front is JSON. If you have an application that takes JSON input, I would suggest you to use the
Content Type Converter that will convert JSON to XML and vice versa. In order to identify is there is an injection you can use a character like a single quote and see if it affects the parser. In case there is an injection, most likely you will see an XML error. From there you can usually play with the entities, and check if you can use them in order to inject code, create an XML bomb, or retrieve some files. XML injection can result in Local File Inclusion, command injection and way more things.
I personally prefer to go manually for those issues, that using automated tools.
Applications sometimes use LDAP to authenticate their users and this is done by doing LDAP queries from what the user supplied. For example when a user signs in, a username and a password is required. Then user’s input is transferred to the LDAP server and results are returned. In case the user does not use his username but an asterisk (*), the LDAP query will run with a wildcard. in order to test if further multiple characters can be used like
Command injection is difficult to identify just by accessing the application, but in case you will find it, it means $$$$$$$. The easiest option to find command injection in my opinion is just by reading the source code. For operations like pinging a host or connecting to a server, a lot of times developers do it just by sending commands directly to the system. The goal of this issue is to break the syntax and inject your commands. Using
|, it is likely that you will be able to inject your commands on the system and get them executed.
Open redirect refers to the fact that an application does not limit the URL that the user will get redirected to, after completing an action. This happens usually when the application accepts the redirect location from a field that is user control and does not validate the domain of the redirect. This can be exploited mainly for Phishing attacks in the following way. A user wants to access his
google.com account. When an Open Redirect occurs, a malicious actor can use the actual google.com domain but with a URL like this
https://google.com?auth_redir=https://attacker.com. This can help also bypass some spam filters, since the origin of the domain is a valid one. In case there is validation for the URL of redirect, you can try to identify how it happens, what exactly is it checking. Can you have a domain like
google.attacker.com that would trick the filter, or could it be bypassed by using the Right to Left
RTLO character https://google.com%40%E2%80%AE@moc.rekcatta
Sometimes also called directory traversal, refers to a vulnerability of a web application to validate the path of a file requested by a user. Using a payload with dots and slashes
../../../, an attacker tries to go out of the directory that the application is configured to work from and reach the root directory in order to retrieve files that would give him some extra information, like reading /etc/passwd or the hosts file. Path traversal is easier to exploit on a Linux server mainly because of the standard files found there. For Windows I try to use payload that specific to the OS version with less luck. When a Path Traversal occurs, it does not have any impact in the availability of the server or the integrity, its main impact is information disclosure.
Local / Remote File Includes
A vulnerability that I have mainly seen on OSCP than in real life, it can occasionally lead to Remote Code Execution. The impact of this vulnerability is high because a malicious user is able to access a file in context of the application. What it means is that the server will load every file requested by the user. In case of an LFI, the server will load and execute (if possible) a local file, like instructed by the attacker. The difference with Path Traversal is that when a path traversal is exploited, the attacker cannot execute code, he can retrieve files, but in case of an LFI, usually code is executed also.
When an RFI vulnerability is identified, the easiest option is to set up a
Web Server and serve the file for the application directly. That way the Web Application will load our malicious file and executed on the context of the application, usually resulting in RCE. Sometimes the server will not connect to an HTTP server, in this case set up a network share and test if the web server will access your
HTTP Request Smuggling
This issue came in my attention recently, after James Kettle from PortSwigger, showed how it is possible to trick a Proxy into processing multiple requests at once. This happens because both the
Transfer-Encoding and the
Content-Length headers are getting submitted, tricking the proxy into believing that there is one request. The content length of the request should cover all the first request making the front-end process the request without seeing anything suspicious. After the request is accepted, the proxy will see that the request is actually split in multiple parts because of the
chunked Transfer Encoding header but it will be processed separately because of the Content-Length header.
This is quite a smart approach and in my opinion is worth it 100% to spend some time reading how to test for it. My explanation is really generic and PortSwigger explain this issue in way more depth, with nice examples.
Session ID Entropy
This issue is not so common nowadays, mainly because people are getting more informed about security. Entropy refers to amount of "randomness" that there is on an item, in this case a session token. This issue occurs when a session token, is generated without enough entropy. An example can be a session token that every time a user is signing in is increasing by one. Or a session token that has only 4 digits of randomness.
Improper Session Termination
This issue is quite common, and referees to the fact that a session token, is still active after a user requested for the termination of it, by logging out. This issue is not exploitable by itself, but it is an extra security measure. In order to test it, send a valid request and store it on Repeater or save the session token somewhere. After that, log out of the account and send again the previous request, with the token that you requested to terminate. In case the request is accepted by the server, then it is possible to understand that the server is not ‘killing’ the session directly after the user logs out.