GET方法

GET 是 HTTP 请求方法之一,用于从服务器获取资源,不修改服务器上的数据。

核心特征

参数拼接在 URL 中

格式:url?参数名1=值1&参数名2=值2

如果要同时传递多个参数,参数之间以”&“分割

如果要给网站传递&这个符号,则要使用百分号+16进制ascii码值:%26。

由于URL编码中通常出现%,所以URL编码又称百分号编码。

示例: http://test.com/index.php?id=1&name=admin    ? 后面的内容就是 GET 传参数据。

GET 方法缺点

  1. 参数明文暴露在 URL 地址栏,容易泄露敏感信息,服务器访问日志也会记录参数。
  2. 受 URL 长度限制,无法传输大容量数据。
  3. 可被浏览器缓存、保存为书签,容易造成数据重复读取、隐私泄露。

POST方法

基本定义

POST 是 HTTP 请求方法,用于向服务器提交数据,常用来新增、提交数据。

POST 提交的数据存放在 HTTP 请求体

核心特征

  1. 数据存放于请求体(Body) 参数不在 URL 中,地址栏看不到提交的数据。
  2. 理论上无大小限制 不受 URL 长度约束,可以传输大量数据(文件上传基本使用 POST)。
  3. 浏览器默认不会缓存 POST 请求,无法直接保存为书签
  4. 多用于提交表单、上传文件、登录操作。

数据库的结构:数据库服务器 → 数据库(Schema) → 数据表(Table) → 行 (记录)、列 (字段)

information_schema

信息数据库。保存着mysql中所有其他数据库的信息,数据库名,数据库中的表、表中的字段等。

以下以stu数据库作为验证,结构图如下

       

show tables;

查询当前选中数据库里面所有数据表

schemata表

  • 功能:存储该用户创建的所有数据库的库名
  • 核心字段:schema_name:数据库自身名称。

数据库名.表名

tables表

  • 功能:存储用户创建的所有数据库的库名和表名
  • 核心字段
    • table_schema:数据表归属的数据库名称。
    • table_name:数据表自身名称

解释:

        information_schema 记录所有数据库的信息,在 information_schema 数据库中有一张 tables 表,记录用户创建的所有数据库的库名和表名,在 tables 表中有两个重要字段为 table_name、table_schema,分别是数据表名,数据表对应的数据库库名。

         执行语下图语句查询含义:读取 tables 表中的表名、所属库名,筛选只展示归属库名为 stu 的数据表。

         查询结果:数据库名为 stu 里有两张表,分别为 class,student,两张数据表所属数据库均为 stu。

        拓展:功能等价 use stu;show tables;

        区别:show tables 无法在 union 联合查询中使用,查询 information_schema.tables 是 SQL 注入获取表名的核心方式。

查询当前 MySQL 实例中所有数据库名 + 数据库内所有数据表名

columns表

column----列

  • 功能:存储用户创建的所有数据库的库名,表名,字段名
  • 核心字段
    • table_schema:字段归属的数据库名称。
    • table_name:字段所属的数据表名称。
    • column_name:数据表内部的字段名称。

distinct:去重,只获取表名

逻辑关联

table_schema(数据库名)  

        ↓包含

table_name(数据表名)  

        ↓包含

column_name(字段名)

sql查询的完整流程

  • 查询 information_schema.schemata,读取 schema_name,获取全部数据库名称。
  • 选定目标数据库,查询 information_schema.tables,通过 table_schema 筛选库名,读取 table_name,获取该库下所有数据表。
  • 选定目标数据表,查询 information_schema.columns,通过 table_schema、table_name 筛选库与表,读取 column_name,获取表内全部字段。
  • 使用得到的库名、表名、字段名,查询真实业务表,读取账号、密码等目标数据。

常用函数:

  1. version() 查询 MySQL 数据库版本
  1. database() 获取当前正在使用的数据库名称
  2. user() / current_user() 数据库登录账号
  3. @@version_compile_os 服务器操作系统(Windows/Linux)
  4. @@datadir 数据库文件存放路径

select查询

#打开某个数据库
use 数据库名;

#查看数据库中的表
show tables;

#显示所有字段
select * from 表名;

#显示指定字段
select 字段1,字段2 from 表名;

union联合查询

        注意:联合查询的字段数量必须一致。如果不一致则需指定为一致的数量,不足时则可以插入数字来补充字段

limit的用法

        格式:limit  m ,n

        m:起始偏移位置(省略时默认从0开始计数)

        n:取出多少条记录

order by的用法

      order by n:按第 n 列排序;通过增减数字观察页面响应,判断查询拥有多少列。

        数字≤真实列数,页面正常;数字>真实列数,SQL 报错。

group_concat() 

        把查询多条结果合并成一行字符串,用来替代limit 

注释符

字符类

在页面有文本框输入时可使用字符类注释符

1. #

2.--空格

3./**/

4.--+

URL编码类

        在页面文本框输入数据提交后,若为GET 提交方式,输入的数据会拼接在 URL 后方传递给网站。 在 URL 中传输参数时,浏览器会自动对特殊字符执行URL 编码。

        URL 规范中,空格、单引号、#、&、+ 等字符拥有特殊含义;直接放在 URL 会破坏参数结构。编码后转为安全十六进制形式,保证数据完整传输。

'    的编码标识为%27   +  表示空格    %3D是=的URL编码     %23:等价于#

URL 常用特殊字符编码对照表

原始字符URL 编码说明
空格%20 / +GET 参数内+代表空格;%20通用
' 单引号%27字符型注入高频
#%23URL 中 #代表锚点,浏览器截断请求,注入必须编码
&%26用于分隔多个参数
+%2B原始加号需要传输时编码

dvwa   low级别SQL注入

文本型注入

        客户端输入的数据被作为字符串带到了select查询语句的一对单引号中。

查看关键源码

变量query的值是一个select查询语句,然后调用mysqli_query()函数执行这个查询

分析查询语句:

$id是来自客户端输入数据

当输入的值为 ' or 1=1 #时
查询语句变成:
where user_id ='' or 1=1#' 
#将最后的单引号给注释,使其并不发挥作用
结果恒为真,则显示了所有的用户信息

使用的payload

' or 1=1 #

        第一个单引号是为了与原代码中的左侧单引号闭合,使其成为一对,

        #是为了将原代码中右侧的单引号注释,这样在mysql中执行select查询时,原本最后的单引号就被忽略了

数字型注入

        不需要闭合符号

常见select语句

1 and 1=2 --+ ,如果浏览器报错,则位数字型

select * from admin where id=$id;

        特点:变量$id没有单引号包裹,直接传入数字

sqli第一关

1.判断文本型,数字型注入的方法

        检测网站是否会对传入的数据进行数值运算,如果做数值运算,就是数值型注入。

id=1时能查出结果

闭合标签,能查询

id=1 and 1=2--+ 

payload id=1 and 1=2--+仍可查询到数据,判定为文本型注入。传入参数整体被单引号封装为字符串,and 1=2无法参与 SQL 逻辑运算;MySQL 隐式提取字符串首部数字1执行查询,所以正常回显数据。

当判断目标为文本型 SQL 注入后,下一步需要确定语句闭合符号,利用闭合符提前终结后端原有 SQL 的引号结构,从而追加自定义查询逻辑,再使用注释符屏蔽后续原生代码,避免语法报错。

2.判断闭合符

双引号不能闭合

单引号能闭合

3.判断查询的列数

第四列时报错,说明列数为3列

4.union联合查询判断回显的位置

UNION:把多条 SELECT 查询结果合并成一张结果集

-1(不存在数据) 前面查询结果为空,页面只会展示 UNION 后面自定义查询的数据。

回显位置为2,,3

5.查询关键信息

    5.1当前正在使用的数据库

    security

    5.2查询当前数据库中的所有表

    如果不使用group_concat(),则显示不全

    使用group_concat()获得所有表的信息

    5.3查询表中的字段信息

    现在已经知道了有users这个表,接下来查询表中的字段

    column_name:数据表字段内部的名

    table_name:数据表自身的名字,当下是security

    6.查询密码

    username,'~',passwoed:指定间隔符为~

    concat():单行多字段拼接,使用limit m,n指定显示的行

    或者substr()截取

     第三关:

    第三关关键点:找到正确的闭合符

    输入id=1,有结果

    判断是数字型还是字符型

    判断为字符型,因为后面的and符号没有生效

    判断闭合符

    ?id=1' and 1=2 --+

    页面正常回显数据 仅传入单引号无法触发逻辑截断,说明原始 SQL 不只是简单id='$id'结构,单引号逃逸后语句语法不匹配,条件未能生效。

    ?id=1" and 1=2 --+

    页面正常回显数据 双引号同样无法破坏原有查询结构,排除双引号作为外层包裹符号。

    ?id=1') and 1=2 --+

    无查询数据返回 ')成功逃逸,查询条件and 1=2生效,判定后端原始 SQL 结构闭合符为('  ')

    逃逸成功:

    整条 SQL 语法合法,可以自由控制查询逻辑,页面不会报语法错,而是根据条件有无数据。

    闭合组合
    '
    "
    ')
    ")
    )
    %'
    %"

    更多推荐