详解Javaweb中常见漏洞的防御
来源:互联网 发布:手机网络短信怎么发 编辑:程序博客网 时间:2024/05/16 06:57
上一篇给大家介绍了SpringMVC中常见的客户端数据输入点,这一篇给大家讲解下java中常见漏洞的防御方法。
0x01.sql注入
下面我们就用利用SpringMVC自带的数据库操作类jdbcTemplate举例。比如下面Dao中有如下的两个函数。
函数save使用的是绑定变量的形式很好的防止了sql注入,而queryForInt_函数接收id参数直接对sql语句进行了拼接,测试时出现sql注入。
public static void save(String username,String password) { jdbcTemplate.update("insert into test_table(user_name,password) values(?,?)", new Object[]{username,password}); }public static int queryForInt_(String id){ return jdbcTemplate.queryForInt("select count(0) from test_table where id = " + id); }#为了方便仅仅贴出了DAO层代码
所以,在java代码的开发过程中,我们尽量避免使用拼接sql语句的形式去执行数据库语句。如果需要使用拼接sql语句的形式进行数据库查询,那么OWASP提供了一个防御sql注入的Esapi包,这个包中的encodeForSQL方法能对sql注入进行很好的防御。
接着我们就分析下这个encodeForSQL方法。
首先我们介绍这个方法的使用,使用时调用如下,不同的数据库使用不到的方法。
//防止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)//防止Oracle注入的方法例子,为了方便仅仅给出sql语句的拼接部分Codec ORACLE_CODEC = new OracleCodec();String query ="SELECT user_id FROM user_data WHERE user_name = ‘"+ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("userID"))+"’ and user_password = ‘"+ESAPI.encoder().encodeForSQL(ORACLE_CODEC,req.getParameter("pwd"))+"’";
下面我们就用mysql为例字分析encodeForSQL函数做了什么防御。具体函数过程就不跟踪了,直接分析最后调用了哪个方法。根据代码可知最后调用的是encodeCharacter方法。
public String encodeCharacter( char[] immune, Character c ) {char ch = c.charValue();// check for immune charactersif ( containsCharacter( ch, immune ) ) {return ""+ch;}// check for alphanumeric charactersString hex = Codec.getHexForNonAlphanumeric( ch );if ( hex == null ) {return ""+ch;}switch( mode ) {case ANSI: return encodeCharacterANSI( c );case STANDARD: return encodeCharacterMySQL( c );}return null;}
上述方法中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; }
我们介绍了利用绑定变量和利用esapi两种方式对sql注入进行防御,我的建议是尽量使用绑定变量的是形式进行防注入,安全性能都比较好。
0x02:跨站脚本攻击
关于跨站脚本攻击的防御,我们分析esapi的防御方式。
esapi的防御方式是根据输出点的不同在不同的输出点进行相应的编码。我们看一下使用方法:
xss输出点在html网页中ESAPI.encoder().encodeForHTML(String input)xss输出点在html属性中ESAPI.encoder().encodeForHTMLAttribute(String input)xss输出点在JavaScript代码中ESAPI.encoder().encodeForJavaScript(String input)xss输出点在CSS代码中ESAPI.encoder().encodeForCSS(String input)xss输出点在VBScript代码中ESAPI.encoder().encodeForVBScript(String input)xss输出点在XPath中ESAPI.encoder().encodeForXPath(String input)xss输出点在XML中ESAPI.encoder().encodeForXML(String input)xss输出点在XML属性中ESAPI.encoder().encodeForXMLAttribute(String input)直接对url进行URL编码ESAPI.encoder().encodeForURL(String input)
如果java输出在html页面,使用如下示例的方法即可。
String username = ESAPI.encoder().encodeForHTML(req.getParameter("name"))
接下来我们就研究这个方法的具体实现。
public String encodeCharacter( char[] immune, Character c ) { // check for immune characters if ( containsCharacter(c, immune ) ) { return ""+c; } // check for alphanumeric characters String hex = Codec.getHexForNonAlphanumeric(c); if ( hex == null ) { return ""+c; } // check for illegal characters //ascii码中的非数字,字符的编码,一般为非打印字符,即不能转换的为uncoide的ascii字符,直接替换成\ufffd,显示的为? if ( ( c <= 0x1f && c != '\t' && c != '\n' && c != '\r' ) || ( c >= 0x7f && c <= 0x9f ) ) { hex = REPLACEMENT_HEX; // Let's entity encode this instead of returning it c = REPLACEMENT_CHAR; } // check if there's a defined entity //#恶意字符以实体的形式输出 String entityName = (String) characterToEntityMap.get(c); if (entityName != null) { return "&" + entityName + ";"; } // return the hex entity as suggested in the spec,#如果是16进制就转换为html16进制实体字符输出 return "&#x" + hex + ";"; }
containsCharacter函数一般定义不需要编码的字符,如果我们不想编码那个字符就可以利用这个函数定义。
Codec.getHexForNonAlphanumeric函数判断是否是数字和字母,如果仅仅是字符和字母就直接返回,不在编码。
剩下的代码是对非数字和字母的字符进行实体编码或者html十六进制字符编码。
如果java输出在js代码页面,使用如下示例的方法即可。
String username = ESAPI.encoder().encodeForJavaScript(req.getParameter("name"))我们研究一下encodeForJavaScript方法:
public String encodeCharacter( char[] immune, Character c ) { // check for immune characters if ( containsCharacter(c, immune ) ) { return ""+c; } // check for alphanumeric characters String hex = Codec.getHexForNonAlphanumeric(c); if ( hex == null ) { return ""+c; } // Do not use these shortcuts as they can be used to break out of a context // if ( ch == 0x00 ) return "\\0"; // if ( ch == 0x08 ) return "\\b"; // if ( ch == 0x09 ) return "\\t"; // if ( ch == 0x0a ) return "\\n"; // if ( ch == 0x0b ) return "\\v"; // if ( ch == 0x0c ) return "\\f"; // if ( ch == 0x0d ) return "\\r"; // if ( ch == 0x22 ) return "\\\""; // if ( ch == 0x27 ) return "\\'"; // if ( ch == 0x5c ) return "\\\\"; // encode up to 256 with \\xHH,编码成js十六进制的形式 String temp = Integer.toHexString(c); if ( c < 256 ) { String pad = "00".substring(temp.length() ); return "\\x" + pad + temp.toUpperCase(); } // otherwise encode with \\uHHHH,编码成jsunicode编码格式 String pad = "0000".substring(temp.length() ); return "\\u" + pad + temp.toUpperCase(); }
恶意字符在js中的编码大家可以看到使用的是js的十六进制编码或者jsunicode编码进行的编码。
其实上面的方法大都是对字符进行html实体编码,html十六进制编码,js十六进制编码,jsunicode的编码和url编码来防止恶意标签的执行。如果感兴趣可以看一下其他的编码方法,原理大致相同就不在一一介绍。
- 详解Javaweb中常见漏洞的防御
- 详解Javaweb中常见漏洞的防御二
- 移动App中常见的Web漏洞
- JavaWeb中常见的乱码处理(亲测)
- javaweb中Filter(过滤器)的常见应用
- NetBIOS 漏洞的入侵与防御
- Android LaunchAnyWhere (Google Bug 7699048)漏洞详解及防御措施
- 常见的编辑器漏洞
- 常见的网站漏洞
- 常见的网站漏洞
- 常见的JavaWEB服务器
- C语言编程中常见的漏洞原因
- CSRF漏洞和防御
- 常见的Web攻击和防御总结
- 互联网常见的攻击与防御
- 常见的web安全问题及防御
- 常见的Web攻击和防御总结
- WEB开发中一些常见的攻击方式及简单的防御方法
- 上海 交通卡退卡规则,余额给退吗
- 超级会员红钻联合活动
- 免费正规发票?教你如何免费开发票教程_
- Ubuntu从入门到精通 ubuntu如何设置和打开3D效果桌面
- 另类加法
- 详解Javaweb中常见漏洞的防御
- Java基本数据类型总结
- Shuttle Puzzle
- Android百度地图例子
- 统一iOS里的警示框
- ubuntu16.0.4 安装 jdk、Android Studio、Android Sdk、Genymotion
- 浅谈ORACLE SQL语句优化经验
- android view
- xcode7.3自动补全失效解决办法