SQL注入防御与绕过的几种姿势

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

前言

本文章主要以后端PHP和MySQL数据库为例,参考了多篇文章后的集合性文章,欢迎大家提出个人见解,互促成长。

SQL注入

一、 PHP几种防御姿势

1. 关闭错误提示

说明:

PHP配置文件php.ini中的display_errors=Off,这样就关闭了错误提示。

2. 魔术引号

说明:

当php.ini里的magic_quotes_gpc=On时。提交的变量中所有的单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)会自动转为含有反斜线的转义字符。

魔术引号(Magic Quote)是一个自动将进入 PHP 脚本的数据进行转义的过程。(对所有的 GET、POST 和 COOKIE 数据自动运行转义)

PHP 5.4 之前 PHP 指令 magic_quotes_gpc 默认是 on。

本特性已自PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除,在PHP 5.4.O 起将始终返回 FALSE。

参考:

《magic_quotes_gpc相关说明》:

http://www.cnblogs.com/qiantuwuliang/archive/2009/11/12/1601974.html

3. addslashes

说明:

addslashes函数,它会在指定的预定义字符前添加反斜杠转义,这些预定义的字符是:单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)。

这个函数的作用和magic_quotes_gpc一样。所以一般用addslashes前会检查是否开了magic_quotes_gpc。

http://p9.qhimg.com/t01b9cc5ebd329c3951.png

magic_quotes_gpc与addslashes的区别用法:

1)对于magic_quotes_gpc=on的情况

我们可以不对输入和输出数据库的字符串数据作addslashes()和stripslashes()的操作,数据也会正常显示。

如果此时你对输入的数据作了addslashes()处理,那么在输出的时候就必须使用stripslashes()去掉多余的反斜杠。

2)对于magic_quotes_gpc=off 的情况

必须使用addslashes()对输入数据进行处理,但并不需要使用stripslashes()格式化输出,

因为addslashes()并未将反斜杠一起写入数据库,只是帮助mysql完成了sql语句的执行。

参考:

《addslashes函数说明》:

https://secure.php.net/manual/zh/function.addslashes.php

《对于magic_quotes_gpc的一点认识》:

http://www.phpfans.net/bbs/viewthread.php?tid=6860&page=1&extra=page=1

4. mysql_real_escape_string

说明:

mysql_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符。

下列字符受影响:

 
  1. \x00 
  2. \n 
  3. \r 
  4. \x1a 

如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

本扩展自 PHP5.5.0 起已废弃,并在自 PHP 7.0.0 开始被移除。

因为完全性问题,建议使用拥有Prepared Statement机制的PDO和MYSQLi来代替mysql_query,使用的是mysqli_real_escape_string

参考:

《 PHP防SQL注入不要再用addslashes和mysql_real_escape_string了》:

http://blog.csdn.net/hornedreaper1988/article/details/43520257

《PDO防注入原理分析以及使用PDO的注意事项》:

http://zhangxugg-163-com.iteye.com/blog/1835721

5. htmlspecialchars()

说明:

htmlspecialchars()函数把预定义的字符转换为 HTML实体。

预定义的字符是:

 
  1. & (和号)成为 & 
  2. " (双引号)成为 " 
  3. ' (单引号)成为 ' 
  4. < (小于)成为 &lt; 
  5. > (大于)成为 &gt; 

6. 用正则匹配替换来过滤指定的字符

 
  1. preg_match 
  2. preg_match_all() 
  3. preg_replace 

参考:

《preg_match说明》:

http://php.net/manual/zh/function.preg-match.php

《preg_replace说明》:

https://secure.php.net/manual/zh/function.preg-replace.php

7. 转换数据类型

说明:

根据「检查数据类型」的原则,查询之前要将输入数据转换为相应类型,如uid都应该经过intval函数格式为int型。

8. 使用预编译语句

说明:

绑定变量使用预编译语句是预防SQL注入的最佳方式,因为使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,攻击者无法改变SQL语句的结构,从根本上杜绝了SQL注入攻击的发生。

代码示例:

http://p6.qhimg.com/t011554d1448b3f5840.png

参考:

《Web安全之SQL注入攻击技巧与防范》:

http://www.plhwin.com/2014/06/13/web-security-sql/

二、 几种绕过姿势

下面列举几个防御与绕过的例子:

例子1:addslashes

防御:

http://p5.qhimg.com/t01bd6f0a9c2f97bc13.png

这里用了addslashes转义。

绕过:

  • 将字符串转为16进制编码数据或使用char函数(十进制)进行转化(因为数据库会自动把16进制转化)
  • 用注释符去掉输入密码部分如“-- /* #”

payload:

 
  1. http://localhost/injection/user.php?username=admin-- hack 

(因为有的SQL要求--后要有空格,所以此处加上了hack)

 
  1. http://localhost/injection/user.php?username=admin/* 

(escape不转义/*)

 
  1. http://localhost/injection/user.php?username=admin%23 

(这里的%23即为#,注释掉后面的密码部分。注意IE浏览器会将#转换为空)

 
  1. http://localhost/injection/user.php?username=0x61646d696e23 

(admin# -->0x61646d696e23)

 
  1. http://localhost/injection/user.php?username=CHAR(97,100, 109, 105, 110, 35) 

(admin# -->CHAR(97, 100, 109, 105, 110, 35))

关于编码原理:

因为一般前端JavaScript都会escape()、encodeURL或encodeURIComponent编码再传输给服务器,主要为encodeURL,如下,所以可以利用这点。

JavaScript代码如:

JavaScript代码

拦截请求:

http://p4.qhimg.com/t018cafe605b0f54abb.png

1)escape( )

对ASCII字母、数字、标点符号"@* _ + - . /"不进行编码。在\u0000到\u00ff之间的符号被转成%xx的形式,其余符号被转成%uxxxx的形式。(注意escape()不对"+"编码,而平时表单中的空格会变成+)

2) encodeURL

对" ; / ? : @ & = + $ , # ' "不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%。

3) encodeURIComponent

用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。

常用编码:  

 
  1. @ * _ + - ./ ;  \ ? : @ & = + $ , # ' 空格 

转码工具可用:

http://evilcos.me/lab/xssor/

参考:

《URL编码》:

http://www.ruanyifeng.com/blog/2010/02/url_encoding.html

例子2:匹配过滤

防御:

http://p1.qhimg.com/t011ef7d8ad83689108.png

绕过:

关键词and,or常被用做简单测试网站是否容易进行注入攻击。这里给出简单的绕过使用&&,||分别替换and,or。

  • 过滤注入: 1 or 1 = 1 1 and 1 = 1
  • 绕过注入: 1 || 1 = 1 1 && 1 = 1

关于preg_match过滤可以看参考文章,文章里讲得很详细了。

参考:

《高级SQL注入:混淆和绕过》:

http://www.cnblogs.com/croot/p/3450262.html

例子3:strstr

防御:

http://p3.qhimg.com/t01e38d15cd0ba68f9d.png

strstr ()查找字符串的首次出现,该函数区分大小写。如果想要不区分大小写,使用stristr()。(注意后面这个函数多了个i)

绕过:

strstr()函数是对大小写敏感的,所以我们可以通过大小写变种来绕过

payload:

 
  1. http://localhost/injection/user.php?id=1uNion select null,null,null 

例子4:空格过滤

防御:

http://p7.qhimg.com/t0197f1f3f7332c497a.png

绕过:

1)使用内联注释。

2)使用换行符代替空格。注意服务器若为Windows则换行符为%0A%0D,Linux则为%0A。

 
  1. http://localhost/injection/user.php?id=1/**/and/**/11=1 
  2. http://localhost/injection/user.php?id=1%0A%0Dand%0A%0D1=1 

例子5:空字节

通常的输入过滤器都是在应用程序之外的代码实现的。比如入侵检测系统(IDS),这些系统一般是由原生编程语言开发而成,比如C++,为什么空字节能起作用呢,就是因为在原生变成语言中,根据字符串起始位置到第一个出现空字节的位置来确定字符串长度。所以说空字节就有效的终止了字符串。

绕过:

只需要在过滤器阻止的字符串前面提供一个采用URL编码的空字节即可。

payload:

http://p3.qhimg.com/t010b93647c17389bbf.png

例子6:构造故意过滤

防御:

http://p9.qhimg.com/t01bb2f5ae28aa52562.png

绕过:

文件的63行开始可以看到,此处将传入的%27和%2527都进行删除处理,也就是还没传入数据库前就已经被该死的程序吃了,但是在67行看到他还吃了*,这样我们就有办法了,我们构造%*27,这样程序吃掉星号*后,%27就会被传入。

payload:    

 
  1. http://localhost/injection/user.php?id%3D1%*27%*20and%*20%*271%*27%3D%*271 

(id=1' and '1'='1-->id%3D1%*27%*20and%*20%*271%*27%3D%*271)

参考:

《phpcms_v9.6.0_sql注入与exp》:

https://zhuanlan.zhihu.com/p/26263513

作者:神月资讯
来源:51CTO

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4天前
|
SQL Web App开发 安全
【less-1】基于SQLI的SQL字符型报错注入
【less-1】基于SQLI的SQL字符型报错注入
14 2
|
4天前
|
SQL 安全 PHP
基于PHPCMS的SQL注入(Havij)
基于PHPCMS的SQL注入(Havij)
14 1
|
17天前
|
SQL 关系型数据库 MySQL
怎么通过第三方库实现标准库`database/sql`的驱动注入?
在Go语言中,数据库驱动通过注入`database/sql`标准库实现,允许统一接口操作不同数据库。本文聚焦于`github.com/go-sql-driver/mysql`如何实现MySQL驱动。`database/sql`提供通用接口和驱动注册机制,全局变量管理驱动注册,`Register`函数负责添加驱动,而MySQL驱动在`init`函数中注册自身。通过这个机制,开发者能以一致的方式处理多种数据库。
|
4天前
【干货】sql-labs、请求方式、注入类型、拼接方式
【干货】sql-labs、请求方式、注入类型、拼接方式
8 0
|
3天前
|
SQL 监控 安全
代码审计-PHP原生开发篇&SQL注入&数据库监控&正则搜索&文件定位&静态分析
代码审计-PHP原生开发篇&SQL注入&数据库监控&正则搜索&文件定位&静态分析
|
4天前
|
SQL Web App开发 前端开发
【less-11】基于SQLI的POST字符型SQL注入
【less-11】基于SQLI的POST字符型SQL注入
17 2
|
4天前
|
SQL 开发框架 安全
【干货】如何判断 Sql 注入点
【干货】如何判断 Sql 注入点
11 1
|
18天前
|
SQL 监控 安全
sql注入取数据库
SQL注入是一种攻击技术,用于在SQL查询中注入恶意代码,从而绕过安全措施,获取、修改或删除数据库中的数据。这种行为是非法的,并且严重违反了网络安全和隐私原则。我不能提供关于如何进行SQL注入的指导或
|
4天前
|
SQL 数据库
sql注入方式
sql注入方式
8 0
|
7天前
|
SQL 安全 Java
Spring Boot中的跨站点脚本攻击(XSS)与SQL注入防护
【6月更文挑战第15天】在现代Web应用程序开发中,安全性是一个至关重要的课题。跨站点脚本攻击(XSS)和SQL注入是最常见的两种攻击类型,它们可以严重威胁到应用程序的安全。
32 0