前记
今天是sql注入学习笔记,基础知识篇,本文主要介绍sql注入当中的一些基础知识,包括一些重要的trick、文件操作、常用的函数(如字符串连接、截取、编码等函数)等,以及在中间会穿插很多细微的、比较少人留意到的一些tips知识点。
0x00 测试环境
先给出测试环境的数据库表
mysql> show variables like '%log_file%'; 查看日志文件存放位置,后续权限够的情况下,我们可能还会通过这个来拿webshell
0x01 一些重要的trick
0x011 查看日志文件存放位置
0x012 查看数据库编码情况
show variables like 'char%'; 查看编码情况
0x013 指定可外连的数据库用户和ip
这里的意思是允许root用户以这个密码,在任意ip上连,实际中肯定不能这样
mysql> grant all privileges on *.* to 'root'@'%' identified by 'admin' with grant option;
mysql> flush privileges;
0x014 关于mysql账号密码
mysql数据库的账号密码在mysql.user这个表中,MYSQL数据库的认证密码有两种方式,MYSQL 4.1版本之前是MYSQL323加密,MYSQL 4.1和之后的版本都是MYSQLSHA1加密,MYSQL数据库中自带Old_Password(str)和Password(str)函数,它们均可以在MYSQL数据库里进行查询,前者是MYSQL323加密,后者是MYSQLSHA1方式加密。
例如
mysql> select user,password from mysql.user ;
例如
localhost root *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
查询出来的值只取*后面的内容拿去解密即
81F5E21E35407D884A6CD4A731AEBFB6AF209E1B
这个才是密文
要解密mysql中查出来的密码,可以在这个网站上解密
选择对应的mysql解密方法或者选择sha1解密都行
MYSQL 4.1版本之前的就选择mysql323这个解密方法
MYSQL 4.1和之后的版本就选择MySQL4.1/MySQL5+ (40 bytes)或者sha1都行
ps:
mysql> select user,authentication_string from user;
有些版本的数据库原有的密码字段名是这个
0x015 模糊匹配
rlike、regexp、like
其中rlike、regexp的用法都和php中正则的用法一模一样
like中使用%表示匹配任意个数的任意字符
匹配username中包含字母j的行
0x016 注释符
# 最普通的单行注释,实际渗透中最好用之前用url编码下,效果会更好,编码后的值为 %23
-- - 注意中间的空格哦
-- +
`` 在bypass一些比较老的waf可能还会有些用
/**/ 常规内联注释--可代替空格,绕过空格过滤
/*!*/
/*!50000 */ mysql 5通用,带版本内联注释
注意:多行注释符(在mysql下需要能闭合 才有效):/* */或` `(反引号)等
0x017 Mysql内置变量,搜集数据库信息时会用到
version() 当前数据库详细版本号,注意,针对mysql 4和5的注入方式是完全不一样的
database() 当前所在的数据库
user() 当前数据库用户权限
@@datadir 数据文件的存放目录
@@basedir 数据库的安装路径
@@version_compile_os 宿主系统平台是什么
@@hostname 当前机器的机器名,可不是域名哦
null 特殊工具,因为它可以匹配任意数据类型,在遍历字段个数时可能会用到
0x02文件操作(读写)
·文件写入--需要有写的权限,通常只有root有
一定要用绝对路径--限制了必须能使用引号
select * into outfile '绝对路径'
select * into dumpfile '绝对路径'
如果是dll,so,exe,必须二进制写,尝试导出udf时可能会用到
tips:
·可以使用16进制和char()来绕过对字符串关键字的过滤
至于使用char()函数来写入,我们可以使用python来辅助构造payload
将刚刚得到的hex放进python里面执行得到payload
关于绝对路径
linux和windows下都可以使用 /
windows下还可以使用 \\ 注意是两个反斜杠(即反斜杠要转义一下)
写入的文件必须是原来不存在的,若是原来已经存在了的文件,我们无法覆盖它写入,会产生一个错误
这里要注意我们使用char()和使用0x16进制的时候都不要加单引号,否则就当成一个字符串来写入了,而不会unhex处理,例如
文件读取--绝对路径
load_file(绝对路径)
0x03常用函数
字符串连接函数--3个
-----MySQL的concat和group_concat函数在连接字符串的时候,只要其中一个是NULL,那么将返回NULL(注意:group_concat也是这样,验证过了 5.x版本)
concat(str1,str2,str3...)中间只要字符串有一个为null,最后结果也为null,注意 ‘null’ 和 null 不一样(区别同 ‘1’ 和 1)
concat_ws(‘指定分隔符’,str1,str2,str3...)它会自动忽略中间的空值,只有分隔符为空,整体才返回空
group_concat(field_name1, field_name2, field_name3...)
把某个字段下的所有数据全部连接成一个字符串,注意有长度限制,默认1024,(默认使用逗号隔开)(不会受limit的限制)
实例测试如下
截取函数--5个
注意在mysql中的所有字符串截取操作[除了limit],默认都是从1开始的,并非像代码中的数组是从0开始的
substring(要截取的字符串,从什么地方开始截取,截取多长)
substr(要截取的字符串,从什么地方开始截取,截取多长)
mid(要截取的字符串,从什么地方开始截取,截取多长)
left(str,length)从左往右截取length个字符,左截取
right(str,length)从右往左截取length个字符,右截取
根据官方文档的描述substring和substr两者基本没有任何区别,所以一个被过滤了的时候可以使用另一个去替代。
而mid()是mysql 专有的字符串截取,也就是说只有在mysql中有,mssql和oracle以及pgsql中都没有。
Tips:
username第一行内容为mjc,长度为3,若截取第四个字符,则输出的ascii码值为0--对应的是null空字符--这个特点可以用于盲注的判断(这个以后讲)
select ascii(substring((select username from user limit 0,1),4,1));
字符串填充,跟代码中的字符串填充是一个意思,注意,如果被填充的位置原来有数据则会被直接覆盖,我们可利用这种方式来查数据
lpad(str,len,padstr)
rpad(str,len,padstr)
用字符串 padstr对 str进行左填充或者右边填充直至它的长度达到 len个字符长度,然后返回填充后的结果。
tips
如果 str的长度长于 len',那么它将被截除到 len个字符,所以可以用这个来代替字符串截断函数,绕过一些过滤了常规的字符串截断函数的waf
返回出现位置--可尝试配合上面的字符串截取函数在读取文件时用
ps:返回的位置从 1 开始
locate(substr,str)第一个语法返回字符串str第一次出现的子串substr的位置。
locate(substr,str,pos)第二个语法返回第一次出现在字符串str的子串substr的位置,从位置pos开始。 substr不在str中,则返回0。
字符串替换--在读取文件时,我们可能需要用到replace()替换一些特殊字符
replace(搜索字符串范围,替换前的子字符串,替换后的子字符串)
这是临时替换,返回替换后的内容,但并不改变原来的内容。
大小写转换,有时候为了减少我们的手工劳动量,可能就需要用到这种转换函数,尽可能的帮我们缩小范围
lower(字符串) upper(字符串)
返回对应的ascii码的函数--2个
ascii(单个字符)
ord(单个字符)
tips:
如果输入多个字符的话,返回第一个字符的ascii码
把指定的数字转换成对应的ASCII码字符,n久以前 bypasswaf的惯用招数,各类编码绕过waf也是最常见的一种方式
char(num)
进制转换函数--3个
16进制转换,导出udf的时候可能会用到
hex() unhex()
conv(num,from_base,to_base) 经常会用来绕过某些编码过滤
Conv(数字,进制1,进制2)返回 数字 从进制1 转为 进制2 的内容
mysql> select conv(11,10,16);
tips:hex()和unhex()都是从右到左读取字符的,如unhex(223)读取的是 23和2,而不是22和3 (0x23代表的是#)
case用法--相当于sql中的’switch’语句
case..when..then..when..then..else..end
语法:
CASE search_expression
WHEN expression1 THEN result1
WHEN expression2 THEN result2
...
WHEN expressionN THEN resultN
ELSE default_result
搜索CASE表达式,使用条件确定返回值.
语法:
CASE
WHEN condition1 THEN result1
WHEN condistion2 THEN result2
...
WHEN condistionN THEN resultN
ELSE default_result
END
tips
有一个类似php的弱比较的特性
0x04 统计(长度、记录)
统计字符串长度
length(字符串)
统计某个表下总共有多少条记录
count(*)
0x05 时间盲注常用函数+if
·时间盲注最常用的两个函数
benchmark(count,expr) 性能测试函数,意思就是执行expr count次
sleep(second) 定时休眠函数
if判断特性,常配合时间盲注一起使用
if(exp,a,b)--表达式exp为真则返回a,否则返回b
0x06 Information_schema数据库的结构+常规利用
(列schema_name跟其他两个表的table_schema是一样的,但名字不同,注意)
查询数据库名字的时候使用schemata表,查询table_name时使用tables表,查询column_name的时候使用columns表,这是有原因的!(重复性问题!在tips中详细说明)
查询所有的数据库名
查询test数据库中的表名
查询user2表的列名
tips
思考:information_schema.tables表中拥有table_schema字段,那为什么查询数据库名字的时候使用schemata表,而不使用tables表呢?
主要还是一个重复性的问题!看下面例子
例如我们使用tables表查询table_schema和使用schemata表查询schema_name
使用schemata表,结果很正常
使用tables表查,会看到很多重复的,这就是区别!
所以查询数据库名字的时候使用schemata表,查询table_name时使用tables表,查询column_name的时候使用columns表
结尾
据此,本文把sql注入中文件操作、常用的函数(如字符串连接、截取、编码等函数)等方面的基础知识基本介绍完了,后续的深入就是常规注入、报错注入、盲注(基于布尔值、基于时间),再深入一点就是实现脚本化自动注入、绕过各种waf等。
看不过瘾?合天2017年度干货精华请点击《【精华】2017年度合天网安干货集锦》
别忘了投稿哟!!!
领取专属 10元无门槛券
私享最新 技术干货