首页 > 数据库 >SQL 注入

SQL 注入

时间:2024-04-15 23:34:14浏览次数:24  
标签:语句 查询 user SQL select 注入

SQL 注入

原理

  SQL 注入的产生本质上是基于字符串的拼接原理从而产生的,通常数据库作为一个中间产品,需要我们将他和我们的开发代码结合起来使用,比如 JavaPHP 等语言。以 Java 为例,通常我们需要用 JDBC 来连接 DBMS, 也就是类似于 MySQL 的数据库管理系统,即,通过 Java 来执行 SQL 语句,这就意味着,我们通常需要将数据库的查询或者插入删除等等指令预先存储在代码中,在最简单的情况下,这些指令就是由字符串的格式被实现放在代码中。例如以下的Java代码:

public boolean findAdmin(Admin admin){
    String sql = "select count(*) from admin where usrname='"+admin.getUsername()+"'and password ='"+admin.getPassword()+"'";  // SQL 查询语句
    try {
        ResultSet res = this.conn.createStatement().executQuery(sql);
        
        if(res.next()){
            int i = res.getInt(1);  // 取第一列的值
            if (i>0){
                return true;
            }
        } 
    } catch (Exception e){
            e.printStackTrace();
    }
    return false;
}

  这段代码就是一个管理员登录时的后端代码的判断语句操作,如果查询的值大于0, 则表示用户存在,查询成功,密码正确,最终判定登录成功,反之代表登录失败。尽管整个代码的逻辑没有任何问题,甚至看起来这个代码也不是仅仅一两句话,但是如果你仔细看就会发现,代表 SQL 代码指令的语句是以 String 类型存储的。就在代码段的第一句话中。

  你在用户名和密码的输入框中输入的字符被存储到 Admin 类中,通过 admin.getUsername() 等方法获取,最终因为字符串的拼接作用被拼接成一个 String,如果你填写的 user 为 user, 密码为:pwd,在第一个语句执行后你的变量 sql 就会变成如下的模样:

select count(*) from admin where username='user' and password='pwd'

  那么,如果我们换一个方向呢?我们在 user 中填写的字段为'or 1=1-- ',密码为空,也就是不做填写,那么这个变量 sql 就会长这样:

select count(*) from admin where username='' or 1=1-- and password='pwd' 

  注意在sql中,单行注释的指令为--

  也就是说,对 SQL 解释器来说,它看到的你的语句执行条件就是一个 or 关系的判断语句,且后面那一个恒定为真,那么这个查询语句一定能找到结果,最终在代码里一定会显示登录成功。我们登录成功,并不是因为这个我们的管理员的名字叫做 'or1=1--' ,而是输入的这个字段篡改了我们原先想要它执行的 SQL 语句,这种情况就称作 SQL 注入。

  那么用维基百科的定义就是: 发生于应用程序与数据库层的安全漏洞。简而言之,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了字符检查,那么这些注入进去的恶意指令就会被数据库資料服务器误认为是正常的SQL指令而执行,因此遭到破坏或是入侵 。

用途

  SQL 注入可能存在于任何地方,在这种登录界面进行 SQL 注入的可能性事实上并不大,又或者说,注入后我们进入的某个账户里的信息并不足以让我们控制整个网站,注入可能会存在于任何地方,那么这个时候,也许我们可能可以尝试检查一下搜索框,如果存在 SQL 注入,则可以利用这个输入框获取信息。

利用 Union 来实现SQL 注入

  SQL 的查询语法 Union 经常会被应用于获取数据库的其他信息,同时我们也会利用 Union 来猜测数据表各个列的数据类型,或是探测字段数。

Union

  Union 通常被用来合并两个查询结果集的结果。这就意味着,前后两个查询的结果的列数必须相同,同时,查询的每个列的数据类型必须兼容。Union的使用可以参考:https://www.runoob.com/sql/sql-union.html

Union 探测字段数

  试想一下一个存在 SQL 注入的搜索框,他对应的正常的 SQL 查询语句是:

select id, username, password, sex from user where id=1

  虽然一个搜索框不可能是这样的查询语句,好吧,就姑且当作是这个把。以这个为例,我们可以得到他的查询语句的结果; 但是我们要知道,作为攻击者的我们,是不知道 select 的查询列数,就是说,我们不知道 select 后面跟着几个字段。Union 的作用就是试探出 select 后面跟着几个列,可以尝试输入 union select null ,那么完整的注入语句应该是:

select id, username, password, sex from user where id=1 union select null

  如果列数不同,那么会收到一个报错提醒你的联合查询的结果列数并不相同,意味着我们知道这个表的列数不是1,那么可以接着试探:

select id, username, password, sex from user where id=1 union select null, null, null,... ,null

  直到不再收到报错为止。

Union 查询敏感信息

  例如在知道列数为4时,就可以尝试构造语句:

select id, ..., sex from user where id=1 union select 'x', null, null, null from sysobjects where xtype ='U'

  sysobjects是一个自带的系统表, xtype 是其中的一个列,'x' 在这里和 xtype 没有任何关联,他只是一个字符串,在这里他所起到的作用就是在第一列的查询结果的后面加一个 'x',这条语句实际上是在查询 xtype 的类型为 U(代表用户表)的sysobjects 的信息,并在第一列的结果后面添加一个 'x',表示这一列的数据类型是一个字符串型。 可以以此调换 x 的位置,以此试探列的类型。

  在知道某一列的类型同 'x' 相同时,就可以将字符 x 调换,例如替换成 version(), 来显示版本号等等。

DBMS 自带函数的应用

  DBMS 本身自带很多的系统函数足够可以便捷的查看信息,例如在 SQLServer 中可以使用语句:

select suser_name(); -- 返回用户的登录标识名;
select user_name(); -- 基于指定的标识号返回数据库用户名等等。
...

  同样 MySQLOracal 同样有着其对应的系统函数,需要时进行查询即可。

延时注入

  延时注入是盲注技术的一种,主要是基于页面返回给浏览器的时间不同来判断网页是否存在 SQL 注入;这种技术多数是运用在网页的容错技术做的很好的时候,无论你输入什么额外的参数,页面都将返回同样的内容,这时候就要通过页面返回的时间来判断,比如 sleep 函数。例如当你要渗透的网站使用的 DBMS 是 MySQL 时,你可以靠如下的方式来获取你的数据:

-- 以获取用户的登录名为例, 代码只显示注入的关键语句
and if(length(user()=0), sleep(3), 1) -- 获取用户名的长度,如果判断成功则3秒后返回
and if(hex(mid(user(), L, 1))=N,sleep(3),1) --循环比较,依次取出用户名字里的字符和ACSII码比较,如果相等则三秒后返回注入

SQL 注入的工具

  在使用语句对单个 URL 进行测试时是比较容易的,但是如果要测试的 URL 非常多的时候,就需要借助工具进行使用了,常见的 SQL 注入工具有 SQLMap, Pangolin, Havij ,下面给出相应的可以参考学习的链接。

SQLMap: https://github.com/kvko/sqlmap-wiki-zhcn

Pangolin: https://developer.aliyun.com/article/393100

Havij:https://www.hackercoolmagazine.com/sql-injection-using-havij-step-by-step-guide/

防范

  SQL 注入实际上完全是可以防范的,即使完全不知道所谓的 SQL注入,但是一个开发团队只要定义好自己的编程模板,就可以很大程度上避免这类问题的产生。例如在碰到 SQL 语句时完全采用 "PreparedStatement"类,且必须用参数绑定,这样就可以将安全问题转移到代码规范的问题上。
  SQL注入包含着很多的内容,本篇笔记只是选取了一部分内容进行介绍和说明,但是还有一大部分的内容需要大家自行去查阅和研究,也可以通过靶场进一步的提升自己的实战能力。

Reference

https://zh.wikipedia.org/zh-cn/SQL注入

《Web 安全深度剖析》

标签:语句,查询,user,SQL,select,注入
From: https://www.cnblogs.com/tjdtec/p/18137178

相关文章

  • 【MySQL】二进制安装MySQL
    【MySQL】二进制安装MySQL一、基于Ubuntu二进制安装MySQL8.0(5.7+适用)1、创建用户[root@Node-Ubuntu1804-20:~]#groupaddmysql[root@Node-Ubuntu1804-20:~]#useradd-r-gmysql-s/usr/sbin/nologinmysql2、创建目录[root@Node-Ubuntu1804-20:~]#mkdir/data/mysql......
  • C#中 控制反转IOC与依赖注入DI
    一、IOC与DI的关系IOC即控制反转,用来管理项目中对象的生命周期和依赖关系,DI依赖注入,用来实现IOC,IOC是思想,DI是实现,在项目中通常一起出现,像是A类调用B类的方法,IOC容器资源给予对应资源,有助于实现依赖倒置DIP二、DI常用的注入方式(.net的DI默认的是构造函数定义)构造函数注入:构......
  • 数据库问题排查以及SQL优化
    数据库CPU飙高通过top等命令确定是否数据库进程CPU飙高通过命令showprocesslist找出耗资源较大的SQL如果没有特别耗资源的SQL,就查看session是不是突然增多,可以通过限制连接数如果有特别耗资源的SQL,排查耗资源的SQL是否命中索引、是否表的数据量特别大kill掉这个消耗大的线程......
  • docker安装mysql8
    一、开始安装#新建挂载目录mkdir-p/opt/docker/mysql/datamkdir-p/opt/docker/mysql/confvim/opt/docker/mysql/conf/my.cnf[root@centos01mysql]#cdconf/[root@centos01conf]#lsmy.cnf[root@centos01conf]#catmy.cnf[client]default-character-set=utf8mb4[m......
  • MySQL 中 DELETE 语句中可以使用别名么?
    1情境deletefromtest1t1wherenotexists(select1fromtest2t2wheret1.id=t2.id);以上sql报错:ERROR1064(42000):YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtouse......
  • java连接ssmsSqlserver数据库 报错信息:com.microsoft.sqlserver.jdbc.SQLServerExce
    解决办法:将官网下载的驱动文件打开,找到如下路径,并复制,粘贴放到jdk的bin目录下......
  • PGSQL 问题解决
    1服务无法启动 这里更改安装目录bin下面例如E:\WorkingSoftware\PostgreSql\16\bin更改权限,下面都改下 2  安装时提示database出错,就初始化下执行以下命令E:\WorkingSoftware\PostgreSql\16\bin\pg_ctl.exe-DE:\WorkingSoftware\PostgreSql\16\dat......
  • 【知识点】常见的SQL优化手段
    问:有哪些常见的SQL优化手段?这也是个高频面试题,并且并非面试造火箭的那种问题,实际项目中也会有非常多的地方需要进行SQL优化避免使用Select*select*中,无用字段会增加网络带宽消耗,特别是varchar、blob、text等大字段select*无法使用Mysql优化器覆盖索引的优化。覆盖索......
  • Winodows安装Mysql 8.0.36 简单教程
    下载https://dev.mysql.com/downloads/mysql/选择下载简单版本即可安装1.解压将下载下来的安装包进行解压2.mysql初始化用cmd进入的mysql的解压包的bin目录里,执行初始化命令mysqld--initialize--console记录一下mysql初始化密码,备用。3.启动mysqlnetstartmy......
  • MySQL锁、事务和索引
    并发事务的控制方式是MVCC和行锁按范围分:表级锁、页锁、行级锁(锁一行或者多行)(记录索、间隙锁、临键锁(可重复读默认用这个做行锁,除非是主键和唯一索引会使用记录索))按功能分:读锁(S)、写锁(X)意向锁是表级锁,分为意向共享锁、意向排他锁,用于协调表锁和行锁的关系,事务想要在某些行上加共......