文章目录

  • 简介
  • 为什么会有DOS
  • 不合理的资源使用
    • 请求用于矢量图的SVG文件和字体文件
    • 字符串或二进制表示的图片转换
    • zip炸弹
    • billion laughs attack
    • hashMap中插入太多相同hashcode的元素
    • 正则表达式悲观回溯
    • 序列化和序列化
    • 大量的输出日志
    • 无限循环
    • 使用第三方jar包
    • Xpath攻击
    • 释放所有资源

简介

DOS不是那个windows的前身,而是Denial of Service,有做过系统安全方面的小伙伴可能对这个再熟悉不过了,简单点讲,DOS就是服务型响应不过来,从而拒绝了正常的服务请求。

今天本文不是要讲怎么发起一个DOS攻击,而是讲一下怎么在java的代码层面尽量减少DOS的可能性。

为什么会有DOS

为什么会有DOS呢?排除恶意攻击的情况下,DOS的原因就是资源的使用不当。一般意义上我们所说的资源有CPU周期,内存,磁盘空间,和文件描述符等。

如果这些资源受到了恶意使用,那么很有可能会影响正常的系统服务响应,从而产生DOS。

怎么在编码层面上,解决DOS问题呢?

不合理的资源使用

如果系统有不合理的资源使用的话,就会造成资源紧缺,从而会产生问题。我们这里举一些不合理使用资源的例子。

请求用于矢量图的SVG文件和字体文件

SVG (全称是 Scalable Vector Graphics) 是一个跟分辨率无关的图形格式。因为SVG是基于XML的,并且保存着大量的复杂路径信息,所以它的体积一般比较大。我们在使用的时候要考虑。

同时如果使用大量的字体文件也会加重系统的资源负担。

字符串或二进制表示的图片转换

图片是一个文件,文件就可以使用二进制来表示,同样的如果我们把二进制进行base64编码就得到了图片的字符串表示。

如果使用过webpack进行前端项目构建的同学应该知道,对于项目中的小图像,一般是将其编码成为字符串直接嵌套在html中的。但是对于大图片,还是保存的原来的格式。

如果我们在后台对字符串或者二进制表示的图片进行转换的时候,可能会需要几倍于原image大小的内存。

看一个imageToBase64的例子:

public String imageToBase64() {File f = new File("/tmp/abc.jpg");try {BufferedImage bi = ImageIO.read(f);ByteArrayOutputStream baos = new ByteArrayOutputStream();ImageIO.write(bi, "jpg", baos);byte[] bytes = baos.toByteArray();return encoder.encodeBuffer(bytes).trim();} catch (IOException e) {e.printStackTrace();}return null;}

zip炸弹

为了提升数据传输的效率,很多时候我们都会使用压缩算法,比如在HTTP中。但是一个压缩过的很小的zip文件,解压之后可能会变得非常非常大。

这里给大家介绍一个非常有名的zip炸弹。

42.zip 是很有名的zip炸弹。它的大小只有42KB,但是解压之后居然有4.5PB之多。

怎么做的呢?

一个zip文件中又包含了16个zip文件,每一个zip文件又包含了16个zip文件,这样循环5次,产生了16的5次方个文件,每个文件的大小是4.3GB,最后导致你的硬盘爆炸了。

感兴趣的朋友可以从http://www.unforgettable.dk/42.zip 下载,自己尝试一下。

怎么避免zip炸弹呢?

第一种做法在解压过程中检测解压过后的文件大小,如果超出一定的限制就结束解压。

另一种做法,就是判断压缩文件中是否还有压缩文件,尽量减少这种压缩套压缩的做法。

billion laughs attack

billion laughs attack是解析XML文件产生的DOS攻击。

先上代码:

<?xml version="1.0"?>
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)><!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"><!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

上面的代码定义了10个entities,每个entity又包含了10个前面定义的entity,从而实现了指数级的字符串增长。最后生成了包含10亿个字符串的xml文件。

一般情况下,我们会将xml放在内存中保存,这么多的字符串最后会耗尽我们的内存,最终导致DOS。

我们可以通过设置 XMLConstants.FEATURE_SECURE_PROCESSING 来防止这种攻击。

hashMap中插入太多相同hashcode的元素

我们知道java中hashMap是用分离链表来处理hash冲突的,如果插入了太多相同hashcode的元素,就会导致这个hashcode对应的链表变得很长,从而查询效率降低,影响程序性能。

正则表达式悲观回溯

什么是悲观回溯呢?

我们举个例子,假如大家对正则表达式已经很熟悉了。

假如我们使用/^(x*)y$/ 来和字符串xxxxxxy来进行匹配。

匹配之后第一个分组(也就是括号里面的匹配值)是xxxxxx。

如果我们把正则表达式改写为 /^(x*)xy$/ 再来和字符串xxxxxxy来进行匹配。 匹配的结果就是xxxxx。

这个过程是怎么样的呢?

首先(x*)会尽可能的匹配更多的x,知道遇到字符y。 这时候(x*)已经匹配了6个x。

接着正则表达式继续执行(x*)之后的xy,发现不能匹配,这时候(x*)需要从已经匹配的6个x中,吐出一个x,然后重新执行正则表达式中的xy,发现能够匹配,正则表达式结束。

这个过程就是一个回溯的过程。

如果正则表达式写的不好,那么就有可能会出现悲观回溯。

还是上面的例子,但是这次我们用/^(x*)y$/ 来和字符串xxxxxx来进行匹配。

按照上面的流程,我们知道正则表达式需要进行6次回溯,最后匹配失败。

考虑一些极端的情况,可能会导致回溯一个非常大的次数,从而导致CPU占用率飙升。

序列化和序列化

我们将java对象存进文件或者进行网络传输的时候,都需要使用到序列化和反序列化。

如果我们在对一个java对象进行反序列化的时候,很可能就会加载恶意代码。

因此我们需要在反序列化的时候进行住够的安全控制。

大量的输出日志

通常我们为了调试程序或者寻找问题都会输出大量的日志,如果日志文件太大会影响到磁盘空间的使用。

同时,日志写入操作也会对同一个硬盘上的其他写入操作产生影响。所以日志输出要抓住重点。

无限循环

在使用循环的时候一定要注意,不要产生无限循环的情况。

使用第三方jar包

现代的java程序都会使用第三方jar包,但是第三方jar包的安全性还是需要我们注意的。如果某些第三方jar包中包含有恶意代码,那么会对我们的系统造成非常严重的影响。

Xpath攻击

XPath 解析器是用来解析XML结构的工具,但是在使用XPath 解析器的时候,我们需要注意防止注入攻击。

举个例子:

<users><user><name>张三</name><username>zhangsan</username><password>123</password></user><user><name>李四</name><username>lisi</username><password>456</password></user>

如果使用xpath,我们需要这样来验证一个用户是否存在:

//users/user[username/text()='lisi'and password/text()='456']

如果用户传入username = ‘lisi’ 和 password = ‘456’, 那么可以匹配成功,证明用户存在。

但是如果用户输入类似 ’ or 1=1 or ‘’=’ 的值,我们看下xpath的解析结果:

//users/user[username/text()=''or 1=1 or ''='' and password/text()='' or 1=1 or ''='']

结果产生和SQL注入一样的结果。

释放所有资源

通常来说,我们在进行文件操作,锁获取操作的的时候会申请相应的资源,在使用完这些资源过后,千万要记得释放他们。

在JDK7 之后,引入了try with表达式,我们可以将要释放的资源放入try语句内,在程序执行完毕,资源会自动释放。

举个例子:

public R readFileBuffered(InputStreamHandler handler) throws IOException {try (final InputStream in = Files.newInputStream(path)) {handler.handle(new BufferedInputStream(in));}}

上面的InputStream会自动释放。

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

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

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

java安全编码指南之:拒绝Denial of Service相关推荐

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

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

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

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

  3. java安全编码指南之:Mutability可变性

    文章目录 简介 可变对象和不可变对象 创建mutable对象的拷贝 为mutable类创建copy方法 不要相信equals 不要直接暴露可修改的属性 public static fields应该被置 ...

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

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

  5. java安全编码指南之:异常处理

    简介:异常是java程序员无法避免的一个话题,我们会有JVM自己的异常也有应用程序的异常,对于不同的异常,我们的处理原则是不是一样的呢? 一起来看看吧. 简介 异常是java程序员无法避免的一个话题, ...

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

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

  7. java安全编码指南之:序列化Serialization

    文章目录 简介 序列化简介 注意serialVersionUID writeObject和readObject readResolve和writeReplace 不要序列化内部类 如果类中有自定义变量 ...

  8. java安全编码指南之:文件IO操作

    文章目录 简介 创建文件的时候指定合适的权限 注意检查文件操作的返回值 删除使用过后的临时文件 释放不再被使用的资源 注意Buffer的安全性 注意 Process 的标准输入输出 InputStre ...

  9. java安全编码指南之:线程安全规则

    文章目录 简介 注意线程安全方法的重写 构造函数中this的溢出 不要在类初始化的时候使用后台线程 简介 如果我们在多线程中引入了共享变量,那么我们就需要考虑一下多线程下线程安全的问题了.那么我们在编 ...

最新文章

  1. IPython 8.0大版本更新:Debug报错提示更清晰,加入自动代码补全
  2. 任务切换的基础:模拟任务切换时寄存器的保存与恢复
  3. 打开MSN提示Windows Live Communication Platform遇到问题需要关闭错误的解决方法
  4. 存储过程 SQL server(01)
  5. Windows XP SP3支持多用户远程桌面连接
  6. hive窗口函数_Hive sql窗口函数源码分析
  7. Linux模拟超级终端minicom(二)
  8. 调取百度地图接口,实现取自己的实时位置,然后可以在百度地图上添加信息标注...
  9. Ubuntu系统下实时监控GPU的温度
  10. 图论算法——加权有向图的数据结构
  11. 空间目录Tomcat ShutDown出现 Insufficient space for shared memory file:
  12. Caffe学习:pycaffe利用caffemodel进行分类(2)
  13. Visual Studio 2012下载安装方法
  14. [转载]追求代码质量: 使用 TestNG-Abbot 实现自动化 GUI 测试
  15. excel html 颜色,excel怎么设置鼠标横竖颜色
  16. wps怎么做文档分享
  17. 伯努利分布、二项分布和多项分布
  18. 银河麒麟高级服务器操作系统V10——安装Tuxedo12
  19. OC 建议实现类似淘宝的物流步骤视图
  20. 学ios 需要学html5me,针对iOS平台移植Flash内容的指导教程(1)

热门文章

  1. (十一)boost库之多线程间通信
  2. 【玩转cocos2d-x之三十五】Earth Warrior 3D大揭秘
  3. cocos2d-x初探学习笔记(17)--瓦片地图集
  4. Python 找出一个整数数组中,第二大的数。
  5. 这 24 个高频存储问题,你一定要知道
  6. 每日一题之 MySQL
  7. 分布式链路跟踪中的 traceid 和 spanid 代表什么?
  8. 如何使用下一代编码技术提升流媒体体验
  9. LiveVideoStack线上分享第三季(十一):Xilinx视频解决方案
  10. 2018收官蓉城,探秘多媒体开发新趋势