Web渗透之联合查询注入全流程
2026/9/10 22:36:07 网站建设 项目流程

本文仅用于网络安全技术学习与授权测试交流。本文实验皆在靶场进行,任何未经授权使用文中技术的行为均与作者无关,请务必遵守法律法规,获得许可后方可进行渗透测试。

目录

一、概念

1.SQL注入的概念

2.SQL注入的目的

二、注入点的数据类型

1、注释

2、注入步骤

(1) 方式一

原理:

(2) 方式二

原理:

(3)方式三:

三、确定字段数

四、sql注入

五、确定回显字段

六、sql注入

七、查询数据库的信息

数据库函数

sql注入

八、查询数据库中所有的表

九、查询某张表中所有的列

十、查询某张表中所有表数据

十一、防御和绕过

1、对特殊符号进行转义

2、强转整数

3、替换关键字

大小写绕过

双写绕过

注释绕过

一、概念

1.SQL注入的概念

SQL注入是一种常见的网络安全漏洞,指攻击者通过在Web表单输入、URL参数或请求头等用户可控的位置,恶意插入SQL代码片段,从而欺骗后端数据库执行非预期的SQL命令。

核心原理:当应用程序动态构造SQL查询语句且未对用户输入进行充分过滤或参数化时,攻击者可以改变原SQL语句的逻辑结构。例如,将登录验证的SQL:SELECT * FROM users WHERE name = '输入的用户名' AND pwd = '输入的密码'通过输入admin' --(恒真条件并注释后续语句)变成:SELECT * FROM users WHERE name = 'admin' --' AND pwd = 'xxx'从而无需正确密码即可绕过认证。

2.SQL注入的目的

SQL注入攻击的主要目的通常分为以下几类,攻击者根据自身意图选择不同的利用方式:

  1. 绕过认证机制在登录、权限校验等场景中,通过注入恒真条件(如' OR '1'='1)或注释掉后续密码检查,无需有效凭证即可冒充其他用户(尤其是管理员)。

  2. 获取敏感数据(数据泄露)

    • 窃取用户表:账号、密码(可能哈希)、个人身份信息、支付信息

    • 提取业务数据:订单、交易记录、内部文档

    • 联合查询获取数据库元数据:如所有表名、字段结构,为后续攻击铺路

  3. 篡改数据利用UPDATEINSERTDELETE语句修改数据库内容,例如:

    • 提升自身权限等级

    • 篡改商品价格、投票结果

    • 删除日志以掩盖入侵痕迹

  4. 拒绝服务或破坏数据

    • 批量删除表或行(如DROP TABLEDELETE

    • 执行耗时查询(笛卡尔积、递归调用)耗尽数据库资源

  5. 提权与命令执行

    • 在特定数据库(如MySQL的INTO OUTFILE)中写入Webshell,获取服务器控制权

    • 利用存储过程或函数执行操作系统命令(如xp_cmdshell

  6. 持久化隐蔽后门通过UNION或时间盲注等技术,长期从数据库中批量外发数据到攻击者控制的服务器。

简单总结:核心目的就是“让数据库执行原本不被允许的操作”,最终实现信息窃取、身份冒用、权限提升或破坏系统。防御上需以参数化查询为根本,并配合权限最小化原则。

二、注入点的数据类型

  1. 数字型(Integer/Float)

    • 特征:SQL中直接拼接数字,无需引号包围。

    • 示例:SELECT * FROM products WHERE id = 1→ 注入id=1 OR 1=1

    • 测试:输入1 AND 1=11 AND 1=2看响应差异。

  2. 字符型(String)

    • 特征:使用单引号'或双引号"包围用户输入。

    • 示例:SELECT * FROM users WHERE name = 'admin'→ 注入admin' OR '1'='1

    • 需闭合或注释掉多余的引号。

  3. 搜索型(LIKE 查询)

    • 特征:与LIKE操作符组合,通常带有%通配符。

    • 示例:SELECT * FROM articles WHERE title LIKE '%{keyword}%'→ 注入%' OR 1=1 --

    • 需处理通配符及引号。

  4. JSON/XML 字段

    • 特征:数据库支持JSON/XML类型,应用程序可能直接拼接查询路径。

    • 示例:MySQL中SELECT />

      发现页面报错

      再加-- -

      发现不报错

      所以判断是字符型

      原理:

      让我们看一下这个靶场的源代码,可以看到这个id有单引号包裹,所以这个靶场是字符型注入

      如果我们加了个单引号,这个语法是错误的,所以会报错

      如果加个-- - 语法正确,回显正常

      (2) 方式二

      在url中输入 and 1=1,页面的结果不发生变化,再输入 and 1=2,页面的结果发生变化,可以确定注入点数据类型为数字型,反之就是字符型

      输入1=1,页面不发生变化

      输入1=2,页面还是不发生变化

      判断是字符型

      原理:

      1=1回显正常,自动取前面的1,后面的丢弃

      1=2,还是不变

      但是数字型1=1是回显正常,1=2就找不到了

      字符型无论后面写什么,它都会把后面的自动丢弃

      (3)方式三:

      在url输入转义符,通过观察页面的报错情况来判断注入的数据类型

      可以看到把最外面引号去掉之后,里面的1\由引号包裹,所以判断是字符型,如果没有引号包裹,那就是数字型

      三、确定字段数

      order by 1 表示根据字段1进行排序,可以查出来数据表字段1里的数据

      如果写2 就是第二个字段进行排序

      同理,写3,也能查出来,但是写4,就会发生报错,如果报错就说明它没有第四个字段

      所以我们就判断只有三个字段

      四、sql注入

      如果是数字型,那就直接写order by 1 -- -,如果是字符型需要按下图格式去写

      正确语法:’ order by 1 -- -

      已知这道题是字符型,加入单引号,界面会报错

      所以要再加-- - 界面恢复正常

      ok,我们再添加order by 1,运行发现没报错,可知字段一存在

      添加2发现都没报错,可知存在2字段

      但是添加3,发现报错,可知,只存在1,2字段,3字段不存在

      五、确定回显字段

      确定回显字段的sql语句:

      六、sql注入

      使用union进行联合查询注入 ​ union的作用就是把左边sql语句查出来的数据与右边sql语句查出来的数据进行合并 ​ 要注意左右列数一致,数据要兼容

      使用limit进行分页查询 ​ limit 索引,行数 ​ 对limit来说第一行的索引是0,第二行的索引是1

      注入的时候limit可以不写前面1前可以加个负号,效果是一样的

      七、查询数据库的信息

      数据库函数

      以下是MySQL 中常用于信息收集的内置函数/变量列表,可在 SQL 注入中用于探测数据库环境:

      最常用的是前三个

      函数/变量作用返回值示例
      database()当前使用的数据库名'security'
      version()MySQL 版本号'5.7.42'
      user()当前连接用户及主机'root@localhost'
      current_user()当前被认证的用户(通常与user()相同)'root@localhost'
      system_user()系统用户(MySQL 服务运行的操作系统用户)'mysql'
      session_user()当前会话用户'root@localhost'
      @@versionversion()'5.7.42-log'
      @@version_commentMySQL 版本附加信息'Source distribution'
      @@datadir数据目录路径/var/lib/mysql/
      @@basedirMySQL 安装基目录/usr/
      @@hostname服务器主机名'localhost.localdomain'
      @@portMySQL 服务端口3306
      @@tmpdir临时目录路径/tmp
      @@secure_file_priv文件导入/导出限制目录NULL或具体路径
      @@log_error错误日志文件路径/var/log/mysql/error.log
      schema()database()'security'

      sql注入

      查询数据库的名称

      查询数据库的版本号

      查询当前登录数据库的账号

      可以进行联合查询数据库的基本信息

      示例:

      八、查询数据库中所有的表

      sql语句:

      这种sql语句还不能进行sql注入,我们得把它转成单行单列的

      用group_concat()把值转换成一行,这样就能进行sql注入了

      查询的时候我们得用子查询,把它放进小括号里

      这样表名就出来了

      演示效果:

      九、查询某张表中所有的列

      查询某张表中的列的sql语句:

      sql注入:

      咱们查users表下的列试一试

      http://192.168.179.135/DVWA-master/DVWA-master/vulnerabilities/sqli/?id=1' union select (select group_concat(column_name)from information_schema.columns where table_schema=database() and table_name='users'),2 limit 1,1-- -&Submit=Submit#

      十、查询某张表中所有表数据

      sql语句:

      先多列转一列

      再多行转一行

      这样就能sql注入了

      示例:

      http://192.168.179.135/DVWA-master/DVWA-master/vulnerabilities/sqli/?id=1' union select (select group_concat(concat_ws('-',avatar,failed_login,first_name,last_login,last_name,password,user,user_id)) from users),2 limit 1,1-- -&Submit=Submit#

      十一、防御和绕过

      1、对特殊符号进行转义

      访问文件,首先他是字符型的

      给它注释掉,可以看到多了个斜杠,这个斜杠是转义符

      对于数字型,可以把userinfo转换为十六进制

      转换完之后sql语句就长这样子,可以绕过转义

      结论:转义对字符型注入点有效,但对数字型注入点无效 ​ 绕过:如果注入点是数字型,可以使用十六进制绕过

      2、强转整数

      强转整数只能进行数字型防御

      3、替换关键字

      大小写绕过

      select没了,这就是替换关键字

      但是换成SELECT就可以绕过

      这样可以写

      这样的话SELECT就无法绕过了

      双写绕过

      但是我们可以双写绕过

      注释绕过

      我们也可以替换空格

      空格就没了

      我们也可以使用/**/(注释)代替空格

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询