SQL Injection - MySQL
Reference
Plugin Id: 40019 | CWE: 89
Resources
Remediation
- Use built-in Object Data Models (ODMs) to gather data: Instead of directly concatenating user input into SQL queries, use ODMs provided by the language framework to interact with the database. ODMs automatically handle data sanitization and prevent SQL injection vulnerabilities. For example, in Node.js with the Mongoose ODM, you can define a schema and use it to query the database:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: String,
password: String,
});
const User = mongoose.model('User', userSchema);
// Example of querying the database using the User model
User.find({ username: 'admin' }).exec((err, users) => {
if (err) {
console.error(err);
return;
}
console.log(users);
});
- Use parameterized queries: Instead of directly embedding user input into SQL statements, use parameterized queries provided by the language framework. Parameterized queries separate the SQL code from the user input, preventing SQL injection attacks. For example, in Java with JDBC, you can use prepared statements:
import java.sql.*;
String username = "admin";
String password = "password";
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, username);
statement.setString(2, password);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
// Process the result
}
resultSet.close();
statement.close();
- Avoid string concatenation on SQL statements: Instead of manually concatenating strings to build SQL statements, use query builders or ORM libraries that handle SQL generation and parameterization. These libraries ensure proper sanitization and prevent SQL injection vulnerabilities. For example, in Python with SQLAlchemy, you can use the ORM to query the database:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)
engine = create_engine('mysql://user:password@localhost/mydatabase')
Session = sessionmaker(bind=engine)
session = Session()
# Example of querying the database using the User model
users = session.query(User).filter(User.username == 'admin').all()
for user in users:
print(user.username)
session.close()
About
SQL injection vulnerabilities occur when user input is not properly sanitized or directly passed to the back-end SQL server. Attackers can exploit these vulnerabilities to inject malicious SQL commands into the application.
Risks
The risks of SQL injection include:
- Enumerating column names: Attackers can use SQL injection to gather information about the database structure, such as column names, which can aid in further attacks.
- Retrieving data from the database: Attackers can extract sensitive data from the database by manipulating SQL queries.
- Remote code execution: In some cases, SQL injection can lead to the execution of arbitrary code on the server, allowing attackers to take control of the application or underlying system.
Most StackHawk tests for SQL injection are time-based, where the scanner attempts to make the SQL server perform time-based actions and increase the response time of the application.