Man
Professional
- Messages
- 3,077
- Reaction score
- 614
- Points
- 113
I'll tell you how to make a QR code with a surprise.
Salute to all, dear friends!
A QR code is now a completely common thing - they are found everywhere, they are used as one of the authorization methods by large services like WhatsApp, Yandex and AliExpress, there are QR codes for connecting to Wi-Fi. But how reliable is this technology? Is it possible to create a QR code that, when scanned, will load the victim's device? We will examine this question in more detail today.
In 2014, the ZXing project's Barcode Scanner for mobile devices did little to no checking of the URI type transmitted via QR code. As a result, any exploit that could be executed by a browser (such as one written in JavaScript) could be transmitted via QR.
The scanner attempted to filter out dangerous types of attacks using regular expressions, requiring that the URI have a period followed by an extension of at least two characters, a transport protocol of at least two characters followed by a colon, and that the URI have no spaces.
If the content does not meet at least one of the requirements, it is detected as plain text, not a URI. This mechanism blocks attacks like javascript;alert("You have won 1000 dollars! Just Click The Open Browser Button");, but with a few simple changes to the code, we get the version that the program executed in the browser, because it considered the JS code to be an ordinary, "normal" URI!
A version of the code that was blocked by the scanner's security mechanism
As we can see, the notification appeared in the browser, which means that the URI with the potentially malicious code was executed. However, this JS code is executed only when the user clicks Open Browser (i.e. "Open in browser").
Another interesting example from 2012: Ravishankar Borgaonkar demonstrated how scanning a simple QR code can format Samsung devices! What was inside? An MMI code for a factory reset: *2767*3855#, as well as a prefix tel:for making a USSD request.
The most dangerous thing here is that a person without prior preparation cannot find out the contents of the code without scanning it. And a person is very curious: in various studies, most subjects (who, by the way, did not even know about the experiment) scanned the QR code out of curiosity, forgetting about their own safety. So always be careful!
Let's start with the QRGen utility, which allows you to create QR codes with scripts encoded in them.
You can view text files with all the variants of QR code “fillings” in the folder words(they are divided into the categories indicated above).
Now a few words about the consequences of attacks with such loads.
The first class of attacks, SQL injections, are used to hack databases and disrupt websites. For example, a request can cause a website to freeze.
The following example (number 2) demonstrates the exploitation of an XSS vulnerability when attacking web applications using SVG (Scalable Vector Graphic). I think you know perfectly well what XSS can lead to, so I won't go into detail about it.
The third item displays the contents of the file on the victim's screen /etc/passwd: a list of Linux-based system accounts and additional information about them (previously, password hashes for these accounts). In such cases, they usually try to get /etc/shadowthe server configuration as well, but everything depends very much on the goal, so it's up to you to decide which files to read.
The fourth example is an expression that will cause a buffer overflow. This occurs when the amount of data to be written or read is greater than the buffer can hold, and can cause the program to crash or hang, leading to a denial of service (DoS). Certain types of overflows allow an attacker to load and execute arbitrary machine code on behalf of the program and with the privileges of the account it is running under, making this a very dangerous bug.
The fifth class of attacks (XXE Injections) is a variant of obtaining hidden information from a web server by analyzing the output of XML files. Specifically, in our example, when requesting the server, it will respond with the Base64-encrypted contents of the file /etc/passwdthat was already mentioned. However, decrypting it is not difficult - it is enough to use the utility built into most Linux distributions base64or an online converter.
Format string attacks (Example 6) are a class of vulnerabilities that involve providing "language-specific format markers" to execute arbitrary code or crash the program. In human terms, this is a class of attacks where an application improperly sanitizes user input from control constructs, causing those constructs to be executed as a result.
The seventh point is a variant of command injection, which executes specific code on the server side. In my example, the command will be executed ls, which will show the contents of the current directory, but of course, there may be much more dangerous code there.
And finally, the last category is LFI (Local File Inclusion) vulnerabilities, which allow viewing files and folders on vulnerable (or misconfigured) servers that should not be visible to everyone. One possible option is to view the file /etc/passwdthat we have already talked about many times. It might look like this.
Each of them contains malicious code, so although I will give an example, part of it will be cut out:
As we can see from the screenshot above, our text was transferred to the QR code absolutely correctly!
This utility (and attack vector) is aimed rather at checking unprotected and unpopular software or highly specialized tools (like warehouse QR scanners that send SQL queries to a company database). Most modern scanners do not execute the QR code for security reasons. Accordingly, there are two possible scenarios after scanning.
SQRL (pronounced squirrel, and standing for Secure, Quick, Reliable Login or Secure Quick Response Login) is an open source project for secure website login and authentication. Login, of course, uses a QR code to verify authenticity.
How is login performed using this authentication method?
For quite a long time, the SQRL method was considered really safe until Mohamed Basset proposed a method of attacking services using SQRL, which was called QRLJacking. The method requires creating a phishing page and placing a QR code on it, generated at certain intervals. Let's take a closer look at it.
It was for the implementation of this method that the QRLJacker utility was created, which we will now discuss.
Which web resources are vulnerable to this attack vector? According to the developers, these are popular messengers such as WhatsApp, WeChat, Discord, Line, all Yandex services (after all, to log into any of them, you need to log into Yandex.Passport, which provides the ability to authenticate via QR), popular trading platforms Alibaba, AliExpress, Tmall and Taobao, the AliPay service, as well as the AirDroid remote access application. Of course, the list is incomplete, because all the resources that use SQRL are simply too numerous to list.
Now let's install the QRLJacker utility (the program only works on Linux and macOS, you can find more detailed information in the project's README, and we also need Python 3.7+).
When running normally (without any arguments at all), you will see something like this:
By writing the command helpinside the framework, you will get full help on QRLJacker commands.
Now let's launch the only (at the moment) module — grabber/whatsapp. We can view the list of all available modules with the command list, and select a module to use with the command use. The command optionswill tell us the current option values, and setwill set a particular option value. The command runwill launch our module, and jobswe can view active tasks with the command.
Port 1337 is standard for this framework, I didn't touch the other options. HOSTI left it local (0.0.0.0), but bringing it online is not a problem. This can be done using, for example, ngrok:
I also decided to leave the parameter User-Agentas default, but there are only three options: standard, random and custom (manual setting). Use the option that suits you best.
After that, I launch the module and look at the current tasks. Their ID, module name, and the address where the module page is located are indicated there. According to the standard, it looks like this (the QR code is partially blurred to protect against abuse by ~~people in uniform~~):
You can change this page by editing the file to your liking QRLJacker/core/templates/phishing_page.html.
The original source is simple and straightforward, which allows even an unprepared hacker to quickly change the text.
Once you make changes to the file, they will be automatically applied in the framework.
You can find documentation and instructions for creating modules in the project repository or in the folder you cloned earlier ( QRLJacker/docs/README.md). Grabber modules are the basis of the framework, and they are located in QRLJacker/core/modules/grabber. When you add any Python file there, it appears in the framework with three options - host, port and user agent.
For example, the module grabber/whatsappis made in this format, you can also view it in the repository or by opening the Python file itself, which is located in QRJacker/core/modules/grabber/whatsapp.py.
Now let's figure out what each of the variables we set on these lines means.
Class info
Here is your name (or nickname), which will appear when calling the module help, a short description of the module and its full description (you can fill it in, or leave the value None). There is nothing else interesting in the class info, but before we move on to the next ( execution), let's look at calling the help (which will draw information from the code) using the WhatsApp module as an example. Here is the code info:
Module: grabber/whatsapp
Provided by: Karim Shoair (D4Vinci)
Description: Whatsapp QR-sessions grabber and controller
Execution class
This is a bit more fiddly: you need not only the module name, but also the URL of the site where the QR code will be taken from and where authorization will be performed. You also need the XPATH of the image with the QR code on the page. To understand what this is, let's look at the WhatsApp module example again. There, this parameter looks like /html/body/div[1]/div/div/div[2]/div[1]/div/div[2], that is, the path to the object inside the HTML document.
Next, you need the XPATH of the button that updates the QR code on the page (if there is one, otherwise leave the None value). For greater secrecy, use the XPATH of the element that disappears after receiving the session. For example, the QRLJacker developers grabber/whatsappused the "Remember me" checkbox in the module.
Finally, you need a variable that takes the values localStorageor Cookies. It should match the way the website defines a user session.
That's it - after you've sorted out all these points, all you have to do is add the file to the grabber modules folder and create an HTML file ( index.html) with a page in core/www/твое_имя_модуля.
Done! You have created your module.
This is a plugin that, if you go to the popular foreign site Amazon, will give a thematic notification about “receiving a gift from WhatsApp in honor of Valentine's Day” (pay attention to the upper right corner). Naturally, to receive the gift, you need to scan the QR code, which will not give you anything except a leak of personal data. Be very vigilant, because, as I showed earlier, this attack vector and utilities for its use are in the public domain, and writing a module for QRLJacker is a task that even a beginner Pythonist can handle.
Salute to all, dear friends!
A QR code is now a completely common thing - they are found everywhere, they are used as one of the authorization methods by large services like WhatsApp, Yandex and AliExpress, there are QR codes for connecting to Wi-Fi. But how reliable is this technology? Is it possible to create a QR code that, when scanned, will load the victim's device? We will examine this question in more detail today.
A QR code (Quick Response Code) is a matrix or two-dimensional barcode that can contain up to 4296 ASCII characters. In other words, it is a picture with encrypted text.
Attack Vector History
In May 2013, Lookout Mobile developed special QR codes that were able to hack Google Glass. At that time, the glasses scanned all photos “that could be useful to their owner,” and provided hackers with full remote access to the device. The researchers reported this vulnerability to Google, and it was closed in just a few weeks.In 2014, the ZXing project's Barcode Scanner for mobile devices did little to no checking of the URI type transmitted via QR code. As a result, any exploit that could be executed by a browser (such as one written in JavaScript) could be transmitted via QR.
The scanner attempted to filter out dangerous types of attacks using regular expressions, requiring that the URI have a period followed by an extension of at least two characters, a transport protocol of at least two characters followed by a colon, and that the URI have no spaces.
If the content does not meet at least one of the requirements, it is detected as plain text, not a URI. This mechanism blocks attacks like javascript;alert("You have won 1000 dollars! Just Click The Open Browser Button");, but with a few simple changes to the code, we get the version that the program executed in the browser, because it considered the JS code to be an ordinary, "normal" URI!
- This is what it looked like:

A version of the code that was blocked by the scanner's security mechanism
As we can see, the notification appeared in the browser, which means that the URI with the potentially malicious code was executed. However, this JS code is executed only when the user clicks Open Browser (i.e. "Open in browser").
Another interesting example from 2012: Ravishankar Borgaonkar demonstrated how scanning a simple QR code can format Samsung devices! What was inside? An MMI code for a factory reset: *2767*3855#, as well as a prefix tel:for making a USSD request.
The most dangerous thing here is that a person without prior preparation cannot find out the contents of the code without scanning it. And a person is very curious: in various studies, most subjects (who, by the way, did not even know about the experiment) scanned the QR code out of curiosity, forgetting about their own safety. So always be careful!
QRGen - a code for everyone
To demonstrate the tools for working with QR codes, I will use Kali Linux with Python version 3.7 installed - this is necessary for the utilities to work correctly.Let's start with the QRGen utility, which allows you to create QR codes with scripts encoded in them.
- Copy the repository and go to the folder with the contents:
Code:
git clone https://github.com/h0nus/QRGen
cd QRGen && ls
QRGen requires Python version 3.6 or higher. If you get an error, try updating the interpreter.
- We install all dependencies and run the script itself:
Code:
pip3 install -r requirements.txt
## or python3 -m pip install -r requirements.txt
python3qrgen.py
- We see the certificate:

- The argument -hwill output the same thing, but running with a key -lwill generate QR codes from a specific category. There are eight of them:
- SQL injections.
- XSS.
- Command injections.
- QR with formatted string.
- XXE.
- String fuzzing.
- SSI injections.
- LFI or gaining access to hidden directories.
Possible attacks
Now let's look at examples from each category and see what damage they can cause to what devices.
Code:
1. 0'XOR(if(now()=sysdate(),sleep(6),0))XOR'Z
2. <svg onload=alert(1)>
3. cat /etc/passwd
4. %d%d%d%d%d%d%d%d%d%d
5. <!ENTITY % xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd" >
6. "A" x 33
7. <pre><!--#exec cmd="ls" --></pre>
8. ../../../../../../etc/passwd
You can view text files with all the variants of QR code “fillings” in the folder words(they are divided into the categories indicated above).
Now a few words about the consequences of attacks with such loads.
The first class of attacks, SQL injections, are used to hack databases and disrupt websites. For example, a request can cause a website to freeze.
The following example (number 2) demonstrates the exploitation of an XSS vulnerability when attacking web applications using SVG (Scalable Vector Graphic). I think you know perfectly well what XSS can lead to, so I won't go into detail about it.
The third item displays the contents of the file on the victim's screen /etc/passwd: a list of Linux-based system accounts and additional information about them (previously, password hashes for these accounts). In such cases, they usually try to get /etc/shadowthe server configuration as well, but everything depends very much on the goal, so it's up to you to decide which files to read.
The fourth example is an expression that will cause a buffer overflow. This occurs when the amount of data to be written or read is greater than the buffer can hold, and can cause the program to crash or hang, leading to a denial of service (DoS). Certain types of overflows allow an attacker to load and execute arbitrary machine code on behalf of the program and with the privileges of the account it is running under, making this a very dangerous bug.
The fifth class of attacks (XXE Injections) is a variant of obtaining hidden information from a web server by analyzing the output of XML files. Specifically, in our example, when requesting the server, it will respond with the Base64-encrypted contents of the file /etc/passwdthat was already mentioned. However, decrypting it is not difficult - it is enough to use the utility built into most Linux distributions base64or an online converter.
Format string attacks (Example 6) are a class of vulnerabilities that involve providing "language-specific format markers" to execute arbitrary code or crash the program. In human terms, this is a class of attacks where an application improperly sanitizes user input from control constructs, causing those constructs to be executed as a result.
If you programmed in C, then, of course, you remember those interesting things with the output of variables via printf: it was necessary to indicate the type of the output value in the first argument (which is a string) ( %dfor a decimal number, and so on).
The seventh point is a variant of command injection, which executes specific code on the server side. In my example, the command will be executed ls, which will show the contents of the current directory, but of course, there may be much more dangerous code there.
And finally, the last category is LFI (Local File Inclusion) vulnerabilities, which allow viewing files and folders on vulnerable (or misconfigured) servers that should not be visible to everyone. One possible option is to view the file /etc/passwdthat we have already talked about many times. It might look like this.

Practice
Now let's move on to practice - let's test this utility ourselves.- For example, let's run it with the key -l 5:
Code:
python3 qrgen.py -l 5
- The utility generated 46 QR codes with payloads. All of them are in the foldergenqr:

Each of them contains malicious code, so although I will give an example, part of it will be cut out:

- Now we can run the script with the flag -w(remember, it makes the script use a custom dictionary), but first we need a file with our useful (and not so useful) payloads. We can use ready-made payloads from Metasploit (in Kali they are located at /usr/share/metasploit-framework/modules/payloads) or create a new text document and write something “bad” in it, for example, a command to delete all files on a Linux-based system:
Code:
rm -rf /*
- So, I named our "virus" clear.txtand run QRGen (after deleting or clearing the folder genqr):
Code:
python3 qrgen.py -w /path/to/clear.txt
- Sometimes an error may occur, as in the screenshot below. Don't be alarmed, it doesn't affect the code generator's functionality.

If you are a perfectionist and want to fix it, then replace it format(i-1)with format(i)at the very end of the script.
- Now let's look at the QR code itself (with the part cut out, of course) and scan it on one of the online services:

As we can see from the screenshot above, our text was transferred to the QR code absolutely correctly!
This utility (and attack vector) is aimed rather at checking unprotected and unpopular software or highly specialized tools (like warehouse QR scanners that send SQL queries to a company database). Most modern scanners do not execute the QR code for security reasons. Accordingly, there are two possible scenarios after scanning.
- The scanner simply displays the contents of our image (an unfavorable option for a hacker).
- The scanner executes the code inside the image, or, using the example we discussed earlier, sends a SQL query to the organization's database. This becomes the first step to hacking the company's database. Naturally, it is foolish in this scenario to expect that the recognized text will be executed as a standalone query, so take a load like the one you usually use in web applications.
QRLJacker
Now we move on to the second tool - QRLJacker. It is somewhat similar to QRGen, but represents a completely different attack vector - QRLJacking.SQRL (pronounced squirrel, and standing for Secure, Quick, Reliable Login or Secure Quick Response Login) is an open source project for secure website login and authentication. Login, of course, uses a QR code to verify authenticity.
How is login performed using this authentication method?

- The user visits the site and opens a session.
- The site generates a QR code with a session key. This code changes regularly for security purposes.
- The user scans the QR code.
- The mobile application generates an authentication signal that contains a secret token (it includes the user ID, session code, and a special message created using the user's private key).
- The site receives a signal and identifies the user, logging in (if, of course, verification is completed correctly).
For quite a long time, the SQRL method was considered really safe until Mohamed Basset proposed a method of attacking services using SQRL, which was called QRLJacking. The method requires creating a phishing page and placing a QR code on it, generated at certain intervals. Let's take a closer look at it.
- The attacker initiates a client QR session and clones the QR login code onto a phishing page.
- The victim is sent a link to this page. The page looks quite safe.
- The victim scans the fake QR code and the app sends a secret token, completing the authentication process.
- The attacker receives confirmation from the service and can now control the victim's account.
It was for the implementation of this method that the QRLJacker utility was created, which we will now discuss.
Which web resources are vulnerable to this attack vector? According to the developers, these are popular messengers such as WhatsApp, WeChat, Discord, Line, all Yandex services (after all, to log into any of them, you need to log into Yandex.Passport, which provides the ability to authenticate via QR), popular trading platforms Alibaba, AliExpress, Tmall and Taobao, the AliPay service, as well as the AirDroid remote access application. Of course, the list is incomplete, because all the resources that use SQRL are simply too numerous to list.
Now let's install the QRLJacker utility (the program only works on Linux and macOS, you can find more detailed information in the project's README, and we also need Python 3.7+).
- Log in to the system as a superuser (root), otherwise Firefox may throw an error when launching QRLJacker framework modules.
- Update Firefox to the latest version.
- Download the latest geckodriverfrom GitHub and unzip the file, then run the commands
Code:
chmod +x geckodriver
sudo mv -f geckodriver /usr/local/share/geckodriver
sudo ln -s /usr/local/share/geckodriver /usr/local/bin/geckodriver
sudo ln -s /usr/local/share/geckodriver /usr/bin/geckodriver
- We clone the repository and go to the folder with the contents:
Code:
git clone https://github.com/OWASP/QRLJacking
cd QRLJacking/QRLJacker && ls
- Install all dependencies:
Code:
python3.7 -m pip install -r requirements.txt
- Let's launch the framework (with a key --helpto get a quick reference):
Code:
python3.7 QrlJacker.py --help

When running normally (without any arguments at all), you will see something like this:

By writing the command helpinside the framework, you will get full help on QRLJacker commands.
Now let's launch the only (at the moment) module — grabber/whatsapp. We can view the list of all available modules with the command list, and select a module to use with the command use. The command optionswill tell us the current option values, and setwill set a particular option value. The command runwill launch our module, and jobswe can view active tasks with the command.

Port 1337 is standard for this framework, I didn't touch the other options. HOSTI left it local (0.0.0.0), but bringing it online is not a problem. This can be done using, for example, ngrok:
Code:
ngrok http 1337
I also decided to leave the parameter User-Agentas default, but there are only three options: standard, random and custom (manual setting). Use the option that suits you best.
After that, I launch the module and look at the current tasks. Their ID, module name, and the address where the module page is located are indicated there. According to the standard, it looks like this (the QR code is partially blurred to protect against abuse by ~~people in uniform~~):

You can change this page by editing the file to your liking QRLJacker/core/templates/phishing_page.html.
The original source is simple and straightforward, which allows even an unprepared hacker to quickly change the text.

Once you make changes to the file, they will be automatically applied in the framework.
Writing your own modules
Let's discuss what is needed to create your own module for QRLJacker.You can find documentation and instructions for creating modules in the project repository or in the folder you cloned earlier ( QRLJacker/docs/README.md). Grabber modules are the basis of the framework, and they are located in QRLJacker/core/modules/grabber. When you add any Python file there, it appears in the framework with three options - host, port and user agent.
- The module code should be built according to the following template:
Code:
## -*- coding: utf-8 -*-
from
core.module_utils import types
class info:
author = ""
short_description = ""
full_description = None
class execution:
module_type=types.grabber
name = ""
url = ""
image_xpath = ""
img_reload_button = None
change_identifier = ""
session_type = "localStorage"
For example, the module grabber/whatsappis made in this format, you can also view it in the repository or by opening the Python file itself, which is located in QRJacker/core/modules/grabber/whatsapp.py.
Now let's figure out what each of the variables we set on these lines means.
Class info
Here is your name (or nickname), which will appear when calling the module help, a short description of the module and its full description (you can fill it in, or leave the value None). There is nothing else interesting in the class info, but before we move on to the next ( execution), let's look at calling the help (which will draw information from the code) using the WhatsApp module as an example. Here is the code info:
Code:
class info:
author = "Karim Shoair (D4Vinci)"
short_description = "Whatsapp QR-sessions grabber and controller"
full_description = None
- And here is the help for the module:
Code:
$ info grabber/whatsapp
Module: grabber/whatsapp
Provided by: Karim Shoair (D4Vinci)
Description: Whatsapp QR-sessions grabber and controller
Execution class
This is a bit more fiddly: you need not only the module name, but also the URL of the site where the QR code will be taken from and where authorization will be performed. You also need the XPATH of the image with the QR code on the page. To understand what this is, let's look at the WhatsApp module example again. There, this parameter looks like /html/body/div[1]/div/div/div[2]/div[1]/div/div[2], that is, the path to the object inside the HTML document.
Next, you need the XPATH of the button that updates the QR code on the page (if there is one, otherwise leave the None value). For greater secrecy, use the XPATH of the element that disappears after receiving the session. For example, the QRLJacker developers grabber/whatsappused the "Remember me" checkbox in the module.
Finally, you need a variable that takes the values localStorageor Cookies. It should match the way the website defines a user session.
That's it - after you've sorted out all these points, all you have to do is add the file to the grabber modules folder and create an HTML file ( index.html) with a page in core/www/твое_имя_модуля.
Done! You have created your module.
Hijacking a session
Now let's take a quick look at how this framework can be used to perform a QRLJacking attack. For example, an attacker can copy the original site web.whatsapp.comand insert a fake QR code there to gain access to the session. Or an example given by the creator of the QRLJacker utility.
This is a plugin that, if you go to the popular foreign site Amazon, will give a thematic notification about “receiving a gift from WhatsApp in honor of Valentine's Day” (pay attention to the upper right corner). Naturally, to receive the gift, you need to scan the QR code, which will not give you anything except a leak of personal data. Be very vigilant, because, as I showed earlier, this attack vector and utilities for its use are in the public domain, and writing a module for QRLJacker is a task that even a beginner Pythonist can handle.