常见漏洞防御 之 防 SQL 注入的三种方式

本贴最后更新于 2962 天前,其中的信息可能已经时移世易

看以下三种SQL语句

String sql1 = "select * from user where username = '"+username+"' and password = '"+password+"'";
String sql2 ="select * from user where username = :username and password = :password"; String sql3 = "select * from user where username = ? and password = ?";</pre>

 

推荐写法是sql2、sql3使用的别名或者通配符的形式进行传值,可以避免SQL注入,sql1就有了常见的典型SQL注入问题,假设username随便传个值,比如'张三',传入的password的值为  

 '  or 1 = 1' 则 拼接的SQL语句成了 

select * from user where username ='张三' and password = '' or 1 = 1 ''

很明显无论前面的and为真还是假,只要or后面为真,则就可使查询为true,导致SQL注入 所以尽可能避免字符串拼接的形式进行SQL传值,但有些场景可能必须采用字符串拼接的形式,比如Mybatis在按要求排序时:

order by #{order} #{sort}

用#{}的形式取值就相当于字符串拼接,但是因为排序DESC、AESC这种是SQL关键字,不能进行转义,所以就必须采用字符串拼接的形式了

如果采用这种形式还要避免SQL注入的话,就需要对传入的值进行SQL过滤,来避免SQL注入

那么OWASP提供了一个防御sql注入的Esapi包,这个包中的encodeForSQL方法能对sql注入进行很好的防御。

//防止Oracle注入  
ESAPI.encoder().encodeForSQL(new OracleCodec(),queryparam)  
//防止mysql注入  
ESAPI.encoder().encodeForSQL(new MySQLCodec(Mode.STANDARD),queryparam) //Mode.STANDARK为标准的防注入方式,mysql一般用使用的是这个方式  
//防止DB2注入  
ESAPI.encoder().encodeForSQL(new DB2Codec(),queryparam) 

使用不同的数据库,使用的过滤方法不同

下面我们就用MySQL为例字分析encodeForSQL函数做了什么防御。具体函数过程就不跟踪了,直接分析最后调用了哪个方法。根据代码可知最后调用的是encodeCharacter方法。

 

public String encodeCharacter( char[] immune, Character c ) {  
        char ch = c.charValue();
// check for immune characters if ( containsCharacter( ch, immune ) ) { return ""+ch; } // check for alphanumeric characters String hex = Codec.getHexForNonAlphanumeric( ch ); if ( hex == null ) { return ""+ch; } switch( mode ) { case ANSI: return encodeCharacterANSI( c ); case STANDARD: return encodeCharacterMySQL( c ); } return null; } </pre>

 

上述方法中containsCharacter函数是不进行验证的字符串白名单,Codec.getHexForNonAlphanumeric函数查找字符传中是否有16进制,没有返回空值。

 

而encodeCharacterANSI和encodeCharacterMySQL才是防御的重点,我们看一下这两个函数的不同,如果选择的我们选择是Mode.ANSi模式,则字符串则进入下面的函数,可以看到这个函数对单撇号和双撇号进行了转义。

 

private String encodeCharacterANSI( Character c ) {  
    if ( c == '\'' )  
        return "\'\'";  
    if ( c == '\"' )  
        return "";  
    return ""+c;  
}  

 

如果选择的是Mode.STANDARD模式,则字符串则进入下面的函数,可以看到这个函数对单撇号和双撇号、百分号、反斜线等更多的符号进行了转换,所以使用时推荐使用标准模式。

 

private String encodeCharacterMySQL( Character c ) {  
    char ch = c.charValue();  
    if ( ch == 0x00 ) return "\\0";  
    if ( ch == 0x08 ) return "\\b";  
    if ( ch == 0x09 ) return "\\t";  
    if ( ch == 0x0a ) return "\\n";  
    if ( ch == 0x0d ) return "\\r";  
    if ( ch == 0x1a ) return "\\Z";  
    if ( ch == 0x22 ) return "\\\"";  
    if ( ch == 0x25 ) return "\\%";  
    if ( ch == 0x27 ) return "\\'";  
    if ( ch == 0x5c ) return "\\\\";  
    if ( ch == 0x5f ) return "\\_";  
    return "\\" + c;  
}  

 

写个单元测试:

@org.junit.Test
	public void testESAPI() {
		String username = "zhangsan";
		String password = "' or 1=1'";
String sql1 = "select * from user where username = '"+username+"' and password = '"+password+"'";

// String sql2 ="select * from user where username = :username and password = :password";
// String sql3 = "select * from user where username = ? and password = ?";
System.out.println("过滤前:"+sql1);

username = ESAPI.encoder().encodeForSQL(new MySQLCodec((Mode.STANDARD)), username); password = ESAPI.encoder().encodeForSQL(new MySQLCodec((Mode.STANDARD)), password); sql1 = "select * from user where username = '"+username+"' and password = '"+password+"'"; System.out.println("过滤后:"+sql1); }</pre>

 

SQL注入

 

我们介绍了利用绑定变量、通配符和利用esapi三种方式对sql注入进行防御,我的建议是尽量使用绑定变量或者通配符的是形式进行防注入,安全性能都比较好,如果不得不使用字符串拼接的形式,则使用esapi进行sql过滤

最后给个esapi的maven支持形式

	<dependency>
			<groupId>org.owasp.esapi</groupId>
			<artifactId>esapi</artifactId>
			<version>2.1.0.1</version>
		</dependency>

 

 

 

 

 

  • SQL
    128 引用 • 390 回帖 • 3 关注
  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 646 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    28 引用 • 197 回帖 • 32 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    57 引用 • 25 回帖 • 2 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 4 关注
  • 音乐

    你听到信仰的声音了么?

    62 引用 • 512 回帖
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 28 关注
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    345 引用 • 742 回帖 • 1 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    16 引用 • 236 回帖 • 266 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    88 引用 • 139 回帖 • 1 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 504 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    99 引用 • 367 回帖
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 678 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 628 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 27 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 1 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    693 引用 • 537 回帖
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 608 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    410 引用 • 3588 回帖
  • 996
    13 引用 • 200 回帖 • 2 关注
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 104 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 702 关注
  • danl
    165 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 648 关注