Skip to content

SQL Inject

JoyChou edited this page Jul 17, 2019 · 2 revisions

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
Clone this wiki locally