java web sql注入测试(3)---现象分析

时间:2023-12-10 23:28:02

那为什么出现以上问题呢?这是程序代码层控制不当导致的。如果web前端对输入数据控制严格,会对数据库进行操作的字符串,在客户端做敏感字符转义处理,或者在操作数据库的dao层,使用动态参数的sql,不使用拼接方式的sql,都可以防止该类问题的发生。

一般情况,如果测试人员了解dao层的具体设计,如果使用的就是非拼接方式的,基本是可以拦截大部分这些存在问题的sql了。而如果使用的是拼接方式,就可以好好的设计测试用例,进行测试了。

那又为什么非拼接方式就可以有效的防止SQL注入测试呢?

修改上部分核心代码块,采用动态sql(预编译sql方式):

String hql="delete from Department where name=?";

Query query = session.createQuery(hql);

query.setString(0, name);

同样输入的代码存在问题:

可是结果却没有删除。为什么呢?

因为在setString方法中实现了对字符串中敏感字符的转义。Jdk提供PreparedStatemen接口,在mysql的jar包中,PreparedStatement实现了jdk中的PreparedStatement,里面的setString方法如下:

  1. public void setString(int parameterIndex, String x) throws SQLException {
  2. // if the passed string is null, then set this column to null
  3. if (x == null) {
  4. setNull(parameterIndex, Types.CHAR);
  5. else {
  6. StringBuffer buf = new StringBuffer((int) (x.length() * 1.1));
  7. buf.append('\'');
  8. int stringLength = x.length();
  9. //
  10. // Note: buf.append(char) is _faster_ than
  11. // appending in blocks, because the block
  12. // append requires a System.arraycopy()....
  13. // go figure...
  14. //
  15. for (int i = 0; i < stringLength; ++i) {
  16. char c = x.charAt(i);
  17. switch (c) {
  18. case 0: /* Must be escaped for 'mysql' */
  19. buf.append('\\');
  20. buf.append('0');
  21. break;
  22. case '\n': /* Must be escaped for logs */
  23. buf.append('\\');
  24. buf.append('n');
  25. break;
  26. case '\r':
  27. buf.append('\\');
  28. buf.append('r');
  29. break;
  30. case '\\':
  31. buf.append('\\');
  32. buf.append('\\');
  33. break;
  34. case '\'':
  35. buf.append('\\');
  36. buf.append('\'');
  37. break;
  38. case '"': /* Better safe than sorry */
  39. if (this.usingAnsiMode) {
  40. buf.append('\\');
  41. }
  42. buf.append('"');
  43. break;
  44. case '\032': /* This gives problems on Win32 */
  45. buf.append('\\');
  46. buf.append('Z');
  47. break;
  48. default:
  49. buf.append(c);
  50. }
  51. }
  52. buf.append('\'');
  53. String parameterAsString = buf.toString();
  54. byte[] parameterAsBytes = null;
  55. if (!this.isLoadDataQuery) {
  56. parameterAsBytes = StringUtils.getBytes(parameterAsString,
  57. this.charConverter, this.charEncoding, this.connection
  58. .getServerCharacterEncoding(), this.connection
  59. .parserKnowsUnicode());
  60. else {
  61. // Send with platform character encoding
  62. parameterAsBytes = parameterAsString.getBytes();
  63. }
  64. setInternal(parameterIndex, parameterAsBytes);
  65. }
  66. }

Hql进行动态参数绑定也存在很多种其他方法:按参数名称绑定,按参数位置绑定, setParameter()方法等等。http://baike.baidu.com/link?url=NKt6I-Gk0HnyFRWyZ0_ZuDe0pz_aDqVul-VDJZCDCGl9K5LsBghBfxhPVJmZh9qmBKtXgY2EqAqK1oQUNK2Su_