How to use User Agent to attack websites

What Is a Browser's User Agent?

The User Agent is a string of text that identifies the browser and operating system for the web server. User Agent is passed in the HTTP header when the browser makes a request to the web server.

You can view the transmitted HTTP headers, including User Agent, in the Webmaster Developer Tools. For example, in Google Chrome to do this, press F12, go to the Network tab and in the General window, find Request Headers:

Or you can make it even easier – go to the page of one of the many services that show your User Agent: https://suip.biz/?act=my-user-agent

User Agent example:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36

The string is not very clear – it is clear that this is Chrome and that its version is 86.

The plot thickens: Chrome is pretending to be both Mozilla and Safari. To understand why, we’ll have to examine the history of user agents and browsers.

How can the User Agent be used to attack websites? I know at least 3 options:

  • SQL Injection via User Agent
  • XSS with User Agent
  • Spoofing User Agent to deceive the server

This guide will show you how to change the User Agent and inject through the User Agent to pretend to be another device or perform attacks on the site.

The User Agent String Mess

Mosaic was one of the first browsers. Its user agent string was NCSA_Mosaic/2.0. Later, Mozilla came along (later renamed Netscape), and its user agent was Mozilla/1.0. Mozilla was a more advanced browser than Mosaic – in particular, it supported frames. Web servers checked to see that the user agent contained the word Mozilla and sent pages containing frames to Mozilla browsers. To other browsers, web servers sent the old pages without frames.

Eventually, Microsoft’s Internet Explorer came along and it supported frames, too. However, IE didn’t receive web pages with frames, because web servers just sent those to Mozilla browsers. To fix this problem, Microsoft added the word Mozilla to their user agent and threw in additional information (the word “compatible” and a reference to IE.) Web servers were happy to see the word Mozilla and sent IE the modern web pages. Other browsers that came later did the same thing.

Eventually, some servers looked for the word Gecko – Firefox’s rendering engine – and served Gecko browsers different pages than older browsers. KHTML – originally developed for Konquerer on Linux’s KDE desktop – added the words “like Gecko” so they’d get the modern pages designed for Gecko, too. WebKit was based on KHTML – when it was developed, they added the word WebKit and kept the original “KHTML, like Gecko” line for compatibility purposes. In this way, browser developers kept adding words to their user agents over time.

Web servers don’t really care what the exact user agent string is – they just check to see if it contains a specific word (source).

XSS via User Agent

XSS vulnerabilities can be:

  • Stored (Persistent)
  • Reflected (Non-persisten)

All XSS shown below are non-persistent, that is, they are only shown to the user who exploits them, and therefore are not dangerous. Such vulnerabilities are usually not even accepted by Bounty programs (some large companies give a reward for vulnerabilities found, if you report them, this is called Bug Bounty).

We'll start with the simplest way to change User Agent – right in a web browser. Of course, there are many browser extensions for this, but you can spoof the User Agent even without them.

Google chrome

The Chrome user agent switcher is part of the developer tools. Open them by clicking the Menu button and choosing More Tools → Developer Tools. You can also use the F12 key on your keyboard.

Find “Console” in the lower half of the window – if it is missing, then press the ESC button:

Click the menu button to the right of the Console tab at the bottom of the developer toolbar and select “Network conditions”.

In the “Network conditions” tab, uncheck the “Select automatically” box next to “User agent”. Then you can select the user agent from the list or copy and paste the user agent into the box.

This setting is temporary. It only works when the Developer Tools panel is open and only for the current tab.

A sample user agent for Linux is missing for some reason. If you want sites to think that you are using Linux, then enter something like the following:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36

Mozilla Firefox

To access the about:config page, type about:config into Firefox’s address bar and press Enter. You’ll see a warning–be careful when you change settings here, you could mess up Firefox’s settings.

Type useragent into the filter box. We’re looking for the general.useragent.overridepreference, but it probably won’t exist on your system.

To create the preference, right-click on the about:config page, point to New, and select String.

Name the preference general.useragent.override .

Enter your desired user agent as the value of the preference. You’ll have to look up your desired user agent on the web and enter it exactly. For example, the following user agent is used by Googlebot, Google’s web crawler:

Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

For Linux, you can take this line:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36

This setting applies to every open tab and persists until you change it, even if you close and reopen Firefox.

To revert Firefox to the default user agent, right-click the “general.useragent.override” preference and select Reset.

If for whatleaks.com you enter User Agent as a string

<script>alert(1)</script>

We will get an alert popup window.

This is the whatsmyuseragent.org website:

This is the site getright.com/useragent.html

Site manytools.org/http-html-text/user-agent-string/

There is no XSS injection on amiunique.org/fp, but the JavaScript code has broken.

In principle, one could not go far for examples, I myself on SuIP.biz had exactly the same problem (https://suip.biz/?act=my-user-agent), but I fixed it. In fact, the user can really change on the fly the page they want to see. If no one else sees this page, then there is no problem. It's another matter if the User Agent values are saved and then can be executed as JavaScript code, that is, if the User Agent values are saved and then shown to someone else, for example, the site owner (say, when analyzing statistics) or other users (for example, the popular or recent User Agent widget).

How to do SQL injection via User Agent

Have you thought about it too? If programmers forget that the User Agent should not be trusted like absolutely everything else coming from users, then tags and special characters may not be filtered there? We have already seen an example of this – on all the above sites, special characters in the <script> tag are not filtered or replaced.

What if special characters are not filtered either and the User Agent value is saved to the database? And this is SQL injection! Applications that can save User Agent values to a database include programs for collecting website statistics, metrics, recent visitor browser widgets, and so on.

BWAPP has an example of User Agent injection. There it is called “SQL Injection - Stored (User-Agent)”.

If you enter something like

Chrome'

Then at the output we will receive a familiar message:

Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Chrome', '192.168.0.89')' at line 1

Of course, where SQLi is, there is sqlmap. To test SQL injection in User Agent, use the --user-agent option, in which specify the injection point with * (asterisk). Example command:

sqlmap -u 'http://192.168.0.96/bWAPP/sqli_17.php' --user-agent="Chrome*" --cookie 'PHPSESSID=a3400ca39ae4c6c1b25bb1eeb91c5410; security_level=0' --dbs

Of course, the vulnerability was found and a list of databases was displayed:

How to spoof User Agent on the command line

How to change User Agent value in cURL

Use the -A option to change the User Agent for the cURL utility. Compare the output of the two commands:

curl -I https://suip.biz
curl -I -A 'Chrome' https://suip.biz

How to change User Agent value in PhantomJS

Create a ua_test.js file and copy into it:

var webPage = require('webpage');
var page = webPage.create();

page.settings.userAgent = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36';

page.open('https://suip.biz/ru/?act=my-user-agent', function (status) {

	console.log('Stripped down page text:\n' + page.content);
	phantom.exit();
});

Let's check the User Agent in PhantomJS:

phantomjs ua_test.js

Let's run as follows to immediately filter the value we need:

phantomjs ua_test.js | grep -E -o '<h1>.*</h1>'

How to Spoof User Agent in Burp Suite

In Burp Suite go to the Proxy → Options tab, find the Match and Replace section. There are already several rules for replacing User Agent to emulate requests from various devices.

You can include existing rules or create a new one. To create a new one, click the “Add” button.

For “Type” select “Request header”.

For the “Match” field, specify

^User-Agent.*$

In the “Replace” field, enter the value that will replace the HTTP header of the user agent. Please note that since we are replacing the entire header, it must begin with the “User-Agent: ” string.

In the “Comment” field, enter any comment to quickly remember what this title is for.

Check the “Regex match” checkbox.

Enable it by checking the box in the “Enabled” column.

By default, Burp Suite listens on localhost:8080 as a proxy.

If you want Burp Suite to become an interception proxy for web browsers, including HTTPS traffic, than you have to configure Burp Suite to work with browsers (import SSL certificates). Remember: modern web browsers usually ignore SSL certificates, which are trusted at the system level!

With cURL, you can use the -x option to send a request through Burp Suite, for example:

curl -x http://localhost:8080 -A 'Any User Agent' --cookie 'security_level=0; PHPSESSID=46d368f57a7c0e17905377f07846b5b0' 'http://192.168.0.96/bWAPP/sqli_17.php'

As you can see, the value of the User Agent header was changed, and we received an error message that may indicate an SQL injection.

User-Agent Impersonation

OWASP Mutillidae II has a “User-Agent Impersonation” exercise. If you followed the article “How to install OWASP Mutillidae II and Damn Vulnerable Web Application (DVWA) in Kali Linux”, then you will have this task at http://localhost/mutillidae/index.php?page=user-agent-impersonation.php.

On this page we are shown the message:

Sorry. You do not look like an Apple iPad using Safari Browser.
This page uses JavaScript browser and O/S fingerprinting to decide if the user-agent is allowed.

There is a variant of my solution further, but I recommend solving this example on your own – it is not as simple as it seems.

This example was prepared as the very first in this article, since bypassing the check seems elementary. It would seem that we select the correct User Agent in the Developer Tools, like this

Mozilla/5.0 (iPad; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1

and the task is completed.

But something went wrong:

The page does not want to accept a User Agent that matches the condition.

I looked at the source code and found there:

if(
		window.navigator.platform === "iPad" && 
		window.navigator.appName === "Netscape" &&
		window.navigator.appCodeName === "Mozilla" &&
		window.navigator.appVersion.indexOf("iPad") !== -1 &&
		window.navigator.appVersion.indexOf("Mac") !== -1 &&
		window.navigator.appVersion.indexOf("AppleWebKit") !== -1 &&
		window.navigator.appVersion.indexOf("Safari") !== -1 &&
		window.navigator.product === "Gecko" &&
		window.navigator.productSub === "20030107"
){
	lResultTD.innerHTML = "Congratulations. You look like an iPad using Safari Browser to me.";
	lResultTD.className = "success-header";
}else{
	lResultTD.innerHTML = "Sorry. You do not look like an Apple iPad using Safari Browser.<br />This page uses JavaScript browser and O/S fingerprinting to decide if the user-agent is allowed.";
	lResultTD.className = "error-header";
}

I don't know how okay this code is, it might just be inadequate in modern browsers. But you can see that it is very easy to break the logic of all these numerous checks by adding “ || 1” which means “OR true”. That is, no matter what the result of all previous checks will be, this condition will always return “True”.

I used the method from the article “How to make changes in browser Developer Tools persist after page reload”. And the check for compliance with the condition I got like this:

if(
		window.navigator.platform === "iPad" && 
		window.navigator.appName === "Netscape" &&
		window.navigator.appCodeName === "Mozilla" &&
		window.navigator.appVersion.indexOf("iPad") !== -1 &&
		window.navigator.appVersion.indexOf("Mac") !== -1 &&
		window.navigator.appVersion.indexOf("AppleWebKit") !== -1 &&
		window.navigator.appVersion.indexOf("Safari") !== -1 &&
		window.navigator.product === "Gecko" &&
		window.navigator.productSub === "20030107" || 1
)

This approach pleased the mechanism for checking the User Agent and the task was passed.

But this method already refers to attacks on JavaScript, read related articles at the links:

Recommended for you:

Leave a Reply

Your email address will not be published. Required fields are marked *