August 2, 2026
Sqli-Header-Lab
While reading through various cybersecurity resources, I came across some interesting ideas that weren’t widely discussed in the community…

By Youssefelbakrey
1 min read
While reading through various cybersecurity resources, I came across some interesting ideas that weren't widely discussed in the community. These concepts, particularly around header-based SQL injection, seemed to be overlooked by most tutorials. So I decided to create something practical — interactive labs that demonstrate these less common attack vectors.
This is my first lab in the series, focusing on SQL injection through HTTP headers. I've uploaded it to Medium to share with the community and help others learn through hands-on practice
$host = getenv("DB_HOST") ?: "mysql";
$user = "labuser";
$pass = "labpass";
$dbname = "labdb";
$conn = new mysqli($host, $user, $pass, $dbname);$host = getenv("DB_HOST") ?: "mysql";
$user = "labuser";
$pass = "labpass";
$dbname = "labdb";
$conn = new mysqli($host, $user, $pass, $dbname);It connects to the database.
if ($conn->connect_error) {
die(...);
}if ($conn->connect_error) {
die(...);
}If the connection fails, the script stops.
2. Creating the Flag Table
$conn->query("
CREATE TABLE IF NOT EXISTS flag (
id INT PRIMARY KEY AUTO_INCREMENT,
flag_value VARCHAR(100)
)
");$conn->query("
CREATE TABLE IF NOT EXISTS flag (
id INT PRIMARY KEY AUTO_INCREMENT,
flag_value VARCHAR(100)
)
");If the table doesn't exist, it creates it.
After that:
SELECT COUNT(*)SELECT COUNT(*)It checks whether a flag already exists.
If not:
INSERT INTO flag ...INSERT INTO flag ...It inserts:
flag{Header_SQLi_Injection_Kali}flag{Header_SQLi_Injection_Kali}3. Receiving User Input
php
$user_input = $_POST['user_input'];$user_input = $_POST['user_input'];This is the form field present on the page.
4. The Secure Part
And this is the most important part.
$stmt = $conn->prepare(
"INSERT INTO logs(user_agent,request_time,is_vulnerable)
VALUES (?,NOW(),0)"
);$stmt = $conn->prepare(
"INSERT INTO logs(user_agent,request_time,is_vulnerable)
VALUES (?,NOW(),0)"
);Here prepare() is used.
After that:
$stmt->bind_param("s",$user_input);$stmt->bind_param("s",$user_input);Meaning no matter what the user typed — whether UNION or OR 1=1 — it will be treated purely as data. Not SQL.
Then:
$stmt->execute();$stmt->execute();This executes the query.
Why is this secure? Because the database separates the data from the query itself.
5. Reading the User-Agent
$user_agent = $_SERVER['HTTP_USER_AGENT'];$user_agent = $_SERVER['HTTP_USER_AGENT'];And this is the most important part of the lab.
Every browser sends a header called User-Agent, for example:
Mozilla/5.0Mozilla/5.0The idea of this lab is that the developer connected the User-Agent to the database. Here's why a developer might do that:
1. Treats headers as "trusted"
Many developers assume that values like:
- User-Agent
- Referer
- X-Forwarded-For
are values only the browser can set.
But the reality is that any HTTP client or tool like Burp Suite and curl can change them completely.
2. Quick logging
The goal is often just to save visitor information:
INSERT INTO logs(user_agent)INSERT INTO logs(user_agent)In case an attack or complaint happens and they want to pull up the data.
3. Bot detection
Some websites block certain tools, for example:
curl
python-requests
sqlmapcurl
python-requests
sqlmapSo they log the User-Agent to determine whether the request came from a real browser or from a tool.
6. The Vulnerable Part
php
$vuln_query =
"INSERT INTO logs
(user_agent,request_time,is_vulnerable)
VALUES
('$user_agent',NOW(),1)";$vuln_query =
"INSERT INTO logs
(user_agent,request_time,is_vulnerable)
VALUES
('$user_agent',NOW(),1)";Here's the problem.
Notice:
'$user_agent''$user_agent'The user-controlled value is placed directly inside the SQL.
If the user sends:
MozillaMozillaThen the query becomes:
INSERT INTO logs
VALUES
('Mozilla',NOW(),1)INSERT INTO logs
VALUES
('Mozilla',NOW(),1)Fine.
But if they send:
''Then it becomes:
VALUES
(''',NOW(),1)VALUES
(''',NOW(),1)The SQL breaks.
And if they send a suitable payload, it starts injecting SQL.
Repo: https://github.com/Youssefbakrey/sql-injection-header-lab