summaryrefslogtreecommitdiff
path: root/python-plugins
diff options
context:
space:
mode:
Diffstat (limited to 'python-plugins')
-rw-r--r--python-plugins/zipbomb/__init__.py2
-rw-r--r--python-plugins/zipbomb/plugin.py71
2 files changed, 73 insertions, 0 deletions
diff --git a/python-plugins/zipbomb/__init__.py b/python-plugins/zipbomb/__init__.py
new file mode 100644
index 0000000..a9d4527
--- /dev/null
+++ b/python-plugins/zipbomb/__init__.py
@@ -0,0 +1,2 @@
+
+from zipbomb.plugin import ZipBombChecker as AutoLoad
diff --git a/python-plugins/zipbomb/plugin.py b/python-plugins/zipbomb/plugin.py
new file mode 100644
index 0000000..be8c12f
--- /dev/null
+++ b/python-plugins/zipbomb/plugin.py
@@ -0,0 +1,71 @@
+
+import io
+import zipfile
+
+from pychrysalide.analysis.scan import ScanRegisteredItem
+from pychrysalide.analysis.scan.exprs import ScanLiteralExpression
+from pychrysalide.core import get_rost_root_namespace
+from pychrysalide.plugins import PluginModule
+
+
+class ZipBombKeyword(ScanRegisteredItem):
+ """Introduce a new keyword in the ROST grammar."""
+
+ _name = 'is_zip_bomb'
+
+
+ def _reduce(self, ctx, scope):
+
+ expr = None
+
+ try:
+
+ has_bomb = False
+
+ # compress < 10% plain => bomb
+ ZIP_BOMB_RATIO = 0.01
+
+ data = io.BytesIO(ctx.content.data)
+
+ zf = zipfile.ZipFile(data)
+
+ info = zf.infolist()
+
+ for i in info:
+
+ ratio = i.compress_size / i.file_size
+
+ has_bomb = ratio < ZIP_BOMB_RATIO
+
+ if has_bomb:
+ break
+
+ expr = ScanLiteralExpression(has_bomb)
+
+ except:
+ pass
+
+ return expr
+
+
+class ZipBombChecker(PluginModule):
+ """Check for ZIP bombs."""
+
+ _name = 'ZipBombChecker'
+ _desc = 'Check if a ZIP archive may contain heavy files on extraction'
+ _version = '0.1'
+ _url = 'https://www.chrysalide.re/'
+
+ _actions = ( )
+
+
+ def __init__(self):
+ """Create a ZipBombChecker plugin instance."""
+
+ super().__init__()
+
+ ns = get_rost_root_namespace()
+
+ kw = ZipBombKeyword()
+
+ ns.register_item(kw)