07 | SQL注入:明明设置了强密码,为什么还会被别人登录?
该思维导图由 AI 生成,仅供参考
SQL 注入攻击是如何产生的?
- 深入了解
- 翻译
- 解释
- 总结
本文详细介绍了SQL注入攻击的原理、影响和防护方法。通过案例和示例,阐述了SQL注入攻击的产生方式,包括修改WHERE语句和执行任意语句两种主要方式。进一步指出,SQL注入攻击可能导致绕过验证、数据篡改、数据窃取和资源消耗等严重后果。文章提出了三种常见的防护方法:使用PreparedStatement、使用存储过程和验证输入。其中,使用PreparedStatement能够避免99.99%的SQL注入问题,通过将SQL语句的解析和执行过程分开,实现防护。另外,使用存储过程和验证输入也是有效的防护手段。总结指出,正确使用PreparedStatement方法或存储过程,尽量避免字符串拼接操作,以及对用户输入进行验证和过滤,是避免SQL注入的关键。文章还提出了思考题,引发读者思考和讨论。
《安全攻防技能 30 讲》,新⼈⾸单¥59
全部留言(21)
- 最新
- 精选
- 豆豆之前只是知道些简单的 SQL 注入方式以及防范措施,今天文末的盲注确实涨了知识,关于思考题自己做了如下的练习。 首先盲注应该也是通过 web 端的输入来实现黑客的入侵目的的,那么黑客就可以通过观察页面的反应来动态修改自己的注入参数。比如一些提交输入框,当我们提交了参数之后页面反应正常那么就说明我们的猜测是正确的,否则继续猜。 我们都知道 MySQL 内部有一个 information_schema 的库,里面都是数据裤的元信息,那么我们就可以利用这个库进行猜测,通过观察页面的反应来验证自己的猜测是否正确。 第一步我们要知道数据的名字,那么就先猜测其长度。以下我们会用到 DATABASE(), LENGTH(), SUBSTRING(), ASCII() 四个内置函数。 1. 确定数据库长度 SELECT name FROM user WHERE id = 1 AND (SELECT LENGTH(DATABASE()) = 4); 得到数据库长度之后猜测数据库名字的每个字母。 2. 确定数据库名字 通过 ASCII 码方式 SELECT name FROM user WHERE id = 1 AND (SELECT ASCII(SUBSTRING(DATABASE(), 1, 1)) < 128); 根据 ASCII 码猜测是可以使用二分法来猜测。假设的到的结果是 test。 得到数据库名字之后,猜测 user 表有多少个列。 3. 获取该表有多少列 SELECT name FROM user WHERE id = 1 AND ((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE table_name = 'user' AND TABLE_SCHEMA = 'test') = 3); 获取到列的多少列之后,就可以获取到每一列的长度了。 4. 获取列长 SELECT name FROM user WHERE id = 1 AND ((SELECT LENGTH(column_name) FROM information_schema.COLUMNS WHERE table_name = 'user' AND TABLE_SCHEMA = 'test' LIMIT 0, 1) = 2); 最后,获取每一列的具体值。 5. 获取列名,同样是使用 ASCII 码方式 SELECT name FROM user WHERE id = 1 AND ((SELECT ASCII(SUBSTRING(column_name, 1, 1)) FROM information_schema.COLUMNS WHERE table_name = 'user' AND TABLE_SCHEMA = 'test' LIMIT 0, 1) < 120) 为了故事的顺利发展这里我假设我们已知表名 user,但是我们可以根据同样的逻辑从 information_schema.TABLES 表中获取 test 库的所有表信息。 最后,我感觉这个方式有点傻啊,因为它依赖一些很特定的条件,比如后端没有做 SQL 注入的防护,而且还必须结合前端页面的反应。
作者回复: 赞,是这么个原理。
2019-12-2346 - 小晏子研究了下盲注的文章,长见识了,以前只是大概知道sql注入,知道最简单的方式,盲注这种方法还是第一次接触,针对这个思考题,可以按如下方式获取其他字段,思路如下,可以写脚本实现,还有前提是能够进行盲注, 1. 先判断字段的第一个字符是否在a-z中,如下所示, select Username from Users where UserId = 1 and 1 = (select 1 from information_schema.columns WHERE table_name='Users’ and COLUMN_NAME REGEXP '^[a-z]') 如果结果显示Username那就说明字段的第一个字符在a到z中, 2. 使用二分查找法在a到z之间查找第一个字符,如下语句, select Username from Users where UserId = 1 and 1 = (select 1 from information_schema.columns WHERE table_name='Users’ and COLUMN_NAME REGEXP '^a[a-z]') 如果能显示Username,那么就说明a是第一个字符,再依次去查第二个字符,反之,换一个字符再试。 3. 以此类推,可以找到所有的字段名。 顺便说下,字段名中可能包含其他字符,如 _ 等,可以在正则表达式中同样去匹配。
作者回复: 赞~
2019-12-238 - sober希望老师能抽出一节讲讲登录实战,想真正了解一下整个登录如何应用加密,谢谢老师了
作者回复: 这块在前面的加密和认证应该有涉及,还有哪些问题,可以具体留言沟通一下。
2019-12-242 - 小老鼠现在SQL注入不常见了吧,现在的开发框架都可避免SQL注入了吧。比如基于python的Django。
作者回复: 如果使用了orm的话,确实不会出现。但如果还是自己写sql的话,其实还是很普遍的。
2019-12-3121 - Gamer777通过使用 PreparedStatement,将 SQL 语句的解析和实际执行过程分开,只在执行的过程中代入用户的操作。分开执行还是无法防御SQL注入吗,不然为什么底层还是会对一些特殊符号进行转义操作?
作者回复: 可以防御注入。底层进行转义,本质上就是preparedstatement帮你采取的防御措施,而不需要你去操心转义啥的。
2020-07-18 - HE明伟老师,现在的spring boot这些框架都能预防sql注入了吧
作者回复: 正确使用的话,就可以
2020-07-09 - felix如果是string,还是解决不了第一个password或的情况?
作者回复: 如果是字符串拼接然后直接执行sql,那就会被注入。
2020-01-13 - 律飛作为编程小白而言,学习难度有点大哦🙄。多看了好几篇盲注的文章,仍然是晕头转向的。豆豆已经提供了很好的答案。不过我还是来说说我的理解,不足之处请老师批评指正。 盲注其实就是结合SQL最基本的两种注入方式,不断去猜测并验证数据库可能的信息,最终获得答案的过程。这需要注入者简单的基础和丰富的经验,以及长时间频繁地跟数据库交互。 对于这种攻击,开发者采用PreparedStatment,存储过程,验证输入等方法就可以防范攻击。 请教老师:对于输入内容验证是不是还可以通过长度进行控制?对于盲注是不是可以通过单位时间内某个id跟数据库连接次数进行限制和预警?如果想动手试验,如何避免触碰红线?
作者回复: 1、可以,就是有点弱。如果你限制只能一个字符的话,可能还行。 2、可以 3、自己搭环境。网上有开源的渗透测试环境,比如WebGoat,可以自己搭一个玩。
2020-01-02 - 小老鼠可介绍下sqlmap吗?
作者回复: sqlmap是自动化进行sql注入的工具,这个专栏注重甲方安全防御,所以攻击只介绍原理,不会过多去涉及攻击的各种细节。这方面感兴趣的话,可以自学一下,有问题欢迎留言沟通。
2019-12-31 - Zhen了解了一下盲注,比较有意思,根据你SQL注入的攻击语句返回TRUE或者FALSE,可被用来一点点猜测获取数据库schema。 比如:如果 http://newspaper.com/items.php?id=2 and 1=2 返回FALSE;http://newspaper.com/items.php?id=2 and 1=1 返回正确,就说明后面输入的语句被服务器执行了 而且存在一个数字型的注入;那我们现在就可以开始盲注,判断它目前使用的数据库、版本、一点点猜测数据库内容。 另外有个很初级的问题想请教一下,SQL注入是不是所有SQL数据库固有的问题?为什么数据库本身不能自我完善做到输入参数的过滤和保护,而是要Java应用程序来通过PreparedStatement来做?
作者回复: 数据库的任务就是执行SQL,在SQL注入的过程中,JAVA提交给数据库的,就是一条完整的SQL语句。因此,从数据库的角度,是没有任何问题的。
2019-12-23