Cyber Security SQL Injection — Demo Attack and Mitigation Methods for Developers Written by Adam Muiz 23 Jul 2026 Updated: 06 Aug 2026 3 min read Ever heard the story about a large website being hacked because there was a line of code that they "forgot" to check? In the world of cybersecurity, there is one type of attack that is more than two decades old but still makes the OWASP Top 10 list for 2025 — SQL Injection. Not because the technology is advanced, but because developers often forget the basics. This article will discuss SQL Injection from a developer's perspective: what it is, how it occurs, and most importantly — how to prevent it.SQL Injection: The Open Side DoorImagine you have a house with the front door locked tight — firewall on, HTTPS installed, authentication running. But it turned out there was a window at the back that was unlocked. That's roughly the SQL Injection analogy. This attack does not penetrate firewalls or bypass encryption. It comes in through the input you receive from the user — input that you should validate but don't.SQL Injection works by inserting malicious SQL code into input that should only be plain text. If your application directly enters user input into a database query without sanitation, an attacker can "hijack" the query. The result? This could be in the form of data theft, data deletion, even complete control over your server database.How SQL Injection Attacks HappenLet's look at a simple example. For example, you have a simple login form:<?php $username = $_POST['username']; $password = $_POST['password']; $query = "SELECT * FROM users WHERE username='$username' AND password='$password'"; $result = mysqli_query($conn, $query); ?> The code above looks "normal" to many novice developers. But notice that the variables $username and $password are inserted directly into the query without any sanitization at all. This is a recipe for disaster.Now imagine that the attacker enters admin' -- in the username field. The resulting query becomes:SELECT * FROM users WHERE username='admin' --' AND password='' The -- flag in SQL is a comment. So the password part is checked, and the query only checks whether the username admin exists. Without actual authentication, the attacker logs into the admin account. This is called authentication bypass — one of the most classic forms of SQL InjectionTypes of SQL InjectionSQL Injection is not always as simple as the example above. Here are some variations that you need to recognize:In-band SQL Injection is the most common type, where the attacker sees the query results directly in the application response. Examples include error messages that reveal the database structure, or pages that change behavior based on malicious input. These include UNION-based (combining the results of a malicious query with the original query) and Error-based (using error messages to extract information).Blind SQL Injection occurs when the application does not display errors or query results directly. The attacker must "peek" at the answer to the boolean question asked. For example, by sending ' OR 1=1 -- and observing the response difference between true and false. The process is slower but just as dangerous.Out-of-band SQL Injection uses database features such as LOAD_FILE() or UTL_HTTP.REQUEST to send data out of the database to the attacker's server. This type is rarer because it requires specific database features, but is difficult to detect.Practical Demo: SQL Injection in PHPLet's try a simple demo. Create a PHP file with an injection vulnerable query:<?php $conn = new mysqli('localhost', 'root', 'password', 'testdb'); if (isset($_GET['id'])) { // VULNERABLE — jangan tiru ini! $id = $_GET['id']; $query = "SELECT name, email FROM users WHERE id = $id"; $result = $conn->query($query); while ($row = $result->fetch_assoc()) { echo "Name: " . $row['name'] . "<br>"; echo "Email: " . $row['email'] . "<br>"; } } ?> If the normal URL is example.com/user.php?id=1, the attacker can try:# Menampilkan semua data example.com/user.php?id=1 UNION SELECT username, password FROM users-- # Menyuntikkan data palsu (INSERT) example.com/user.php?id=1; INSERT INTO users(name,email) VALUES('hacker','[email protected]')-- # Menghapus tabel example.com/user.php?id=1; DROP TABLE users-- Just imagine this happening on a website that stores credit card data, medical history, or national identity. The impact can be huge.How to Prevent SQL InjectionThe good news is, SQL Injection is an attack that is very easy to prevent as long as you know how. The following methods have been proven effective:1. Prepared Statements (Parameterized Queries)This is the most effective and most recommended method. Prepared statements separate the SQL query from the data, so that user input is never interpreted as SQL code.<?php // SAFE — gunakan prepared statements $stmt = $conn->prepare("SELECT name, email FROM users WHERE id = ?"); $stmt->bind_param("i", $_GET['id']); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { echo "Name: " . $row['name'] . "<br>"; echo "Email: " . $row['email'] . "<br>"; } ?> Notice the question mark ? in the query — it's a placeholder that will be filled in by bind_param(). The database will simply treat the value as data, not as part of the query structure. SQL Injection attacks are useless.2. Input ValidationIn addition to prepared statements, you also have to validate user input. If the field must be a number, make sure it is a number. If you must email, validate the email format. Never trust input as it is.<?php // Validasi: pastikan ID hanya angka $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT); if ($id === false) { die("Invalid ID"); } // Sekarang aman untuk dimasukkan ke query $stmt = $conn->prepare("SELECT name, email FROM users WHERE id = ?"); $stmt->bind_param("i", $id); ?> 3. Stored ProceduresStored procedures are blocks of SQL that are stored in the database and executed from the application. With stored procedures, complex queries do not need to be written directly in the application code, and you can limit the data required by database users.4. Whitelist ApproachIf the input can only be a certain number of values (for example roles: admin, editor, viewer), use a whitelist. Compare the input with a list of allowed values, not with a list of prohibited values.<?php $allowed_roles = ['admin', 'editor', 'viewer']; $role = $_POST['role']; if (!in_array($role, $allowed_roles)) { die("Role tidak valid"); } ?> 5. Least Privilege PrincipleUse a database user with as few access rights as possible. If the application only needs to read data, do not use a user with DROP or GRANT privileges. Even if there is injection, the impact can be limited.SQL Injection Detection ToolsApart from preventing it from the code side, you can also use tools to detect SQL Injection vulnerabilities in your application:sqlmap is an automatic tool that can detect and exploit SQL Injection. Very useful for testing your own application. Run a scan of local applications before deploying to production.Burp Suite (free Community Edition) can be used to intercept and modify HTTP requests, so you can test input manually.Nikto is a web server scanner that can detect several types of vulnerabilities including SQL Injection at the configuration level.Remember: use this tool only for testing your own application. Using this tool on other people's applications without permission is illegal.ConclusionSQL Injection may sound like an outdated "classic" topic, but the reality is that this attack is still very relevant in 2025. There are many cases of data leaks caused by something as simple as "forgetting to use prepared statements."As a developer, you have a responsibility to protect user data. From now on, make sure that every query you write uses prepared statements, every input you receive has been validated, and every database user has been given the minimum possible access rights.Have you ever encountered a SQL Injection vulnerability in your project? Or maybe you have additional tips about prevention? Tell us in the comments column — who knows, your experience might help other developers.