文章目录

  • 简介
  • 在字符串标准化之后进行校验
  • 注意不可信字符串的格式化
  • 小心使用Runtime.exec()
  • 正则表达式的匹配

简介

为了保证java程序的安全,任何外部用户的输入我们都认为是可能有恶意攻击意图,我们需要对所有的用户输入都进行一定程度的校验。

本文将带领大家探讨一下用户输入校验的一些场景。一起来看看吧。

在字符串标准化之后进行校验

通常我们在进行字符串校验的时候需要对一些特殊字符进行过滤,过滤之后再进行字符串的校验。

我们知道在java中字符是基于Unicode进行编码的。但是在Unicode中,同一个字符可能有不同的表示形式。所以我们需要对字符进行标准化。

java中有一个专门的类Normalizer来负责处理,字符标准化的问题。

我们看下面一个例子:

    public void testNormalizer(){System.out.println(Normalizer.normalize("\u00C1", Normalizer.Form.NFKC));System.out.println(Normalizer.normalize("\u0041\u0301", Normalizer.Form.NFKC));}

输出结果:

Á
Á

我们可以看到,虽然两者的Unicode不一样,但是最终表示的字符是一样的。所以我们在进行字符验证的时候,一定要先进行normalize处理。

考虑下面的例子:

    public void falseNormalize(){String s = "\uFE64" + "script" + "\uFE65";Pattern pattern = Pattern.compile("[<>]"); // 检查是否有尖括号Matcher matcher = pattern.matcher(s);if (matcher.find()) {throw new IllegalStateException();}s = Normalizer.normalize(s, Normalizer.Form.NFKC);}

其中\uFE64表示的是<,而\uFE65表示的是>,程序的本意是判断输入的字符串是否包含了尖括号,但是因为直接传入的是unicode字符,所以直接compile是检测不到的。

我们需要对代码进行下面的改动:

    public void trueNormalize(){String s = "\uFE64" + "script" + "\uFE65";s = Normalizer.normalize(s, Normalizer.Form.NFKC);Pattern pattern = Pattern.compile("[<>]"); // 检查是否有尖括号Matcher matcher = pattern.matcher(s);if (matcher.find()) {throw new IllegalStateException();}}

先进行normalize操作,然后再进行字符验证。

注意不可信字符串的格式化

我们经常会使用到格式化来对字符串进行格式化,在格式化的时候如果格式化字符串里面带有用户输入信息,那么我们就要注意了。

看下面的例子:

    public void wrongFormat(){Calendar c = new GregorianCalendar(2020, GregorianCalendar.JULY, 27);String input=" %1$tm";System.out.format(input + " 时间不匹配,应该是某个月的第 %1$terd 天", c);}

粗看一下没什么问题,但是我们的input中包含了格式化信息,最后输出结果:

 07 时间不匹配,应该是某个月的第 27rd 天

变相的,我们获取到了系统内部的信息,在某些情况下面,可能会暴露系统的内部逻辑。

上面的例子我们应该将input也作为一个参数,如下所示:

    public void rightFormat(){Calendar c = new GregorianCalendar(2020, GregorianCalendar.JULY, 27);String input=" %1$tm";System.out.format("%s 时间不匹配,应该是某个月的第 %terd 天",input, c);}

输出结果:

 %1$tm 时间不匹配,应该是某个月的第 27rd 天

小心使用Runtime.exec()

我们知道Runtime.exec()使用来调用系统命令的,如果有恶意的用户调用了“rm -rf /”,一切的一切都完蛋了。

所以,我们在调用Runtime.exec()的时候,一定要小心注意检测用户的输入。

看下面的一个例子:

    public void wrongExec() throws IOException {String dir = System.getProperty("dir");Runtime rt = Runtime.getRuntime();Process proc = rt.exec(new String[] {"sh", "-c", "ls " + dir});}

上面的例子中,我们从系统属性中读取dir,然后执行了系统的ls命令来查看dir中的内容。

如果有恶意用户给dir赋值成:

/usr & rm -rf /

那么系统实际上执行的命令就是:

sh -c 'ls /usr & rm -rf /'

从而导致恶意的删除。

解决上面的问题也有几个方法,第一个方法就是对输入做个校验,比如我们只运行dir包含特定的字符:

    public void correctExec1() throws IOException {String dir = System.getProperty("dir");if (!Pattern.matches("[0-9A-Za-z@.]+", dir)) {// Handle error}Runtime rt = Runtime.getRuntime();Process proc = rt.exec(new String[] {"sh", "-c", "ls " + dir});}

第二种方法就是使用switch语句,限定特定的输入:

    public void correctExec2(){String dir = System.getProperty("dir");switch (dir){case "/usr":System.out.println("/usr");break;case "/local":System.out.println("/local");break;default:break;}}

还有一种就是不使用Runtime.exec()方法,而是使用java自带的方法。

正则表达式的匹配

在正则表达式的构建过程中,如果使用用户自定义输入,同样的也需要进行输入校验。

考虑下面的正则表达式:

(.*? +public\[\d+\] +.*<SEARCHTEXT>.*)

上面的表达式本意是想在public[1234]这样的日志信息中,搜索用户的输入。

但是用户实际上可以输入下面的信息:

.*)|(.*

最终导致正则表达式变成下面的样子:

(.*? +public\[\d+\] +.*.*)|(.*.*)

从而导致匹配所有的日志信息。

解决方法也有两个,一个是使用白名单,判断用户的输入。一个是使用Pattern.quote()来对恶意字符进行转义。

本文的代码:

learn-java-base-9-to-20/tree/master/security

本文已收录于 http://www.flydean.com/java-security-code-line-input/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

java安全编码指南之:输入校验相关推荐

  1. java密码安全验证_java安全编码指南之:输入校验

    简介 为了保证java程序的安全,任何外部用户的输入我们都认为是可能有恶意攻击意图,我们需要对所有的用户输入都进行一定程度的校验. 本文将带领大家探讨一下用户输入校验的一些场景.一起来看看吧. 在字符 ...

  2. java判断输入的格式化_java安全编码指南之:输入校验 - flydean - 博客园

    目录简介 在字符串标准化之后进行校验 注意不可信字符串的格式化 小心使用Runtime.exec() 正则表达式的匹配 简介 为了保证java程序的安全,任何外部用户的输入我们都认为是可能有恶意攻击意 ...

  3. java安全编码指南之:输入注入injection

    文章目录 简介 SQL注入 java中的SQL注入 使用PreparedStatement XML中的SQL注入 XML注入的java代码 简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下 ...

  4. java injection_java安全编码指南之:输入注入injection

    简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下java中的SQL注入和XML注入的防范. SQL注入 什么是SQL注入呢? SQL注入的意思是,用户输入了某些参数,最终导致SQL的执行偏 ...

  5. Java安全编码之用户输入

    0x00 安全引言 1.传统Web应用与新兴移动应用 (1)传统Web应用:浏览器 HTTP 服务器 (2)新兴移动应用:APP HTTP 服务器 从安全角度看,传统Web应用与新兴移动应用没有本质区 ...

  6. java安全编码指南之:堆污染Heap pollution

    简介 什么是堆污染呢?堆污染是指当参数化类型变量引用的对象不是该参数化类型的对象时而发生的. 我们知道在JDK5中,引入了泛型的概念,我们可以在创建集合类的时候,指定该集合类中应该存储的对象类型. 如 ...

  7. java安全编码指南之:字符串和编码

    文章目录 简介 使用变长编码的不完全字符来创建字符串 char不能表示所有的Unicode 注意Locale的使用 文件读写中的编码格式 不要将非字符数据编码为字符串 简介 字符串是我们日常编码过程中 ...

  8. java安全编码指南之:拒绝Denial of Service

    文章目录 简介 为什么会有DOS 不合理的资源使用 请求用于矢量图的SVG文件和字体文件 字符串或二进制表示的图片转换 zip炸弹 billion laughs attack hashMap中插入太多 ...

  9. java安全编码指南之:文件和共享目录的安全性

    文章目录 简介 linux下的文件基本权限 linux文件的特殊权限 Set UID 和 Set GID Sticky Bit SUID/SGID/SBIT权限设置 文件隐藏属性 特殊文件 java中 ...

最新文章

  1. 阿里云引入AI力量智能护航金砖会议
  2. PKI/CA (4)根CA信任模型“证书构建”
  3. java 接口的观察者模式_java观察者模式
  4. JAVA中增强循环中用线程_在Java中以循环方式运行线程
  5. 增加定时检测linux占用内存,及时清理功能
  6. 计算机史话 —— 回车和换行 与 文本文件和二进制文件
  7. 【同113】LeetCode 129. Sum Root to Leaf Numbers
  8. 机器学习中的决策树算法
  9. 2022年(第八届)全国大学生统计建模大赛
  10. 学习大数据参加培训班,大概需要多长时间?
  11. 什么情况下,英文单词中的k发音变g,t发音变d,p发音变b
  12. vim设置(非常全面),即.vimrc文件的配置
  13. FW: 10家不错的iphone编程资源站
  14. andriod studio页面跳转
  15. Leetcode 809. Expressive Words
  16. 计算机主板电感有正负极么,功率电感有没有方向?正负极区分
  17. MySQL 3306端口被占用 ERROR 1043 (08S01): Bad handshake
  18. 写给初学者的6条网页设计安全配色指南
  19. 向oracle中插入图片和读取图片
  20. ERP综合竞争力排名价值几何?

热门文章

  1. UVA307 Sticks小木棍
  2. UVA10603 倒水问题
  3. 机器学习-Stacking方法的原理及实现
  4. 二阶振荡环节的谐振频率_晶体振荡器和谐振器的区别 555压控振荡器电路图
  5. 13.IDA-显示正确的函数名称(去掉c++后缀命名)
  6. 散谈游戏保护那点事~就从_TP开始入手吧
  7. 如何获取Google地图API密钥?(翻译版)
  8. 深入理解 MySQL 索引底层原理
  9. 你了解HTTPS工作原理吗?
  10. 介绍两款Docker可视化工具