Skip to content
BeoHosting
BeoHosting
Security

How to Recognize and Prevent SQL Injection

BeoHosting Team··11 min read read
How to Recognize and Prevent SQL Injection

What is SQL injection

SQL injection (SQLi) is one of the oldest and most dangerous types of attacks on web applications. The attack works by an attacker injecting malicious SQL code into input fields (forms, URL parameters, cookies) that the application uses to build SQL queries to the database. If the application doesn't validate and sanitize user input before embedding it in a SQL query, the attacker can manipulate the query to read, modify, or delete data from the database.

According to the OWASP Top 10 list, injection attacks have been among the three most critical web vulnerabilities for years. A successful SQL injection attack can result in theft of the entire database (user accounts, passwords, personal data), modification or deletion of data, authentication bypass (login without password), execution of commands on the server operating system, and complete server compromise.

How SQL injection works

Basic principle

Imagine a login form that checks a username and password. The application builds a SQL query that looks roughly like this: SELECT * FROM users WHERE username = 'entered_name' AND password = 'entered_password'. If the application simply inserts the user's input into the query without any check, the attacker can enter a special value into the username field that changes the query logic. For example, an input containing an apostrophe followed by SQL code can close the string literal and add a condition that's always true, bypassing the password check.

Types of SQL injection attacks

There are several types of SQL injection attacks. In-band SQLi is the most common where the attacker uses the same communication channel for sending the attack and receiving results. It splits into Error-based SQLi (uses database error messages to extract information) and Union-based SQLi (uses the UNION operator to combine results of a malicious query with a legitimate one). Blind SQLi is a type where the attacker doesn't see direct results but can infer information based on application behavior. Boolean-based blind SQLi sends queries that return true or false and infers data character by character based on response differences. Time-based blind SQLi uses SQL pause functions (SLEEP, WAITFOR DELAY) to determine whether a condition is true based on response time. Out-of-band SQLi uses a different channel for data exfiltration, like DNS or HTTP requests the database sends to the attacker's server.

Spotting SQL injection vulnerabilities

Manual testing

The simplest way to test for SQL injection vulnerabilities is by injecting special characters into input fields. An apostrophe (') is the first test - if the application returns a database error, there's a potential vulnerability. A double apostrophe ('') shouldn't cause an error if a single one did. SQL comments (-- or #) can be used to comment out the rest of the query. Logical operators (OR 1=1, AND 1=2) can reveal boolean-based vulnerabilities. The SLEEP command ('; WAITFOR DELAY '0:0:5'--) reveals time-based vulnerabilities if the page delays its response.

Automated tools

For systematic testing, use specialized tools. SQLMap is the best-known open-source tool for automatic detection and exploitation of SQL injection vulnerabilities - it supports all SQLi types and most databases. Burp Suite Professional has a built-in scanner for SQL injection and other web vulnerabilities. OWASP ZAP is a free alternative to Burp Suite with a solid SQLi scanner. Acunetix and Netsparker are commercial web vulnerability scanners with advanced SQLi detection.

Signs of compromise

If you suspect your site has already been a SQL injection target, check the following: unusual entries in web server logs (URLs with SQL keywords), new or modified user accounts in the database (especially admin accounts), modified data without your knowledge, new files on the server (web shells), and increased traffic to specific pages with unusual parameters. Also review database log files for unexpected queries.

Prevention - Prepared Statements

What prepared statements are

Prepared statements (parameterized queries) are the most effective protection against SQL injection. Instead of inserting user input directly into a SQL query as text, a prepared statement separates query structure from data. First the query structure is defined with placeholders for data, and then the data is sent separately. The database treats data only as values, never as SQL code, making injection impossible.

Implementation in different languages

PHP with PDO (PHP Data Objects) uses the prepare() method to prepare a query with placeholders (:username, :password) and execute() with an array of values. The MySQLi extension supports prepared statements with ? placeholders and bind_param() for binding values with data types. Python with sqlite3 or psycopg2 uses ? or %s placeholders. Java uses the PreparedStatement class with setString(), setInt() methods. Node.js libraries like mysql2 and pg support parameterized queries with ? or $1 placeholders. Regardless of programming language, the principle is the same - never concatenate user input with a SQL query as strings.

Additional prevention methods

Input validation

Beyond prepared statements, always validate user input. Whitelist validation allows only expected values - if a field should contain a number, verify it really is a number before processing. For text fields, restrict allowed characters, input length, and format (regex). Never rely on client-side validation (JavaScript) alone because an attacker can bypass it - validation must be implemented on the server.

Stored Procedures

Stored procedures are SQL code stored and executed on the database server. When properly written (without dynamic SQL inside the procedure), they provide an additional layer of protection because the application calls the procedure with parameters instead of sending raw SQL queries. However, stored procedures by themselves aren't a guarantee of security - if procedures internally construct dynamic queries from parameters, the vulnerability still exists.

ORM (Object-Relational Mapping)

ORM libraries like Eloquent (Laravel), SQLAlchemy (Python), Hibernate (Java), and TypeORM (Node.js) automatically use prepared statements for all queries, eliminating most SQL injection risk. However, most ORMs allow raw SQL queries for complex operations - in those cases you must manually use prepared statements. An ORM doesn't replace knowledge of SQL security but significantly reduces the attack surface.

Principle of least privilege

Configure the database so the application uses an account with the minimum required privileges. A web application typically needs SELECT, INSERT, UPDATE, and DELETE privileges on specific tables. Don't grant DROP, ALTER, CREATE, or FILE privileges to the application account. If an attacker succeeds in SQL injection, restricted privileges prevent dropping tables, modifying database structure, and accessing the server file system.

WAF protection from SQL injection

How a WAF detects SQLi

A Web Application Firewall (WAF) analyzes HTTP requests and blocks ones containing SQL injection patterns. The WAF recognizes SQL keywords in unexpected places (SELECT, UNION, DROP in URL parameters), special characters used in SQLi attacks (apostrophes, comments, logical operators), known SQLi payloads from a signature database, and anomalies in request structure that indicate an injection attempt.

WAF limitations

A WAF is not a substitute for secure code. Experienced attackers can bypass a WAF using encoding techniques (URL encoding, Unicode, double encoding), comments and spaces to break signatures, alternative SQL syntaxes the WAF doesn't recognize, and incremental testing to determine which rules the WAF uses. The WAF is an additional layer of protection (defense in depth), but the primary protection must be in the application code through prepared statements and input validation.

SQL injection in WordPress

WordPress protective mechanisms

WordPress core uses the $wpdb->prepare() method for all queries to the database, which is WordPress's implementation of prepared statements. This method uses sprintf-style placeholders (%s for strings, %d for integers, %f for floats) and automatically escapes values. However, vulnerabilities most often appear in plugins and themes that don't use $wpdb->prepare() or construct queries by manually concatenating strings.

Protecting a WordPress site

To protect a WordPress site from SQL injection, regularly update WordPress core, plugins, and themes because security patches often address SQLi vulnerabilities. Use only plugins and themes from trusted sources (WordPress.org repository, well-known commercial providers). Install a security plugin (Wordfence, Sucuri, iThemes Security) that includes WAF protection. Also see our guide for protecting a site from hackers. Remove unused plugins and themes because even deactivated plugins can be exploited. Restrict database access - WordPress only needs one user with access to its database.

Common mistakes that leave a site vulnerable

  • Dynamic SQL in code: Concatenating user input with a SQL query as a string is the main cause of SQL injection vulnerabilities. Always use prepared statements.
  • Trusting client-side validation: JavaScript validation can be bypassed - all validation must exist on the server.
  • Detailed error messages: Displaying SQL errors to users reveals database structure and makes attack easier. In production, log errors internally and display a generic message to users.
  • Outdated software: Old versions of CMS, frameworks, and libraries often have known SQLi vulnerabilities with publicly available exploits.
  • One database user for everything: Using a root account for the application gives the attacker full control of the database in case of a successful attack.

Conclusion

SQL injection is a serious threat that can completely compromise your site and user data. Prevention is relatively simple - use prepared statements for all database interactions, validate user input on the server, apply the principle of least privilege, and keep software up to date. A WAF provides an additional layer of protection but doesn't replace secure code. With BeoHosting hosting, all servers come with a configured ModSecurity WAF that detects and blocks SQL injection attempts, but we recommend that your code also follow best secure coding practices.

BeoHosting Team

10+ years of experience — Web hosting and infrastructure specialists

  • Web Hosting
  • WordPress Hosting
  • VPS
  • Dedicated Serveri
  • Domeni
  • SSL
  • cPanel
  • LiteSpeed
  • Linux administracija
  • DNS

Last updated: