手工SQL注入示例
一、联合查询注入(回显注入)
是一种结合数据库原始报错信息和union查询的注入方式
使用场景:数据库中查询的结果能够直接在前端页面中展示出来
UNION 操作符用于将两个或多个 SELECT 语句执行的结果合并为一个结果集输出,以下是演示示例:
了解MySQL数据库中几个特殊的数据库
sys
mysql
performanc_schema
information_schema (是MySQL的元数据信息数据库,存储了关于数据库、表及其字段、用户等的元数据,MySQL5.0及以后的版本才有这个库,也是进行SQL注入时重点关注的一个库)
查询时使用的关键字段信息(这个不重要)
操作步骤
(一)判断注入点
判断注入点的数据类型
(1)一般情况下,看默认的输入的值与输入点的功能即可看出输入点的数据类型(默认输入时数字,则可能是数字型;默认输入是字符,则一定是字符型)。
(2)判断数字型,使用四则运算判断(如果id=n和id=(n+1)-1产生的结果一致,则可能是数字型,再尝试添加闭合符号,时sql执行出错,就能证明注入点的数据类型为数字型)
(3)判断字符型(先是报错再闭合),如果有原始数据库报错信息,就一一枚举可能得闭合符号。
(4)判断注入点是否存在,在疑似注入点后加上 and 1=1 和and 1=2,如果两次执行的页面发生了改变(也就是拼接的sql语句在数据库中执行的时候出了问题,页面就会有所改变),说明漏洞存在
(二)判断表中的列数
利用order by 结合折半查找的方式确定表中的列数。
(三)判断数据回显的位置
利用union并将原始查询置空(置空的目的,是让union前面的select查询语句查不到结果,union前面的select语句就不会输出内容,使整个sql语句只输出union后面select语句的查询内容(也就是我们想要看到的内容))来判断数据回显的位置。
(四)将待查询的内容替换到数据回显的位置
示例(以sqlli_labs第3关为例)
(一)判断注入点
(1)判断注入点的数据类型
可以看到输入参数id=1和id=2时返回的结果不一致,表明注入点的数据类型为字符型。
(2)判断注入点使用的闭合符号
一般情况下,输入点的闭合符号大概为英文状态下的单引号、双引号和小括号。在判断闭合符号时,遵循“先报错,再闭合”原则,“报错”是指让界面显示数据库原始报错信息。然后再使用闭合符号使sql语句形成闭合状态。
此时出现了数据库原始报错信息,接着我们按照“先报错,再闭合”的思路进去进行下一步“闭合操作”
可以看出,当我在末尾加上 --+ 用来注释掉sql语句后面多余的部分,还是出现了数据库原始报错信息。(这里为什么使用 --+ 我会在后面进行解释)。出现这种情况,说明此处数据的闭合符号不单单是一个单引号,必定还有其他符号和这个单引号一起组成了闭合符号。
借来继续尝试 ’ 号与其他符号组合,让前端界面出现数据原始报错信息。
可以看到,在加上 ') 闭合符号后,页面也出现了数据库原始报错信息。
其实当我在注入点数据后加上 ') 后,在后端文件中,sql语句已经被拼接成了以下语句
SELECT * FROM `users` where id=('1')') LIMIT 0,1;
可以看出,拼接后的sql语句多了一组闭合符号,也就是 ') 这两个符号,此时sql语句已经不再是一条正确的sql查询语句,所以当后端文件在拼接完成sql语句并带入到数据库中执行时,必然会出错。并且报错信息在前端界面中展示了出来。
为了更直观的展示拼接后的sql语句在数据中执行的效果,我直接在数据库中进行演示。
从以上两张图是不是很直观的看出问题出在了哪?首先,sql语句中的1,就是我在前端中输入的参数,参数1后面的 ') 这组闭合符号,也是我在前端中通过不断尝试凑出的闭合符号。而后面青蓝色框框住的这一组 ') 闭合符号,其实是在后端文件中预设好的。以下是第3关的原代码
从上图可以看出,在源代码中,确实已经有了一组 ') 闭合符号,而我在前端中又凑了一组闭合符号,而多出来的这一组闭合符号,就是让sql语句报错的根本原因。
至于为什么要在末尾加上 --+ 这几个符号,这就涉及到MySQL中的注释了。在MySQL的查询语句中,除了使用 # 号来做注释意外,是不是还可以使用 – 来做注释(注意:–符号后面有一个空格)。在末尾加上 --+ 符号,就是为了将sql语句中后面多余的内容给注释掉。下面我将在数据库中做演示。
为什么在URL中空格要换成 + 号,大致解释可以参考该文章https://blog.youkuaiyun.com/dongheng123/article/details/130416855
(二)判断表中的列数
一般情况下,数据库中表的字段数(列数)不会很大,一般不会超过20 ,但也存在特殊情况。通常情况下从10或者20开始,一半一半往下降,很快就能确定表中的列数。
order by 10
order by 5
order by 3
order by 4
从上面四张图可以看出,我使用order by 进行排序,当我尝试到order by 3时,前端界面展示出了数据,而尝试到order by 4时,数据有没了,这就说明表中的字段只有三个。
看一下数据库,表中确实只有三个字段id,username,password
(四)判断数据回显位置
表中有既然有3个字段信息,就使用union select 1,2,3 来观察,哪些数据会在前端界面中展示出来。(注意:在判断回显位置时,要将原始查询置空。)
从上图可以看出,2和3出现的位置就是数据回显的位置,此时我们只需要把我们要查询的内容给替换到这两个位置的任一位置就行。比如获取当前数据库和数据库角色。
可以看出当前用户为本地root用户,当前数据库为security。
(五)爆数据
爆数据是在知道库、表、列的情况下,才能获得最终数据。也就是你得知道数据库服务器中有哪些数据库,数据库中有哪些表,表中有哪些字段(列),你才能获得明确的数据。这里就设计到MySQL数据库中有一个特殊的数据库——information_schema数据库
这个数据库中,有三个特殊的表:schemata、tables、columns,这三个表的有哪些特殊的点呢?
schemata表
该表中schema_name字段,记录了该数据库服务器中所有数据库的信息。
tables表
该表中的table_name字段,记录了数据库中所有表的信息。
columns表
该表中的column_name字段,记录了数据库中所有字段(列)的信息。
(1)爆库
就是我们首先得知道这个数据库服务器中有哪些数据库,只有获取到数据库的信息,才能继续往下操作。
之前说过,information_schema数据库的schemata表的schema_name字段,记录了数据库中所有数据库的信息,所以此时我们要获取所有数据库的信息,就得在information_schema库的schemata表中来操作。
从上图可以看出,sql语句执行后它只列出了一个数据库名 information_schema,很显然列出的数据库不全。如何让它显示全部的数据库信息,这里就要用到MySQL中的聚合函数group_concat(),该聚合函数的作用,就是把查询出的多行数据,合并成一个字符串进行输出。
以下是数据库管理软件中的截图
结合两张图,确实只有六个数据库,且完全对应得上。
(2)爆表
在知道有哪些数据库以后,我们得根据需求,去获取指定数据库中有哪些表。之前说过,information_schema数据库的table表的table_name字段,记录了数据库中所有表的信息,所以要获取表的信息,就得在information_schema数据库的table表中进行操作。另外,还得根据上一步确定的数据库的信息,指定获取哪个数据库中的表
(3)爆字段(列)
http://127.0.0.1/sqli-labs-master/Less-3/?id=-1%27)%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema%20=%20%27security%27%20and%20table_name%20=%20%27users%27--+
从上图可以看出,表中的字段有id,username,password
(4)爆数据
http://127.0.0.1/sqli-labs-master/Less-3/?id=-1%27)%20union%20select%201,2,group_concat(id,username,password)%20from%20users--+
只查询用户名和密码
以上,就是手工进行联合查询注入的步骤及操作。
二、报错注入
报错注入,是在数据库原始报错信息会在前端界面展示出来的情况下使用。这可能是在系统开发的过程中,开发工程师为了调试方面,会把数据库报错信息在前端界面中打印出来。但开发工程师在开发结束后,未将这样功能给去掉,依然保留了这一方法。
示例(以sql_labs第5关为例)
(一)判断注入点
报错注入,在判断注入点,依然遵循“先报错,再闭合”的原则
可以看到,但执行id=1和id=2-1时,界面并没有,什么变化,既然这样,我们直接尝试让它出现报错
使用 ’ 号进行闭合时,出现了报错,接下来尝试将后的内容注释掉,看页面是否报错
当注释掉后面的内容后,界面恢复了正常,说明拼接的sql语句在数据库中执行了,且没有出错,证明这里的闭合符号就是 ’ 号。解下来就是使用and 1=1 和and 1=2 来判断是否存在注入点。
可以看到,当使用and 1=2时,界面发生了明显的变化(此时sql语句被拼接再到数据库中执行时,由于条件 and 1=2 不成立,sql没有出错,但语句查询不出结果,也就无法再界面中显示什么内容。到这里我们大概知道,当我们输入的内容经过后端文件拼接,带到数据库中执行后,如果sql语句语法正确且查询有结果,那前端界面中就会显示 “You are in…………”,如果sql语句出现了语法错误,前端界面中就会将错误信息打印出来,如果,sql语句语法没问题,但给出的条件不成立,sql语句查询不到任何内容,界面就会“空空如也”。页面发生了改变,说明存在注入点。
(二)使用报错函数爆数据
extravtvalue为MySQL数据库中的报错函数
concat()函数的作用,是连接两个或多个字符串,生成一个新的字符串,在这里,表示把查询到的内容生成一个新的字符串进行输出(展示)
(1)爆库
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata))))--+
group_concat()函数之前讲过
可以看到,确实爆出了数据库的信息,但显示的信息不完整。如果是这样,由于无法获取后面没有显示的数据库的信息,我们不知道数据库服务器中有哪些数据库,那我们岂不是无法获得我们想要的数据库的数据了?这里,我们要使用到MySQL数据库中的截断函数。mysql 中可进行数据截断的函数有好几个,我比较喜欢使用mid()函数
mid()函数使用方法 :mid(string, start, length)
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select mid(group_concat(schema_name),1,30) from information_schema.schemata))))--+
mid(group_concat(schema_name),1,30)解释
group_concat(schema_name),是将查询到的所有数据库的名称合成一个字符串进行输出
mid(group_concat(schema_name),1,30) 这一整句,就是说把查询到的这写数据合成一个字符创,在把这个字符创从第一个字符开始,往后取30个字符,进行输出。示例如下图
如果要获取到后面为显示的内容,修改mid()函数中的第二个参数即可
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select mid(group_concat(schema_name),30,30) from information_schema.schemata))))--+
mid(group_concat(schema_name),30,30) 这一整句,就是说把查询到的这写数据合成一个字符创,在把这个字符创从第30个字符开始,往后取30个字符,进行输出。
经过多次截取数据,是不是就可以确定数据库服务器中有哪些数据库(information_schema、challengs、dvwa、mysql、performance_schema、security)
接下来爆表,爆字段、报数据和联合查询的方法类似,只需简单修改部分参数即可
(2)爆表
tip:这里有个小点要注意,访问URL后,界面却没有任何结果,怎么查都不知道哪里有问题,如下图
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select mid(group_concat(table_name),60,30) from information_schema.tables where table_schema='security'))))--+
很多人在爆出数据库后想要继续爆表时,怎么都爆不出数据,此时要注意mid()函数的第二个参数是否在正常范围内,如果第二个参数超出了字符创长度范围,肯定爆不出数据。下图才是正解。
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select mid(group_concat(table_name),1,30) from information_schema.tables where table_schema='security'))))--+
从第30个字符开始截取30个字符串没有数据,说明,所有数据都在1到30个字符串之间了,也就是往上第二张图中的数据。
(3)爆字段
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select mid(group_concat(column_name),1,30) from information_schema.columns where table_schema='security' and table_name='users'))))--+
(4)爆数据
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and (extractvalue(1,concat(0x7e,(select mid(group_concat(id,'*',username,'*',password),1,30) from users))))--+
里面的 '*' 号,只是为了看上去美观,把id,username,password之间用*号隔开了而已
后续还有布尔盲注,时间盲注,堆叠注入、宽字节注入等常见注入方式讲解,后面会继续完善。
零基础网络安全学习计划
学习路线图大纲总览
我一共划分了六个阶段,但并不是说你得学完全部才能上手工作,对于一些初级岗位,学到第三四个阶段就足矣~
这里我整合并且整理成了一份【282G】的网络安全从零基础入门到进阶资料包,需要的小伙伴文末免费领取哦,无偿分享!!!
【一一帮助网络安全学习,以下所有资源文末免费领取一一】
①网络安全学习路线
②上百份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥HW护网行动经验总结
⑦100个漏洞实战案例
⑧安全大厂内部视频资源
⑨历年CTF夺旗赛题解析
接下来我将给各位同学划分一张学习计划表!
学习计划
那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:
阶段一:初级网络安全工程师
接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。
综合薪资区间6k~15k
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)
2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等
3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)
4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现
5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固
6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)
那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?
阶段二:中级or高级网络安全工程师(看自己能力)
综合薪资区间15k~30k
7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。
零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;
Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完
用Python编写漏洞的exp,然后写一个简单的网络爬虫
PHP基本语法学习并书写一个简单的博客系统
熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)
了解Bootstrap的布局或者CSS。
阶段三:顶级网络安全工程师
这部分内容对于咱们零基础的同学来说还太过遥远了,由于篇幅问题就不展开细说了,我给大家贴一个学习路线。感兴趣的童鞋可以自行研究一下哦,当然你也可以点击这里加我与我一起互相探讨、交流、咨询哦。
资料领取
上述这份完整版的网络安全学习资料已经上传网盘,朋友们如果需要可以微信扫描下方二维码 ↓↓↓ 或者 点击以下链接都可以领取
