背景:

测试组搞了个“ZIP炸弹”传给后台,发现后台并没有识别,一度怀疑后台是不是偷懒了压根没有做安全校验。

于是,激动万分地给我提了个单。

排查:

阅读同事的代码,发现有做校验,步骤如下:

  1. 第一步,校验ZIP压缩包大小。
  2. 第二步,校验ZIP压缩包解压后的大小。

于是随便拿了个ZIP包本地验了一把,明明算得很准啊,一个字节都不差,是不是测试搞错了?!

再去测试组要了他们搞出来的变态ZIP包验了一把,发现校验得出的解压大小比实际小了许多。

问题:

显然,问题就出在第二步。

有个ZipUtil工具类,注释清一色地道英文,不知道原作者是哪位大神,也不知最初是谁从哪里拷过来的。

这个类提供的校验方法是通过传入ZIP文件的输入流,然后一顿字节操作猛如虎得出解压大小。计算过程涉及的变量和运算没有任何注释,看不懂啊——我摊牌了!

解决:

既然看不懂改不动,网上找替代方案吧。

很快,找到了一个方法改造一下:

/*** 计算ZIP文件的解压大小* * @param filePath 文件路径* @return 解压大小*/
public static long getUncompressedSize(String filePath) throws IOException {ZipFile zipFile = new ZipFile(filePath);long uncompressedSize = 0;Enumeration<? extends ZipEntry> entries = zipFile.entries();while (entries.hasMoreElements()) {uncompressedSize += entries.nextElement().getSize();}return uncompressedSize;
}

拿几个ZIP包验了验,发现有时候会抛异常:java.util.zip.ZipException: error in opening zip file,明明很正常的包啊,也查不出个原因,莫名其妙,无奈,再找找吧。。。

于是有了下面的方法:

/*** 计算ZIP文件的解压大小* * @param inputStream 输入流* 注:输入流由调用方负责关闭* @return 解压大小*/
public static long getUncompressedSize(InputStream inputStream) throws IOException {ZipInputStream zipInputStream = new ZipInputStream(inputStream);long uncompressedSize = 0;ZipEntry zipEntry;while ((zipEntry = zipInputStream.getNextEntry()) != null) {uncompressedSize += zipEntry.getSize();zipInputStream.closeEntry();}return uncompressedSize;
}

这回妥妥的,原来的异常不再出现了,不过还是有点小问题,因为压缩包内出现中文,导致新异常出现了:java.lang.IllegalArgumentException:MALFORMED at java.util.zip.ZipCoder.toString(ZipCoder.toString:58),好吧,还必须将编码改为GBK,再改:

/*** 计算ZIP文件的解压大小* * @param inputStream 输入流* 注:输入流由调用方负责关闭* @return 解压大小*/
public static long getUncompressedSize(InputStream inputStream) throws IOException {ZipInputStream zipInputStream = new ZipInputStream(inputStream, Charset.forName("GBK"));long uncompressedSize = 0;ZipEntry zipEntry;while ((zipEntry = zipInputStream.getNextEntry()) != null) {uncompressedSize += zipEntry.getSize();zipInputStream.closeEntry();}return uncompressedSize;
}

接着验。。。嗯?zipEntry.getSize()等于-1是什么情况?!脑壳痛,再改:

/*** 计算ZIP文件的解压大小* * @param inputStream 输入流* 注:输入流由调用方负责关闭* @return 解压大小*/
public static long getUncompressedSize(InputStream inputStream) throws IOException {ZipInputStream zipInputStream = new ZipInputStream(inputStream, Charset.forName("GBK"));long uncompressedSize = 0;ZipEntry zipEntry;while ((zipEntry = zipInputStream.getNextEntry()) != null) {long size = zipEntry.getSize();// ZipEntry的size可能为-1,表示未知if (size == -1) {ByteArrayOutputStream baos = new ByteArrayOutputStream();int bytes;while ((bytes = zipInputStream.read()) != -1) {baos.write(bytes);}uncompressedSize += baos.size();baos.close();} else {uncompressedSize += size;}zipInputStream.closeEntry();}return uncompressedSize;
}

这次可以了,可是这一个字节一个字节地读效率太慢了,绝对不能拿来主义,得再改:

/*** 计算ZIP文件的解压大小* * @param inputStream 输入流* 注:输入流由调用方负责关闭* @return 解压大小*/
public static long getUncompressedSize(InputStream inputStream) throws IOException {ZipInputStream zipInputStream = new ZipInputStream(inputStream, Charset.forName("GBK"));byte[] buffer = new byte[8*1024*1024];long uncompressedSize = 0;ZipEntry zipEntry;while ((zipEntry = zipInputStream.getNextEntry()) != null) {long size = zipEntry.getSize();// ZipEntry的size可能为-1,表示未知if (size == -1) {int len;while ((len = zipInputStream.read(buffer, 0, buffer.length)) != -1) {uncompressedSize += len;}} else {uncompressedSize += size;}zipInputStream.closeEntry();}return uncompressedSize;
}

OK,验证没问题,  合一把代码,走单。

记. ZIP炸弹防御问题相关推荐

  1. ZIP炸弹怎样反击扫描器?

    本文讲的是ZIP炸弹怎样反击扫描器?,如果你曾经维护一个网站或管理过服务器,那么你会清楚,总会人会尝试攻击你.当我在13岁时首次托管我自己的linux服务器时,我每天阅读日志,并查看每天有多少尝试连接 ...

  2. 惊爆:当Python代码遇到zip解压炸弹,未做防护的你后悔莫及!

    zip解压炸弹 在文章的开头,让我们先来介绍一下zip解压炸弹是个 什么妖怪! 解压炸弹是指解压缩后能够产生巨大的数据量的可疑压缩文件!默认设置是文件扫描中产生500MB以上解压数据的是"解 ...

  3. 数仓拉链表使用_如何用拉链炸弹捍卫您的网站

    数仓拉链表使用 This article was originally published on Christian's blog and republished here with his perm ...

  4. ZBLG:非递归zipbomb炸弹,比例为28000000:1

    分享一个有趣的工具 ZBLG:非递归zipbomb炸弹,比例为28000000:1 存储有价,数据无价,谨慎使用,请勿用于非法用途. 译文发表记录声明 版本:V1 「个站:北岸冷若冰霜」A bette ...

  5. 压缩炸弹(zipbomb)制作(附演示)

    最近看到资料有说到ZIP炸弹,主要在存在上传功能且对上传文件有解压动作的地方,如果校验不严,可能导致压缩炸弹,导致消耗CPU导致宕机 1.生成ZIP炸弹: https://github.com/Cre ...

  6. 一个42KB的文件,解压完其实是个4.5PB的“炸弹”

    你听说过 ZIP 炸弹吗? 一个很小很小的,几十 KB 的压缩过后的文件,解压以后有几百万 GB ,好像炸弹一样. 在继续介绍它之前,差评君想先问问各位都用过哪些压缩软件... WinRAR ? 或者 ...

  7. pb 数据窗口插入数据_46MB 变4.5PB 数据炸弹:新方法突破性压缩资料

    电脑文件相当多,对于不少用户的电脑来说,经常需要将一些文件进行压缩,解决空间不足的问题,Zip 就是最多人使用的格式之一,不过它亦是一把双刃剑,David Fifield制作一个内含超大量垃圾数据的z ...

  8. [转]信息安全相关理论题(三)

    21.静态分析是运行程序后进行调试? A. 对 B. 错 您的答案: 标准答案: B 22.安卓反编译后会出现$符号字节码表示是匿名内部类? A. 对 B. 错 您的答案: 标准答案: A 23.反编 ...

  9. [转]信息安全相关理论题(二)

    27.在工程实施之前,验收方可以不给施工方弱电布线图纸,但施工结束后必须有图纸 A. 对 B. 错 您的答案: 标准答案: B 28.在OSI七层协议中,提供一种建立连接并有序传输数据的方法的层是 A ...

最新文章

  1. 飞书,成就组织和个人 让每一分努力都有意义!
  2. 谷歌翻译无法连接网络_Windows无法连接网络,这几招教你解决
  3. python怎么自动中文版_Python实现AI自动版贪吃蛇
  4. kaggle机器学习作业(房价预测)
  5. 生理周期,POJ(1006)
  6. 搞懂C语言指针,看这篇就够了!
  7. 项目建立数据库初始环境脚本文件的示例
  8. 如何使用1Password,Authy和Privacy.com外包您的在线安全性
  9. Docker镜像和容器常用命令
  10. 吉士丁与新潮传媒达成亿级战略合作,打造国产奶酪新势力
  11. 灵魂拷问,SQL 查询语句先执行 SELECT吗?
  12. mybatis一次可以执行多个sql语句
  13. 制图折断线_无锡春华教育AutoCAD家具制图/机械/工程制图
  14. mongodb可视化工具robo3T的安装和使用
  15. linux 的空命令:(冒号)
  16. 【English】20190430
  17. python鼠标键盘事件代码_Python鼠标键盘事件
  18. MATLAB三维画图函数使用总结
  19. Fig (无花果)任务流水线式 多线程框架使用
  20. 计算半圆弧长及半圆的面积。(3分)

热门文章

  1. Installshield制作安装包可以设置自定义字体安装
  2. 火狐浏览器如何添加Xpath扩展
  3. 黑莓,还有多少情怀尚存?
  4. java304_HTTP 304状态码
  5. 开发登陆按钮(丛林战争项目)
  6. 欧姆龙CP1H与力士乐VFC-x610变频器通讯程序
  7. Unity3D入门第一天:初识Unity
  8. ubuntu 系统连接 xiaomi手机
  9. 抢渡长江论文matlab,模型解析及Matlab程序 抢渡长江
  10. 尚硅谷java多线程