SQL Injection Attacks (SQLi)

Learn what SQLi attacks are, who they target, how they differ from other types of cyberattacks.

2023 Mid-Year Threat Report

What is a SQL Injection Attack?

Structured Query Language (SQL) is a language designed to manipulate and manage data in a database. Since its inception, SQL has steadily found its way into many commercial and open source databases. SQL injection (SQLi) is a type of cybersecurity attack that targets these databases using specifically crafted SQL statements to trick the systems into doing unexpected and undesired things.

If you have less than five minutes, learn about SQL Injection Attacks in this video: 

成功的攻击者可能对受攻击的目标采取的行动包括:

  • Bypassing authentication
  • Exfiltrating/stealing data
  • Modifying or corrupting data
  • Deleting data
  • Running arbitrary code
  • 获得对系统本身的root访问权限

How Dangerous are SQL Injections?

If completed successfully, SQL injections have the potential to be incredibly detrimental to any business or individual. Once sensitive data is compromised in an attack, it can be difficult to ever fully recover. 

Databases are commonly targeted for injection through an application (such as a website, which requests user input and then does a lookup in a database based on that input), but they can also be targeted directly. SQL注入攻击列在 OWASP 公司需要应对的十大应用程序安全风险.

Types of SQL Injection Attacks

SQL注入攻击可以通过多种方式实现. Attackers may observe a system’s behavior before selecting a particular attack vector/method.

Unsanitized Input

Unsanitized input is a common type of SQLi attack in which the attacker provides user input that isn’t properly sanitized for characters that should be escaped, 并且/或者输入没有被验证为正确/期望的类型. 

For example, a website used to pay bills online might request the user’s account number in a web form and then send that to the database to pull up the associated account information. If the web application is building a SQL query string dynamically with the account number the user provided, it might look something like this:

            “SELECT * FROM customers WHERE account = ‘“ + userProvidedAccountNumber +”’;”

While this works for users who are properly entering their account number, it leaves the door open for attackers. For example, 如果有人决定提供一个账号“'或' 1 ' = ' 1”, 这将导致查询字符串为:

            “SELECT * FROM customers WHERE account = " or ' 1 ' = ' 1 '; "

由于' 1 ' = ' 1 '总是求值为TRUE, 将此语句发送到数据库将导致数据为 all 顾客被退回,而不是单个顾客.

Blind SQL Injection

也称为推理SQL注入, a Blind SQL injection attack doesn’t reveal data directly from the database being targeted. 相反,攻击者会仔细检查行为中的间接线索. Details within HTTP responses, blank web pages for certain user input, and how long it takes the database to respond to certain user input are all things that can be clues depending on the goal of the attacker. They could also point to another SQLi attack avenue for the attacker to try.

Out-of-Band Injection

This attack is a bit more complex and may be used by an attacker when they cannot achieve their goal in a single, direct query-response attack. Typically, 攻击者将编写SQL语句, when presented to the database, will trigger the database system to create a connection to an external server the attacker controls. In this fashion, the attacker can harvest data or potentially control behavior of the database.

二阶注入是一种带外注入攻击. In this case, the attacker will provide an SQL injection that will get stored and executed by a separate behavior of the database system. When the secondary system behavior occurs (it could be something like a time-based job or something triggered by other typical admin or user use of the database) and the attacker’s SQL injection is executed, 这就是攻击者“伸出”控制系统的时候.

SQL Injection Example 

For this SQL injection example, let’s use two database tables, Users and Contacts. The Users table may be as simple as having just three fields: ID, username, and password. Contacts表中有关于用户的更多信息, such as UserID, FirstName, LastName, Address1, Email, credit card number, and security code. 

Users表包含如下登录信息: 

  1. jsmith,P@$$w0rd
  2. sbrown,WinterIsComing!
  3. kcharles,Sup3rSecur3Password$

Note: Passwords should always be hashed and salted when stored in a database and never in cleartext.

When someone wants to log in, they’ll go to the login page and enter their username and password. 然后将此信息发送到web服务器, which will construct a SQL query and send that query to the database server. 这个查询的一个例子可能是:

从用户名= ' jsmith '和密码= ' P@$$w0rd '的用户中选择ID

The way SQL works is that it will then perform a true or false comparison for each row that the query requests. In our example, the query says to check the Users table and give back the ID value for every row where the username is jsmith and the password is P@$$w0rd. Often, the webserver will then see what is returned by the database server and if it is a number. In our case, the webserver would receive back a 1 and let the user past the login page. 

但是,如果我们想恶意地使用它呢? 因为数据库服务器执行真假检查, 我们可以欺骗它,让它相信我们已经成功认证了. 我们可以通过在密码中添加OR来实现这一点. If we log in with x’ or 1=1 as our password, that will create a new SQL query that looks like: 

从用户名= ' jsmith ',密码= ' x '或1=1的用户中选择ID

This will work for us, 因为x不是jsmith的密码, 然后,数据库服务器将检查第二个条件. 如果x不是jsmith的密码,那么1是否等于1? It does! The ID will be sent back to the application and the user will be successfully authenticated. 

这并不一定是1=1的条件. 任意两个相等的值都可以,2=2,4726=4726,甚至a=a. 

如果一个网页能够显示数据, 也可以在屏幕上打印额外的数据. 为了访问数据,我们可以尝试将两个SQL请求链接在一起. In addition to our ‘ or 1=1, 我们可以在此基础上添加第二个语句,如UNION SELECT LastName, credit card number, security code from Contacts. 像这样的附加条款可能需要额外的工作, but getting access to data is the ultimate goal of a SQL injection attack.

另一种可以用于SQL盲注入的技术, the one where no data is sent back to the screen is to inject other hints. 与' or 1=1条件类似,我们可以告诉服务器休眠. 我们可以加上:“' or sleep(10)”,这看起来就像这样. It will tell the database server to take a 10-second nap and all responses will be delayed.

How to Prevent SQL Injection Attacks

The following suggestions can help prevent an SQL injection attack from succeeding:

Don’t use dynamic SQL

  • 避免将用户提供的输入直接放入SQL语句中.
  • Prefer 预处理语句和参数化查询, which are much safer.
  • 存储过程通常也比动态SQL更安全.

Sanitize user-provided inputs

  • 适当转义那些应该转义的字符.
  • 验证提交的数据类型是否与预期的类型匹配.

Don’t leave sensitive data in plaintext

  • 加密存储在数据库中的私有/机密数据.
  • Salt the encrypted hashes.
  • This also provides another level of protection just in case an attacker successfully exfiltrates sensitive data.

限制数据库权限和特权

  • 将数据库用户的能力设置为所需的最低限度.
  • 这将限制攻击者在设法获得访问权限时所能做的事情.

避免直接向用户显示数据库错误. Attackers can use these error messages to gain information about the database.

Use a Web Application Firewall (WAF) 用于访问数据库的web应用程序

  • 这为面向web的应用程序提供了保护.
  • 它可以帮助识别SQL注入尝试.
  • Based on the setup, it can also help prevent SQL injection attempts from reaching the application (and, therefore, the database).

Use web application security testing 常规测试与数据库交互的web应用程序. Doing so can help catch new bugs or regressions that could allow SQL injection.

保持数据库更新到最新的可用补丁. This prevents attackers from exploiting known weaknesses/bugs present in older versions.

SQL注入是攻击者常用的攻击方法, 但是通过采取适当的预防措施,比如确保 data is encrypted, 保护和测试您的web应用程序, 并且你的补丁是最新的, 您可以采取有意义的步骤来保证数据安全.