安全攻防技能30讲
何为舟
前微博安全研发负责人
立即订阅
2909 人已学习
课程目录
已更新 10 讲 / 共 30 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 别说你没被安全困扰过
免费
安全基础概念 (5讲)
01 | 安全的本质:数据被窃取后,你能意识到问题来源吗?
02 | 安全原则:我们应该如何上手解决安全问题?
03 | 密码学基础:如何让你的密码变得“不可见”?
04 | 身份认证:除了账号密码,我们还能怎么做身份认证?
05 | 访问控制:如何选取一个合适的数据保护方案?
Web安全 (4讲)
06 | XSS:当你“被发送”了一条微博时,到底发生了什么?
07 | SQL注入:明明设置了强密码,为什么还会被别人登录?
08 | CSRF/SSRF:为什么避免了XSS,还是“被发送”了一条微博?
09 | 反序列化漏洞:使用了编译型语言,为什么还是会被注入?
安全攻防技能30讲
登录|注册

07 | SQL注入:明明设置了强密码,为什么还会被别人登录?

何为舟 2019-12-23
你好,我是何为舟。
在上一讲中,我们介绍了 XSS 攻击。今天,我们来介绍另外一种常见的 Web 攻击:SQL 注入。
在讲正文之前,让我们先来看一个案例。某天,当你在查看应用的管理后台时,发现有很多异常的操作。接着,你很快反应过来了,这应该是黑客成功登录了管理员账户。于是,你立刻找到管理员,责问他是不是设置了弱密码。管理员很无辜地表示,自己的密码非常复杂,不可能泄漏,但是为了安全起见,他还是立即修改了当前的密码。奇怪的是,第二天,黑客还是能够继续登录管理员账号。问题来了,黑客究竟是怎么做到的呢?你觉得这里面的问题究竟出在哪里呢?你可以先自己思考一下,然后跟着我开始今天的学习!

SQL 注入攻击是如何产生的?

在上一讲中,我们讲了,XSS 是黑客通过篡改 HTML 代码,来插入并执行恶意脚本的一种攻击。其实,SQL 注入和 XSS 攻击很类似,都是黑客通过篡改代码逻辑发起的攻击。那么,不同的点是什么?SQL 注入到底是什么呢?
通常来说,我们会将应用的用户信息存储在数据库中。每次用户登录时,都会执行一个相应的 SQL 语句。这时,黑客会通过构造一些恶意的输入参数,在应用拼接 SQL 语句的时候,去篡改正常的 SQL 语意,从而执行黑客所控制的 SQL 查询功能。这个过程,就相当于黑客“注入”了一段 SQL 代码到应用中。这就是我们常说的 SQL 注入
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《安全攻防技能30讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(7)

  • 豆豆
    之前只是知道些简单的 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-23
    10
  • sober
    希望老师能抽出一节讲讲登录实战,想真正了解一下整个登录如何应用加密,谢谢老师了

    作者回复: 这块在前面的加密和认证应该有涉及,还有哪些问题,可以具体留言沟通一下。

    2019-12-24
    1
  • 小晏子
    研究了下盲注的文章,长见识了,以前只是大概知道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-23
    1
  • 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
  • Cy23
    注册的时候看input的name都有什么,基本上就了解个大概有什么字段,然后尝试猜常用的字段,
    或者查询显示的语句里注入查询表中所有字段名,然后替换字段名到显示输出的地方查看,
    突然想起原来有个资源下载的网站,原来是免费的,后来收费了,有天无意将页面上下载所需要的分值改为负数,结果下载--为正给我加分了,然后尝试修改分值大小,结果我给自己充满了,我把这个漏洞告诉给站长,站长为了表示感谢奖励我1000分,然后我发现,我那999999999变成了1000。

    作者回复: 这是典型的应用逻辑的漏洞。这种数据,必须以后台数据为准,不能拿前端的数据去修改任何后台的数据。

    2019-12-23
    1
  • rocedu
    要是有个课题程配套虚拟机就更好了

    作者回复: 你好,感谢你的留言。本课题的主要目的还是让大家懂得如何避免漏洞,所以只以最简单的漏洞利用原理进行讲解,实操攻击不是必须的~

    2019-12-23
  • ban
    现在应该很多大部分开发都使用 PreparedStatement 了吧

    作者回复: 我也希望是这样的。

    2019-12-23
收起评论
7
返回
顶部