Japan
サイト内の現在位置
CVE-2007-4559(Pythonのtarfileモジュールに対するディレクトリトラバーサル)についての考察
NECセキュリティブログ2022年10月11日
CVE-2007-4559の概要
CVE-2007-4559 [3]は、Pythonのtarfileモジュールのextract関数とextractall関数に含まれるディレクトリトラバーサルの脆弱性です。tarアーカイブ内のファイル名(パス)に”../”を含めることで攻撃者が任意のファイルを指定できます。本ブログの執筆時点(2022年10月3日)において、このCVE-2007-4559の脆弱性は修正されておらずそのまま残り続けていることをTrellix社が発見しました。本件に関してTrellix社が公開している記事
[4]では、技術的な詳細について記載があり悪用が容易であることが指摘されています。また、何十万ものリポジトリがこの脆弱性に対して脆弱であると同記事で述べられており、影響範囲の広さを表しています。
/etc/passwdの上書きを例にtarfileモジュールのextractall関数の動作を以下に示します。
-
上書き前の/etc/passwdの内容を確認します。
- 各ユーザーの情報が確認できます。
root@421636302b62:/tmp# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
(省略) -
“../”をファイル名(パス)に含むtarアーカイブを作成します。
- etc/passwdの前に”../”が付与されていることが確認できます。
root@421636302b62:/tmp# tar tvfP untrusted.tar
-rw-rw-r-- root/root 30 2022-09-29 07:15 ../../../../../../etc/passwd -
tarfileモジュールのextractall関数でtarアーカイブを解凍するスクリプトを作成します。
root@421636302b62:/tmp# cat extract.py
import tarfile
import sys
def extract(filename):
with tarfile.open(filename, "r") as tar:
tar.extractall() -
2.で作成したtarアーカイブを3.で作成したスクリプトにより展開します。
root@421636302b62:/tmp# python3 extract.py untrusted.tar
-
/etc/passwdの内容を確認します。
- /etc/passwdが上書きされていることが確認できます。
root@421636302b62:/tmp# cat /etc/passwd
overwritten by tarfile module!!!
CVE-2007-4559の検出ツールCreosote
本節ではTrellix社より公開されているCVE-2007-4559の検出ツールCreosote [5]を紹介します。Creosoteは、Apache-2.0ライセンスで使用できます。
使用例は以下となります。
$ git clone https://github.com/advanced-threat-research/Creosote
$ python3 Creosote/creosote.py vuln_tar
(省略)
Starting scan of:vuln_tar/
Scanning for Vulnerabilities:
Scan Completed
1 files with vulns: 1 vulns, 0 probable vulns, and 0 potential vulns found
vuln_tar/untar.py
Found vulns on lines: 6
検査対象のディレクトリを引数としてPythonプログラムを実行するだけなので使用は簡単です。結果として脆弱性を含むファイルと該当行番号を表示されます。
CVE-2007-4559の対策
CVE-2007-4559はtarアーカイブ内のファイル名(パス)に”../”を含めることで悪用されます。そのため、tarアーカイブからファイルを展開する前にファイル名(パス)に”../”が含まれていないかを検証することが対策となります。2007年にgithubのissueの中でtarfileモジュールの修正サンプルコードが投稿されています [6]
[7]。その中でファイル名(パス)の検証方法が参考になります。
このサンプルコードでは_check_pathという関数でファイル名(パス)を検証しています。ユーザー側でtarファイルを展開する前にtarinfoオブジェクト [8]からファイル名を取得して以下の関数で各ファイル名を検証することで不正なファイルの展開を防ぐことができます。
+ def _check_path(self, path):
+ """Raise an SecurityError if `path' is an insecure pathname.
+ """
+ path = normpath(path)
+ if path.startswith("/"):
+ raise SecurityError("found insecure absolute path %r" % path)
+ if path.startswith("../"):
+ raise SecurityError("found insecure relative path %r" % path)
CVE-2007-4559の修正が適用されなかった経緯

結論としては、「セキュリティの問題とは考えていない。pax定義、そしてPOSIXのパス名解決ガイドラインに従った動作である。」と述べています。また、「ドキュメントに信頼できない配信元からのアーカイブの展開は危険であると注意書きを追記する」としています。公式のドキュメント [10]を確認すると以下の注意書きを確認できます。

この結論に対して、報告者は「それが公式のスタンスと考えるなら、それでよい。」としてissueはクローズされています。

開発者はtarアーカイブの展開の動作は規格に従った動作であり、展開前のアーカイブの検査はユーザー責任で行うことを求めているように読み取れます。
誰がどこまでアーカイブを検査するかは明確に決められていないため、モジュールがどこまで検査してくれるかは注意しなければなりません。
開発者の「規格に則った仕様である」というスタンスは理解できますが、実際に問題のあるリポジトリが多く検出されているので検証機能の追加は必要と考えます。互換性の問題もあるため、既定の動作は変えられないかもしれませんが、必要に応じてユーザーが検証機能を有効にできるとよいです。
tarfileモジュールでのtarアーカイブの検証については、議論はされています [11]。今後、検証機能が追加されるかもしれませんが、現状はユーザー側でアーカイブを検証する必要があります。GNU tar
[12]では、tarアーカイブの展開の際のセキュリティについて記載されています。このようなドキュメントを参考にしながら対応を検討するのがよいと考えます。
さいごに
今回はCVE-2007-4559の概要、検出ツール、対策、問題が修正されなかった経緯ついて紹介しました。検出ツールが公開されているので、脆弱性に該当する箇所がないか検査することを推奨します。
参考
- [1]Unpatched 15-year old Python bug allows code execution in 350k projects
https://www.bleepingcomputer.com/news/security/unpatched-15-year-old-python-bug-allows-code-execution-in-350k-projects/
- [2]Pythonの15年間見過ごされてきた脆弱性が30万件以上のオープンソースリポジトリに影響を与える可能性
https://gigazine.net/news/20220922-python-old-bug-unpatched-15-years/
- [3]NVD - CVE-2007-4559
https://nvd.nist.gov/vuln/detail/CVE-2007-4559
- [4]Tarfile: Exploiting the World With a 15-Year-Old Vulnerability
https://www.trellix.com/en-us/about/newsroom/stories/research/tarfile-exploiting-the-world.html
- [5]
- [6]tarfile insecure pathname extraction #45385
https://github.com/python/cpython/issues/45385
- [7]insecure_pathnames.diff
https://bugs.python.org/file8339/insecure_pathnames.diff
- [8]tarfile — Read and write tar archive files — Python 3.10.7 documentation
https://docs.python.org/3.10/library/tarfile.html#tarinfo-objects
- [9][Python-Dev] tarfile and directory traversal vulnerability
https://mail.python.org/pipermail/python-dev/2007-August/074290.html
- [10]tarfile — Read and write tar archive files —; Python 3.10.7 documentation
https://docs.python.org/3.10/library/tarfile.html
- [11][Security] CVE-2007-4559: tarfile: Add absolute_path option to tarfile, disabled by default #73974
https://github.com/python/cpython/issues/73974
- [12]
執筆者プロフィール
岩川 健人(いわかわ けんと)
セキュリティ技術センター リスクハンティング・アナリシスグループ
高性能計算(HPC)分野のソフトウェア開発業務を経て、現在はペネトレーションテスト、脆弱性診断などに従事。
SANS SEC575 メダルを保持。
CISSP/情報処理安全確保支援士(RISS) /情報処理技術者試験(NW,DB,ES)/GIAC GREM/AWS認定(SAA,SCS)を保持。

執筆者の他の記事を読む
アクセスランキング