10年前,我就用 SQL注入漏洞黑了学校网站

news/2024/5/14 10:52:22/文章来源:https://blog.csdn.net/weixin_43167418/article/details/112793056


10年前,我就用 SQL注入漏洞黑了学校网站

标题有点臭不要脸,有标题党之嫌了,没有黑,只是网站安全性做的太差,我一个初学者随便就搞到了管理员权限。

事情是这样子的,在10年以前,某个月黑风高夜的夜里,虽然这么说有点暴露年龄了,但无所谓,毕竟我也才18而已。我打开电脑,在浏览器中输入我们高中学校的网址,页面很熟悉,很简陋,也没什么设计感,不过学校的网站从来都是这种风格,直到今天依然是这样。

这次访问与以往有些不同,因为我的目的很明确。作为学校的一员,理应为学校做些贡献的,为学校官网找些安全漏洞也算贡献的一种吧(强烈的求生欲)。

之所以选择学校的官网,一来是因为熟悉,先从熟悉的东西下手,一定错不了。二来是因为之前使用网站的时候碰过到一些异常的页面,直接就是异常堆栈直接抛出来。正好那段时间对网络安全比较有兴趣,在研究SQL 注入的时候正好想到在学校官网上碰到的问题好像就存在 SQL 注入的风险。于是,顺理成章,我的第一个目标就锁定了学校官网。

问题就出在一个大概这样的搜索页面,真正的网站已经改版过好多次了,以前的页面找不到了。

当时我在上面随便输入了一些内容,里面含有单引号,然后一点击搜索,页面就直接出现了异常提示,类似于下面这样子的。别惊讶,当时很多网站都是这样的,异常是直接抛出来的,别说以前了,现在也不少。

于是我用那时候刚学会的皮毛知识,加上两个好用的工具,轻松拿到了数据库的数据,其中就包括了管理员的账号、密码,密码还是明文的,你说气人不。然后通过后台管理员登录页面进入了管理员后台,当然了,只是进去看了看,什么都没碰,而且后台也没什么重要数据,顶多就是一些通知、新闻等数据。

我是怎么做到的呢,不说具体细节了,也确实没什么技术含量,而且时间太长也记不清了,后面就说一下 SQL 注入的原理和具体操作。

什么是 SQL 注入

SQL注入,是发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了字符检查,那么这些注入进去的恶意指令就会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏或是入侵。

SQL 注入一般发生在用户交互场景中,比如需要用户自已输入信息的输入框,或者下拉选择选项的这种,如果不做好输入内容的过滤,就很可能发生 SQL 注入。

就拿这个登录界面来说,用户名和密码都是你要输入的内容,点击登录按钮之后,会把你输入的值传递到服务端,服务端再到数据库进行查询。

假设后端的查询语句是这样的,不要在乎这是什么语法,只是举个例子。

String sql = "select * from `user` where  account={account} and password={password}";

正常的情况,比如 account 输入的是一个电话号码 13001980988,密码是 123456,那拼接出的 SQL 语句就是

String sql = "select * from `user` where  account='13001980988' and password='123456'";

然后,服务端通过数据库连接执行这条语句:

select * from `user` where  account='13001980988' and password='123456';

最后,数据库正常返回符合条件的记录,代码中再根据结果进行判断,执行后面的逻辑。

不正常的输入

SQL 注入就是通过不正常的输入来获取程序开发者意料之外的结果。

什么是不正常的输入呢?

比如我在用户名输入框中输入的内容是这样子的 :13001980988' or 1=1 --,密码输入框随便输入什么都无所谓,然后点击登录,传输给后端,后端拼接出来的结果就是这样的:

String sql = "select * from `user` where  account='13001980988' or 1=1 --'  and password='123456'";

然后,服务端通过数据库连接会执行下面这条语句:

select * from `user` where  account='13001980988' or 1=1 --'  and password='123456'

以 MySQL 为例, -- 是 MySQL 中的注释符号,上面的语句中 --后面的相当于是注释内容了,所以最后实际执行的 SQL 语句是这样的:

select * from `user` where  account='13001980988' or 1=1 

于是,SQL 注入就这么发生了,显然有了 or 1=1 这个条件,表中所有的记录都符合条件。如果在用户名输入框中输入的是 adminadministrator 等已知的后台管理员账号,那就可以用管理员账号直接登录系统了。

上面就是 SQL 注入的基本原理。

SQL 注入遍地都是的年代

在9、10年前,也就是在我小时候(对,这个词好,小时候)。那时候智能手机才刚刚出来,塞班系统还很贵,根本就买不起。用着功能机,30M的流量能用坚持一个月,聊天只靠 QQ 和 短信,微信才刚要问世,更别提什么 APP 了,根本就没有。那时候,PC Web 才是根正苗红的网络主宰,如果说要在网上干点儿什么的话,那必须要有一个配套的网站才可以。

互联网还没有发展的这么成熟,用的技术也比较原始,绝大多数的网站是用 PHP 写的,还有很多用 ASP 。可能有些同学都不知道 ASP 是什么,它虽然也是微软的,但是却不是 ASP.NET。数据库很多用的是 MySQL ,还有一部分用的是更原始的 Access,可能又触到某些同学的盲区了,这不怪你没见识,只怪你太年轻。

一些小公司啊、学校啊、政府部门网站啊、各种论坛啊等等,各种五花八门的网站。不像现在这样,无论你用 PHP、Java 还是 Python,都有很多成熟的开发框架供你选择,成熟的框架必然会减少漏洞和降低被攻击的风险。但那时候没有这么多框架供选择,就比如很多学校会选择用 ASP + Access 组合的架构来开发自己的学校官网、教务管理系统等,功能上比较简单,但是全靠手工去写,就说 SQL 查询吧,从建立数据库连接到拼接 SQL 语句,再到执行查询处理查询结果,全都要自己实现,并没有什么 ORM 框架、数据库连接池供选择,由此就带来了 SQL 注入的风险。

而且建网站,如果不想开发的话,有很多 CMS 框架,尤其 PHP 的很多,现在依旧使用广泛的有 WordPress,当时国内的有 Discuz、DEDECMS 等一批傻瓜建站的 CMS 系统,由于代码都是开源的,而且 WordPress 还支持插件,所以会有很多相关的漏洞爆出来,尤其在多年以前,有了漏洞,想拿下一个网站真是太容易了,即使漏洞已经公布并有了解决方案,但依然有好多网站不及时修补和升级。现在在 Google 中搜索相关的 SQL注入关键词,有很多相关介绍。

说了这么多,这不都是 PHP 的代码吗?嘘,只是碰巧而已,说明 PHP 市场大呀,毕竟PHP是最好的开发语言。那 Java 中就没有了吗,当然有啊。

MyBatis 中的 SQL注入风险

最近在看一些代码,Spring Boot + MyBatis 的,偶然发现一个模糊查询的方法的 SQL 语句中用到了 like '%${keyword}%'这样的查询条件,这一看就有 SQL 注入漏洞。大家可能都了解,MyBatis 是可以解决 SQL 注入的问题的。一般我们在使用 MyBatis 的时候都会把 SQL 语句单独的放到 xml 文件中,在 SQL 语句中支持两种格式的参数占位符,一种是 #{parameter},另一种是 ${parameter},在这两种参数占位符中,#{parameter}是安全的,不存在SQL注入漏洞,而 ${parameter}是存在 SQL 注入漏洞的。

安全的占位符格式

#{parameter} 这种占位符会在 MySQL中进行预编译,所以你观察到 MyBatis 打印出来的日志是这样的:

select * from `user` where  account=? and password=?

其实在框架底层,是 JDBC 中的 PreparedStatement 类在起作用,PreparedStatement 是我们很熟悉的 Statement 的子类,它的对象包含了编译好的SQL语句。这种预编译的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。

不知道你有没有写过直接用 JDBC 操作数据库的代码,反正大学老师就告诉我们要用占位符去做数据库查询,而不是拼接 SQL 字符串,因为用占位符的方式安全。其实,MyBatis 的预编译模式的底层实现就可以理解为下面这样的。

Connection conn = getConn();//获得连接
String sql = "select * from `user` where  account=? and password=?"; //执行sql前会预编译号该条语句
PreparedStatement pstmt = conn.prepareStatement(sql); 
pstmt.setString(1, "13001980988");
pstmt.setString(2, "123456");
ResultSet rs=pstmt.executeUpdate(); 

不安全的占位符格式

${parameter} 这种格式是不进行预编译的,也就相当于字符串的拼接,存在 SQL注入的问题,如果非要用这种方式,那需要在程序中对参数进行安全性校验。强烈建议在使用 MyBatis 的过程中不要使用 ${parameter}这种格式的占位符,而要使用 #{parameter}这种格式。

来一波SQL注入

我模拟了一个 SQL 注入的场景,很简单,就是一个模糊查询的接口,根据用户输入的关键词查询。

数据库中有两张表,分别为用户表(user)和 新闻表(news)。

用户表:

新闻表:

NewsMapper 类:

public interface NewsMapper {List<News> selectNewsLikeTitle(@Param("keyword") String keyword);
}

实际的 SQL 语句,注意,正是用到了 ${keyword},才有了 SQL 注入的问题。

<select id="selectNewsLikeTitle"  resultType="org.kite.purely.mybatis.entity.News">select * from news where title like '%${keyword}%';
</select>

然后我写了一个控制台,接收输入的参数,传给 selectNewsLikeTitle,以便来尝试 SQL 注入。

代码已上传至 github,链接放在了文末,需要的同学自取

正常的输入

新闻表就三条数据,我以 Docker 作为关键词,正常情况下,应该是这样的返回结果:

蓝色是我输入的关键词,后面跟着查询语句。一个标准的模糊查询语句,最后输出的结果也没问题。

select * from news where title like '%Docker%'; 

SQL 注入

如果使用者都这么守规矩就好了,但是真实情况往往并不是这样的,有些人就是喜欢躲在阴暗的角落放着冷箭,大部分情况下是有利可图,极少部分干脆就只是为了满足变态心理。

1、查询所有记录

有同学已经看出来了,输入空值不就是查询所有吗?对的,没错,但真实情况下,前端或者 Controller、Service 层会做拦截,不允许查询所有。

正常逻辑不允许,但是 SQL 注入就可以。我输入下面这样的条件参数,看看会出现什么结果呢?

Docker' or 1=1 or 1='

结果出来了,三条数据全部查询出来了。

因为构造的 SQL 语句已经完全变味儿了,SQL 语句是这样的,由于条件 or 1=1  的加持,导致任何记录都符合条件。

select * from news where title like '%Docker' or 1=1 or 1='%';

通过添加'来保证条件中字符串前后单引号的闭合。

还可以是这样的条件

Docker' or 1=1 -- 
或者
Docker' or 1=1 #

因为--#都是 MySQL 中的注释符号,用它们来注释掉关键注入后面的部分,最后构造出来的 SQL 语句是:

select * from news where title like '%Docker' or 1=1 -- %';
或
select * from news where title like '%Docker' or 1=1 #%';

所以,最后有效的部分就是注释符号前面的部分,自然,查询出来的就是所有的记录。

select * from news where title like '%Docker' or 1=1

这种情况,其实保密数据没有什么泄漏,但是,它可能会拖垮数据库,抛开 Redis 缓存什么的不谈,假设仅有 MySQL 这一层,假设数据库中有几万条、几十万条数据,黑客不断制造这样的模糊查询,你的数据库服务马上就会挂掉。

2、联查其他表,危险行为

把数据库拖垮已经很不爽了,但是更严重的,是获取数据。

我想要通过这条查询语句把 user表的数据也套出来,你看着是不是就有点儿意思了。怎么办呢,通过 union就可以。

前提是我已经知道有 user 表的存在了,别问怎么知道的,反正是已经知道了,而且黑客有很多办法能猜到。

我构造这样的参数:

Docker' union select * from `user` -- 注释掉后面的内容

执行一下,出现这样的提示:

构造出来的 SQL 没有问题,就是我们想要的。

select * from news where title like '%Docker' union select * from `user` -- 注释掉后面的内容%';

但是这用户体验很好,给出了具体的异常。体验好是对于攻击者而言的,如果每次异常都把原始异常信息抛出,那能给攻击者省不少事儿,就像下面这个异常。

Cause: java.sql.SQLException: The used SELECT statements have a different number of columns

这是因为 news 表和 user 表的列数不一致导致的,前后列数不一致,那这时候怎么办呢?

构造出下面这样的查询语句可以试探出 news 表的列数,其中 select 1,2 from user中的 1,2表示假设 news 表有两列,可以从 1 到 n,当尝试到哪一个而不出错或者正常返回的时候,表示 news 表就有多少列了。

select * from news where title like '%Docker' union select 1,2 from `user`;

要构造这样的语句,需要输入的参数是:

Docker' union select 1,2 from user # 

因为 news 表只有两列,所以上面的参数可以成功执行。

盲注

大多数网站都不会将异常信息直接返回的,当攻击者拿不到即时的异常反馈时,就像是合着眼睛去猜,这种情况就叫做盲注。盲注是需要极大的耐心、高超的技术以及丰富的经验的,所以说黑客真不是好当的。

当试探出 news 表的列数后,再去配合它筛选 user 表的列就可以了,user 表的列名其实也是靠各种猜测的,比如常规的命名 name、account、phone、mobile、password 等,或者根据你返回给前端的属性对应着猜,比如返回的用户名是 userName,那你数据库中的字段就很有可能是 user_name。

假设我猜 user 表有 phone 这个字段,那我构造的参数就可以是下面这样的:

Docker' union all select 1,phone from user # 注释掉后面的内容 ,来确定news表有两个字段

最后执行下来,结果是这样的,四条 user 记录全出来了。

或者我还确定 user 表中有 password 列,那就可以直接把 password 再取出来了,如果 password 再是明文的,那就热闹了。

有了用户名和密码,是不是就有点危险了。

3、更危险的高权限

还有更危险的呢,假设你程序中数据库连接用到的账号是高权限的,比如 root 账号,有好多中小应用都这么用,别惊讶。

发散思维想一想,这时候能干嘛?

由于权限够高,那意味着可以执行任何合法的 SQL 语句了。在 MySQL 中有数据库 information_schema,它存储着当前数据库实例中的很多重要信息,而且其中的表结构都是公开透明的,那这样一来呢,我们就可以通过这个数据库掌握当前数据库服务的几乎所有内容了。

不仅如此,高权限用户还能通过 MySQL 的读写文件功能实现更多的功能,比如配合 webshell 上传木马,获取服务器的控制权,从而实现脱裤(拖库)。

当然了,说的轻松,实现起来就困难了,不过只要有漏洞,就会被利用。

一些工具

俗话说,工欲善其事,必先利其器。漏洞哪儿那么容易挖,很多有价值的漏洞确实是厉害的黑客手工挖出来的。

为了方便的挖掘常见漏洞及利用漏洞,有很多网络安全专家开放出来的工具,可以让我等小白简单上手。比如我上学时候用到的「啊D注入工具」。可以用来扫码注入点、SQL注入检测、管理入口检测等。

还有比较专业的 SQL 注入工具「SQLMap」,它是一款命令行工具。SQLMap 提供了丰富的命令来帮我们发现漏洞、利用漏洞。

img

另外,如果你想学习 SQL 注入的一些基础,可以直接整个靶场来玩玩儿。比如这个 Pikachu 就不错。

https://github.com/zhuifengshaonianhanlu/pikachu

总结

本文并不是为了教各位如何完成 SQL注入,毕竟,我也没这个实力。当然,制造漏洞的实力还是有的。

只是想说,在写代码的时候一定要注意,稍有不慎就可能写出有漏洞的 SQL,所以,尽量用成熟框架的标准写法,不要图省事自己拼 SQL。

不光是 SQL 这部分,其他的涉及到用户交互的地方都要注入,比如用户表单,有时候可能产生 xss 漏洞,还有文件上传的部分,别用户上传了木马都不知道怎么回事。

愿你的代码没有 bug。虽然这是不可能的。

文中的测试代码已放至仓库:https://github.com/huzhicheng/SQL_Injection,有需要的同学自取。

-----------------------------------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_828565.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十年磨一剑,美国巨头视频网站 Hulu 的直播系统架构实践

Hulu 是 2007 年在美国上市的在线视频公司&#xff0c;提供会员制付费视频服务&#xff0c;商业模式与国内的爱奇艺、优酷类似。Hulu 今年 5 月发布了最新的 OTT 电视直播应用——Hulu Live TV&#xff0c;目标是替代传统的有线电视服务&#xff0c;和国内最近兴起的直播应用&a…

如何抓到入侵网站的黑客?

今天我在知乎看到一个提问&#xff1a;在下面回答区&#xff0c;我看到网友分享的真实案例&#xff0c;大家可以看一下&#xff0c;顺便了解一下网络溯源是怎么一回事&#xff0c;也给大家一些启示。我朋友在创业&#xff0c;听说他公司被人搞了&#xff0c;请我去帮忙看下。我…

table改网站框的大小

table 当网站出现这样 上下不一样宽的时候 修改的时候要修改最外部的table 修改完后效果 本文转自 yeybz 51CTO博客&#xff0c;原文链接:http://blog.51cto.com/hmlwl/1398906

储备量为零也可以有自己的网站

创建一个属于自己&#xff0c;任何人都可以访问的网站&#xff08;最最最详细的步骤&#xff09; 这篇文章将从购买服务器一直到最后网站完成备案&#xff0c;详细说明整个过程&#xff0c;就算是不懂编程的人照样可以拥有属于自己的服务器和网站 必备条件&#xff1a; 1&…

小型电子商务网站架构图

这是我为我们项目创建的电子商务架构图 本文转自 charles_wang888 51CTO博客&#xff0c;原文链接&#xff1a;http://blog.51cto.com/supercharles888/834295&#xff0c;如需转载请自行联系原作者

《大型网站技术架构:核心原理与案例分析》读书笔记

作者&#xff1a;13 GitHub&#xff1a;https://github.com/ZHENFENG13 版权声明&#xff1a;本文为原创文章&#xff0c;未经允许不得转载。 此篇已收录至《大型网站技术架构:核心原理与案例分析》读书笔记系列&#xff0c;点击访问该目录获取完整内容。 初次阅读:仰视和懵懂 …

电商网站中购物车功能模块完善

主要有两方面的问题&#xff1a; 1、登录状态下添加商品到购物车 此时购物车是对应一个用户&#xff0c;很简单&#xff0c;就是将商品的数据插入数据库中即可&#xff0c;但是如果读写频繁的时候&#xff0c;就存在压力问题&#xff0c;此时我们可以使用Redis担任读的部分功能…

分享几个下载应用的网站

在这哪都有捆绑软件的互联网时代&#xff0c;我还是分享一下我个人在使用的一些下载应用的网站吧1吾爱论坛https://www.52pojie.cn/forum-16-1.html很久之前就有的破解论坛&#xff1b;有着很多软件&#xff1b;教程等。唯一不好的是注册需要缴费&#xff0c;不过每年都会有免费…

Windows 服务器配置、运行、图文流程(新手必备!) - IIS建站配置一条龙

Window 2008 服务器的配置教程 本文提供全流程&#xff0c;中文翻译。 Chinar 坚持将简单的生活方式&#xff0c;带给世人&#xff01;&#xff08;拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例&#xff09; Chinar —— 心分享、心创新&#xff01;助力快…

我的网站搭建 (第十四天) xadmin强化后台

2019独角兽企业重金招聘Python工程师标准>>> 昨天在逛开源中国社区时&#xff0c;偶然在推荐中看到有关xadmin的文章&#xff0c;一想到Django自带的后台不是admin吗&#xff0c;难道它们之间有某种联系&#xff1f;果不其然&#xff0c;还真的是&#xff0c;xadmin…

怎么把页面内容填满一页_SEO人员,为什么要研究搜索结果第一页?

对于SEO人员而言&#xff0c;我们每天的目标就是提高网站排名&#xff0c;这需要我们不断的发现问题&#xff0c;并制定不同的方案来完成自己的预期目标。 比如&#xff1a; ①撰写优质内容&#xff0c;丰富内容展示类型。 ②建立高质量外链&#xff0c;确保外链稳定&#xff0…

认证服务器的搭建_从域名到网站,只需要四步!服务器网站搭建流程总结

随着网站技术的不断发展&#xff0c;做一个网站的成本越来越低&#xff0c;甚至我们每个人都可以承担的起网站的经营。在真实世界我们渴望有独属于自己的一幢小房子&#xff0c;在虚拟的网络世界&#xff0c;也同样渴望有自己的一块地盘&#xff0c;比如拥有自己的博客网站&…

网站访问速度测试

前端优化的一般是为了提高页面访问速度和使用者的体验感 安利几个测试速度的好网站 一、最推荐的是最全面的测试网站 有各项评分&#xff0c;优化建议&#xff0c;时间列表 二、仅显示时间部分的测试地址 测试地址2 这个就是比较常见的那种测试网站了 三、类似上面…

https降级为http+网站账号密码获取

大家浏览网页时候可以看到有些网站是http开头的&#xff0c;有些是https开头的&#xff0c;有什么区别呢&#xff1f; http是没有经过加密处理的&#xff0c;这种网站账号密码之类的东西特别容易获取 https是经过加密处理的&#xff0c;这中网站账号密码很难抓取到&#xff08;…

iis网站属性在哪_??5、IIS环境web搭建

第一步&#xff1a;添加中间件IIS在控制面板中点击添加或删除程序&#xff0c;然后点击添加/删除windows组件&#xff0c;然后勾选应用程序服务器&#xff0c;点击详细信息然后勾选http://ASP.NET和Internet信息服务&#xff08;IIS&#xff09;&#xff0c;点击详细信息勾选万…

vs2013发布网站到服务器,在VS2013创建WebService并在IIS中发布和使用

创建WebService打开VS&#xff0c;新建空项目,注意选择.NET Framework的版本.这里我选择的是.NET Framework 4新建好项目后,在项目中添加一个WebService项打开这个文件,我们可以看到,代码如下using System;using System.Collections.Generic;using System.Linq;using System.We…

网站底部运行时间的php代码,Typecho:在页面底部显示网站运行时间

小白看别人网站底部有显示网站运行时间&#xff0c;感觉挺好玩的。就想着自己也弄一个。显示效果&#xff1a;简单教程&#xff1a;复制以下代码到主题文件夹下functions.php中。建议放置到底部?> 前。// 设置时区date_default_timezone_set(Asia/Shanghai);/*** 秒转时间&…

用python中django创建网页_3.使用Django创建网站

使用Django创建网站 从今天开始讲解如何利用Django框架搭建监控系统 再次推荐可先行网上了解下&#xff0c;另外我力求把每期分割的很细 开发环境 操作系统:CentOS 7.3 Python版本 :2.7 Django版本: 1.10.5 操作系统用户:oracle 安装Django 这里我们使用pip安装 这样安装的是最…

sendmessagea后面的两个参数怎么填写_苹果cms怎么采集别人网站的视频?

苹果cms怎么采集别人网站的视频&#xff1f;采集别人的网站上的视频需要让他帮你打开api接口你才可以采集。然后按照下面的方法开启api接口。还有就是直接采集资源站的接口。网上有很多可以百度搜索下资源采集。就可以找到。操作步骤&#xff1a;苹果cms管理后台&#xff1a;系…

跨境电商自建站后台系统原型rp_小白必看!新手小白如何做好亚马逊跨境电商?...

什么是亚马逊&#xff1f;亚马逊公司(Amazon&#xff0c;简称亚马逊)&#xff0c;是美国最大的一家网络电子商务公司&#xff0c;位于华盛顿州的西雅图。是网络上最早开始经营电子商务的公司之一&#xff0c;亚马逊成立于1995年&#xff0c;开始只经营网络的书籍销售业务&#…