Sometimes, as a test engineer, you need to check that your web application is not vulnerable.

I am not going to describe what security testing is because there are many introductory articles about it. In some companies, security testing or vulnerability assessment is performed by penetration testers from a special team or by the information security department, but it happens that such kind of activities have to be done by ordinary manual testers.

I would like to list practical actions of a brief security testing that can be performed manually and right away without additional tooling.

The main testing landmarks are:

  • HTTPS
  • XSS (Cross-site scripting)
  • SQL Injection
  • CSP (Content Security Policy)
  • CORS (Cross-Origin Resource Sharing)
  • CSRF (Cross-Site Request Forgery). Here, in terms of defense
  • Open Redirect

HTTPS

Manual testing of your web application over HTTPS means performing a regression run with HTTPS in URLs.

If all functionality works as expected, then it is OK, but here are a few tips:

1. URLs with HTTP protocol should redirect to HTTPS. This is a server’s side setting and a part of nonfunctional requirements — ask your developers about it.

If there is no redirect, then use a browser extension for automatic redirection from HTTP to HTTPS:

Some browsers (Firefox since version 83 and since version 91 in Private mode) do it by default without any extensions.

2. Check the certificate for validity.

Firefox: under the «protection» icon in the URL bar (since version 70, it is not colored green):

Firefox Connection security

Fig. 1. Firefox Connection security

Chrome: under the same «protection» icon or in the Security Panel in DevTools:

Chrome DevTools Security Panel

Fig. 2. Chrome DevTools Security Panel

3. Watch out for mixed content!

All your data should be loaded over HTTPS. If your page is loaded over secure HTTPS, but other resources (images, videos, scripts) are loaded over an insecure HTTP, you’ll be notified about it in a browser’s Console. In some cases, «mixed content» may be the reason that content may not be displayed on the web page.

4. All URLs inside <head> tag should have HTTPS protocol.

Check href, content, and src attributes in <link>, <meta>, and <script> tags:

All URLs inside <head> tag have HTTPS protocol

Fig. 3. All URLs inside <head> tag have HTTPS protocol

5. All sharing widgets should provide HTTPS URLs.

Check pop-ups of Facebook, Twitter, or «Copy link» buttons: all shared links should have HTTPS protocol. Click on it and check what link is going to be shared.

Twitter’s widget shares HTTPS link

Fig. 4. Twitter’s widget shares HTTPS link

Further reading:

XSS (Cross-site scripting)

Cross-site scripting is the most common security vulnerability that can be found in web applications. It enables the attacker to put his client-side script into a web page, and this script will be executed when another user opens a spoofed page.

Examples of XSS execution

Fig. 5. Examples of XSS execution

Examples of XSS execution

Fig. 6. Examples of XSS execution

The most common types of XSS are:

  • Reflected XSS, when script executes immediately (in search suggestions or by following a link with XSS in URL);
  • Stored XSS, when script saves (as a user’s comment) and executes when another user opens the page.

For both types of XSS we will test how developers coped with escaping special special characters to prevent XSS attacks. Some developers argue that escaping should be done on frontend, and others argue that it should be done on backend, but for safety, it must be done both on frontend and backend.

Based on the above, the principles of testing XSS are:

  1. Take the XSS vector → put it in all forms and inputs → press [Enter] → see what happens;
  2. Take the XSS vector → put it URL → press [Enter] → see what happens.

The main thing in these cases is to have a set of universal XSS vectors, for example:

  • &lt;XSS>'':!--"&lt;hr/>&{()}

  • &lt;img/src='x'onerror=alert(1)>

  • "&lt;img/src='x'onerror=alert(1)>"@gmail.com

  • &lt;%2Ftitle>&lt;svg%2Fonload%3Dprompt'XSS'>

  • javascript:/*-->&lt;/marquee>&lt;/script>&lt;/title>&lt;/textarea>&lt;/noscript>&lt;/style>&lt;/xmp>">[img=1]&lt;img -/style=-=expression&#40&#47;&#42;'/-/*&#39;,/**/eval(name)//&#41;;width:100%;height:100%;position:absolute;behavior:url(#default#VML);-o-link:javascript:eval(title);-o-link-source:current name=alert(1) onerror=eval(name) src=1 autofocus onfocus=eval(name) onclick=eval(name) onmouseover=eval(name) background=javascript:eval(name)//>"

  • For URL: #'">&lt;script>prompt(document.domain)&lt;/script>1

More examples:

If your web application is based on a popular UI framework, then with a high probability, it has protection for XSS attacks «out of the box», but the manual check will not be superfluous.

3. Check for an X-XSS-Protection header.

This header stops pages from loading when they detect reflected cross-site scripting attacks. This feature only partially protects against XSS attacks because it is supported only by a few browsers. At least, expect to see (or ask developers to implement) this value:

x-xss-protection: 1; mode=block

Further reading:

SQL Injection

For brief manual testing without special knowledge, SQL injection may be the same as XSS.

You should put SQL injection payloads in the forms and inputs in the hope they will not crash your web application.

Further reading:

CSP (Content Security Policy)

According to Content Security Policy, the source code on the site could be loaded only by the site itself (same-origin policy) or from allowed sites (resources). This is one of the ways to protect against XSS attacks — if the attacker somehow implemented a link to his script into your site, this script will not be loaded from the attacker’s resource because this resource is not in the allowlist.

For example, scripts, images, and other content on https://developer.mozilla.org can be loaded only from https://developer.mozilla.org OR from the allowed sites.

The allowlist of Content Security Policy resources can be found in response headers:

Content-Security-Policy response header

Fig. 7. Content-Security-Policy response header

The testing vectors are:

  1. All allowed resources are loading;
  2. Watch out for errors of blocked content in a browser’s Console.

Common case: developers forget to put some allowed resources in a white list, and due to this, this resource does not load.

Content Security Policy

Fig. 8. Content Security Policy: The page’s settings blocked the loading of the resource

  1. All data from not allowed resources is blocked.

To test that third-party resource does not load, you can run this script in the browser’s Console:

fetch("https://example.com/").then(response => response.json()).then(data => console.log(data));

If you see the Content Security Policy error: «The page’s settings blocked the loading of the resource…» — then the test passed.

Content Security Policy

Fig. 9. Content Security Policy: The page’s settings blocked the loading of the resource

CORS (Cross-Origin Resource Sharing)

According to Cross-Origin Resource Sharing (based on HTTP-headers), a site can give permission to third-party sites to have access to its content.

How to test:

1. Make an HTTP request:

curl -i 'https://example.com/' -H 'Origin: http://evil.com/'

If you will see the Access-Control-Allow-Origin response header — it is a bug. It means that our site (https://example.com) gives access to an absolutely unknown resource.

2. Watch out for errors of blocked content in a browser’s Console:

Cross-Origin Request Blocked

Fig. 10. Cross-Origin Request Blocked

Further reading:

CSRF (Cross-Site Request Forgery). Here, in terms of defense

CSRF is a name for a type of attack when an unauthorized command is submitted from a trusted user. In most cases, this command includes in the URL as a malicious parameter, for example:

https://example.com/?action=delete_session_id&id=123

To prevent such kinds of actions, sites can implement unique tokens in each truthful request (in GET parameter, in the header, or as a cookie), for example:

curl -X POST 'https://example.com/' -H 'X-CSRF-Token: pebesbmvvrac9r7ieaq0rxf5sqz49ti8'

There are two test cases:

1. If you know that your site has CSRF tokens, you can:

Make a request without a CSRF token or with a spoiled CSRF token — in this case, you should not get a valid response.

2. Or, if your site does not have CSRF tokens, you still can try to make an unauthorized request:

Steps:

1. Find POST request on your site;

2. Make an HTML file with a button that will run this request, but without any headers:

<html><head></head><body>
<form method="POST" action="https://accounts.firefox.com/metrics">
<input type="submit" name="button" value="OK"></form>
</body></html>

3. Open your HTML file and click on the button (run the request).

If you see response code = 400, 401, 403, or 404 — it is OK, at least your site does not allow unauthorized requests.

Bad Request

Fig. 11. Bad Request

Further reading:

Open Redirect

If your web application supports Open Redirect, then it has potentially vulnerable functionality.

How does it work? If you pass in the URL a GET parameter with the link, then a passed link will be opened. The GET parameter for redirection in URL could be arbitrary (as developers decide, usually: url, link, retpath, or continue), for example:

https://example.com/destination?retpath=http://example.com/redirection

Instead of open /destination, it will redirect to /redirection.

Open Redirect is commonly used during authorization when the user should be returned to the original page after logging in ⇒ the Open Redirect links should be strictly validated to prevent redirects to third-party sites.

The testing vectors are:

  1. Redirect works only for allowed sites (ideally, only for URLs of the same domain);
  2. Redirect does not work for third-party sites.

If you try to open https://example.com/?url=https://mozilla.org, only example.com site should open:

No redirection through GET parameter in URL

Fig. 12. No redirection through GET parameter in URL


As I pointed out at the beginning, I have listed only brief checks for manual execution. Of course, there are a bunch of tools for deep security testing, like Burp Suite.

Further reading:

Copy @ Medium