SQL Inject
POC
访问http://localhost:8080/sqli/jdbc?username=joychou' or 'a'='a返回joychou: 123 wilson: 456 lightless: 789。
正常访问http://localhost:8080/sqli/jdbc?username=joychou返回joychou: 123
数据库表数据SQL
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for users -- ---------------------------- DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `username` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `isAdmin` varchar(255) NOT NULL, `id` int(10) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- ---------------------------- -- Records of users -- ---------------------------- BEGIN; INSERT INTO `users` VALUES ('joychou', '123', '1', 1); INSERT INTO `users` VALUES ('wilson', '456', '0', 2); INSERT INTO `users` VALUES ('lightless', '789', '0', 3); COMMIT; SET FOREIGN_KEY_CHECKS = 1;
预处理修复原理
SQL注入修复方式采用预处理方式,修复见代码。
预处理的修复原理:针对字符串类型的SQL注入,是在字符串两边加上一对单号哈'',对于中间点的单引号对其进行转义\',让其变成字符的单引号。Mybatis的#{}也是预处理方式处理SQL注入。
在使用了mybatis框架后,需要进行排序功能时,在mapper.xml文件中编写SQL语句时,注意orderBy后的变量要使用${},而不用#{}。因为#{}变量是经过预编译的,${}没有经过预编译。虽然${}存在SQL注入的风险,但orderBy必须使用${},因为#{}会多出单引号''导致SQL语句失效。为防止SQL注入只能自己对其过滤。
根据下面的结果可以发现order by 'username'并没有用,第一条SQL和第二条SQL效果一样。
select * from users order by 'username' desc -- 结果为 joychou wilson lightless select * from users -- 结果为 joychou wilson lightless select * from users order by username -- 结果为 joychou lightless wilson select * from users order by username desc -- 结果为 wilson lightless joychou