Back to list
SQL インジェクション解説:ハッカーがログインフォームを迂回する方法(および防ぎ方)
SQL Injection Explained: How Hackers Bypass Login Forms (and How to Stop Them)
Translated: 2026/4/25 4:00:39
Japanese Translation
时至今日,一条编写不当的 SQL 查询就足以让攻击者绕过身份验证或暴露敏感数据。
而最令人惊恐的是?问题往往只出在短短一行代码上。
在之前的文章中,我们见证了微小的实现决策如何引入严重漏洞。SQL 注入是这一现象最清晰的示例之一——易于理解,但仍被广泛利用。
SQL 注入发生在不受信任的用户输入直接包含在 SQL 查询中时。
输入不被视为数据,而是被解释为 SQL 命令的一部分。这使得攻击者能够操纵查询并控制数据库的行为。
考虑一个典型的登录查询:
SELECT * FROM users
应用程序期望输入是普通的用户数据。
但如果攻击者提供以下输入呢?
' OR 1=1 --
OR 1=1 → 恒为真
-- → 注释掉查询的其余部分
👉 结果:数据库执行被修改后的查询,忽略了身份验证检查。
让我们看看这个漏洞如何在真实代码中出现。
String username = request.getParameter("username");
String password = request.getParameter("password");
String query = "SELECT * FROM users WHERE username = '"
+ username + "' AND password = '" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
用户输入被直接拼接进 SQL 查询中。
代码与数据之间没有分隔。
数据库无法区分预期的查询逻辑和攻击者输入。
username: admin
💣 生成的查询结果
SELECT * FROM users
👉 条件 OR 1=1 恒为真,因此无论密码如何,查询都会返回结果。
结果:身份验证被绕过。
SQL 注入不仅仅是一种理论风险——它可能导致严重后果:
未授权登录(身份验证绕过)
敏感数据暴露
数据库记录的修改或删除
数据库完全沦陷
预防 SQL 注入很简单——只要正确执行即可。
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
👉 原因:
查询结构固定
用户输入被严格视为数据,而非可执行的 SQL
User user = userRepository.findByUsernameAndPassword(username, password);
👉 ORM 会在内部生成参数化查询,这有助于在正确使用时降低 SQL 注入风险。
限制输入长度
⚠️ 重要提示:输入验证 alone 不足以预防 SQL 注入。
数据库用户应仅拥有其所需的权限
仅依赖输入验证
手动转义字符串而非使用参数化查询
信任前端验证
记录包含敏感数据的原始查询
SQL 注入并非复杂的攻击——它通常是简单编程错误的结果。
但其影响可能非常严重。
作为开发人员,结论很明确:
编写查询的方式中的微小决策决定了你的应用程序是安全的——还是完全暴露。
Original Content
Even today, a single poorly written SQL query can allow an attacker to bypass authentication or expose sensitive data.
And the scary part? It often comes down to just one line of code.
In the previous articles, we saw how small implementation decisions can introduce serious vulnerabilities. SQL Injection is one of the clearest examples of this—simple to understand, yet still widely exploited.
SQL Injection occurs when untrusted user input is included directly in a SQL query.
Instead of being treated as data, the input is interpreted as part of the SQL command itself. This allows attackers to manipulate queries and control how the database behaves.
Consider a typical login query:
SELECT * FROM users
The application expects input to be normal user data.
But what if an attacker provides this instead?
' OR 1=1 --
OR 1=1 → always true
-- → comments out the rest of the query
👉 The database ends up executing a modified query that ignores authentication checks.
Let’s look at how this vulnerability often appears in real code.
String username = request.getParameter("username");
String password = request.getParameter("password");
String query = "SELECT * FROM users WHERE username = '"
+ username + "' AND password = '" + password + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
User input is directly concatenated into the SQL query
No separation between code and data
The database cannot distinguish between intended query logic and attacker input
username: admin
💣 Resulting Query
SELECT * FROM users
👉 The condition OR 1=1 is always true, so the query returns results regardless of the password.
Result: Authentication is bypassed.
SQL Injection is not just theoretical—it can lead to serious consequences:
Unauthorized login (authentication bypass)
Exposure of sensitive data
Modification or deletion of database records
Full database compromise
Preventing SQL Injection is straightforward—but only if done correctly.
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
👉 Why this works:
Query structure is fixed
User input is treated strictly as data, not executable SQL
User user = userRepository.findByUsernameAndPassword(username, password);
👉 ORMs generate parameterized queries internally, which helps reduce the risk of SQL injection when used correctly.
Limit input length
⚠️ Important: Input validation alone is not sufficient to prevent SQL Injection.
Database users should have only the permissions they need
Relying only on input validation
Manually escaping strings instead of using parameterized queries
Trusting frontend validation
Logging raw queries with sensitive data
SQL Injection isn’t a complex attack—it’s usually the result of a simple coding mistake.
But its impact can be severe.
As a developer, the takeaway is clear:
Small decisions in how you write queries can determine whether your application is secure—or completely exposed.