例如,以下是一个PHP代码片段,用于根据用户输入的用户名和密码进行登录验证:
$username = $_POST['username'];$password = $_POST['password'];$sql = "SELECT FROM users WHERE username = '$username' AND password = '$password'";$result = mysqli_query($conn, $sql);
这段代码直策应用了用户输入的用户名和密码,拼接成了一个SQL查询语句,然后实行该语句。如果用户输入的用户名和密码都是合法的,例如username = 'admin'和password = '123456',那么SQL语句便是:
SELECT FROM users WHERE username = 'admin' AND password = '123456'
这个语句的浸染是从users表中查询用户名和密码都匹配的记录,如果存在,就表示登录成功,否则,就表示登录失落败。

但是,如果用户输入的用户名或密码包含了一些分外的字符或命令,例如username = 'admin'和password = '123456' OR 1 = 1,那么SQL语句就变成了:
SELECT FROM users WHERE username = 'admin' AND password = '123456' OR 1 = 1
这个语句的浸染是从users表中查询用户名和密码都匹配,或者1即是1的记录,由于1即是1永久为真,以是这个语句会返回users表中的所有记录,相称于绕过了密码验证,实现了SQL注入攻击。(万能密码便是这个事理)
例2,假设你想在某个网站上购买一本书,你须要输入你的姓名、地址、信用卡号等信息,然后点击提交按钮,完成订单。这个网站的后台程序可能会利用类似于以下的SQL语句,将你的信息插入到数据库中:
INSERT INTO orders (name, address, credit_card) VALUES ('$name', '$address', '$credit_card')
个中,$name、$address和$credit_card是你输入的内容,用单引号包围。如果你输入的内容都是合法的,例如name = '张三'、address = '重庆市南岸区YJ'和credit_card = '1234-5678-9012-3456',那么SQL语句便是:
INSERT INTO orders (name, address, credit_card) VALUES ('张三', '重庆市南岸区YJ', '1234-5678-9012-3456')
这个语句的浸染是将你的信息插入到orders表中,没有任何问题。
但是,如果你输入的内容包含了一些分外的字符或命令,例如name = '张三'、address = '重庆市南岸区YJ'和credit_card = '1234-5678-9012-3456'; DROP TABLE orders; --',那么SQL语句就变成了:
INSERT INTO orders (name, address, credit_card) VALUES ('张三', '重庆市南岸区YJ', '1234-5678-9012-3456'; DROP TABLE orders; --')
这个语句的浸染是先将你的信息插入到orders表中,然后实行一个分号后面的命令,即删除orders表,末了实行一个双破折号后面的注释,即忽略后面的内容。这样,你就利用了SQL注入攻击,删除了网站的订单数据,造成了严重的丢失。
#SQL注入防御利用参数化查询或预编译语句即将用户输入的内容作为参数通报给SQL语句,而不是直接拼接。参数化查询或预编译语句可以有效地防止SQL注入攻击,由于它们会将用户输入的内容作为字面值,而不是可实行的代码。例如,以下是一个利用参数化查询的PHP代码片段,用于根据用户输入的用户名和密码进行登录验证:$username = $_POST['username']; $password = $_POST['password']; $sql = "SELECT FROM users WHERE username = ? AND password = ?"; $stmt = mysqli_prepare($conn, $sql); mysqli_stmt_bind_param($stmt, "ss", $username, $password); mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt);这段代码利用了mysqli_prepare函数来预编译SQL语句,利用了?占位符来表示参数,利用了mysqli_stmt_bind_param函数来绑定参数的值和类型,利用了mysqli_stmt_execute函数来实行SQL语句。这样,即利用户输入的用户名或密码包含了分外的字符或命令,也不会影响SQL语句的构造和语义,而只会作为普通的字符串进行比较,从而避免了SQL注入攻击。利用最小权限原则如果给数据库用户分配了过多的权限,导致攻击者可以利用SQL注入攻击实行一些危险的操作,例如删除表、修正数据、实行系统命令等。例如,如果Web运用程序利用的数据库用户拥有db_owner角色,那么攻击者就可以利用SQL注入攻击实行以下语句,删除users表:DROP TABLE users或者实行以下语句,调用xp_cmdshell扩展存储过程,实行系统命令,例如打开打算器:EXEC xp_cmdshell 'calc.exe'因此,为了防止SQL注入攻击,Web运用程序该当利用最小权限原则,即只给数据库用户分配必要的权限,例如只许可实行查询和更新操作,而不许可实行删除和实行操作。你可以利用MySQL的GRANT命令,指定用户的用户名、主机名、数据库名、表名和权限。例如,假设你的webapp用户的用户名是webapp,主机名是localhost,数据库名是mydb,表名是mytable,你可以利用以下命令:GRANT SELECT, UPDATE ON mydb.mytable TO 'webapp'@'localhost';这个命令的浸染是给webapp用户付与在mydb数据库的mytable表上实行SELECT和UPDATE操作的权限。如果你想要付与webapp用户在mydb数据库的所有表上实行查询和更新操作的权限,你可以利用以下命令:GRANT SELECT, UPDATE ON mydb. TO 'webapp'@'localhost';