• R/O
  • SSH
  • HTTPS

hamigaki: 提交


Commit MetaInfo

修訂1782 (tree)
時間2018-06-10 15:01:53
作者hamigaki

Log Message

fix for Zip Slip

Change Summary

差異

--- hamigaki/trunk/libs/archivers/doc/tutorial.xml (revision 1781)
+++ hamigaki/trunk/libs/archivers/doc/tutorial.xml (revision 1782)
@@ -4,7 +4,7 @@
44 <!--
55 Hamigaki.Archivers Library Document Source
66
7- Copyright Takeshi Mouri 2006-2008.
7+ Copyright Takeshi Mouri 2006-2018.
88 Distributed under the Boost Software License, Version 1.0.
99 (See accompanying file LICENSE_1_0.txt or copy at
1010 http://www.boost.org/LICENSE_1_0.txt)
@@ -78,9 +78,25 @@
7878 namespace fs = boost::filesystem;
7979 namespace io = boost::iostreams;
8080
81+bool is_valid_path(const fs::path& ph)
82+{
83+ if (ph.has_root_name() || ph.has_root_directory())
84+ return false;
85+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
86+ {
87+ if (*it == "..")
88+ return false;
89+ }
90+ return true;
91+}
92+
8193 void extract_file(ar::tar_file_source& tar)
8294 {
8395 const ar::tar::header& head = tar.header();
96+ if (!is_valid_path(head.path))
97+ {
98+ std::cerr << "Warning: skip invalid path: " << head.path.string() << std::endl;
99+ }
84100
85101 fs::ofstream file(head.path, std::ios_base::binary);
86102 io::copy(tar, file);
@@ -99,7 +115,7 @@
99115
100116 <para>tarファイルのオープンに成功したら、メンバ関数<methodname>next_entry</methodname>()を呼び出し、次のエントリを確認する。この関数は未読のエントリがある場合<code>true</code>を返す。全てのエントリを読み終わり、これ以上のエントリが見つからない場合は<code>false</code>が返され、ループは終了する。</para>
101117
102- <para><methodname>next_entry</methodname>()の呼び出しに成功したら、アーカイブは<conceptname>Source</conceptname>として読み出し可能である。また、メンバ関数<methodname>header</methodname>()を呼び出すことで、ヘッダ情報を取得することもできる。ここでは、ヘッダから取得したパス名と同名のファイルを作成し、エントリから読み出した内容を書き出している。</para>
118+ <para><methodname>next_entry</methodname>()の呼び出しに成功したら、アーカイブは<conceptname>Source</conceptname>として読み出し可能である。また、メンバ関数<methodname>header</methodname>()を呼び出すことで、ヘッダ情報を取得することもできる。ここでは、ヘッダから取得したパス名と同名のファイルを作成し、エントリから読み出した内容を書き出している。特に意図していない限り、絶対パスやカレントディレクトリより上への相対パスを含むアーカイブは悪意のあるものである。ファイルシステムへ出力する前には必ずパス名を検証する必要がある。</para>
103119 </section>
104120
105121 <section id="archivers.tutorial.zip">
--- hamigaki/trunk/libs/archivers/example/extract.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/extract.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // extract.cpp: multi-format extractor
22
3-// Copyright Takeshi Mouri 2006-2008.
3+// Copyright Takeshi Mouri 2006-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -34,6 +34,21 @@
3434 namespace fs = boost::filesystem;
3535 namespace io = boost::iostreams;
3636
37+template<class Path>
38+bool is_valid_path(const Path& ph)
39+{
40+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
41+ if (ph.has_root_name() || ph.has_root_directory())
42+ return false;
43+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
44+ {
45+ if (*it == "..")
46+ return false;
47+ }
48+#endif
49+ return true;
50+}
51+
3752 struct entry
3853 {
3954 fs_ex::file_type type;
@@ -367,6 +382,11 @@
367382 const entry& e = ext_ptr->current_entry();
368383
369384 std::cout << e.path.string() << '\n';
385+ if (!is_valid_path(e.path))
386+ {
387+ std::cerr << "Warning: invalid path" << '\n';
388+ continue;
389+ }
370390
371391 if (!e.hard_link_path.empty())
372392 fs_ex::create_hard_link(e.hard_link_path, e.path);
--- hamigaki/trunk/libs/archivers/example/uniso.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/uniso.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // uniso.cpp: a simple ISO image extractor program
22
3-// Copyright Takeshi Mouri 2007, 2008.
3+// Copyright Takeshi Mouri 2007, 2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -38,6 +38,21 @@
3838 #endif
3939 }
4040
41+template<class Path>
42+bool is_valid_path(const Path& ph)
43+{
44+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
45+ if (ph.has_root_name() || ph.has_root_directory())
46+ return false;
47+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
48+ {
49+ if (*it == "..")
50+ return false;
51+ }
52+#endif
53+ return true;
54+}
55+
4156 int main(int argc, char* argv[])
4257 {
4358 try
@@ -77,6 +92,11 @@
7792 const ar::iso::header& head = iso.header();
7893
7994 std::cout << head.path.string() << '\n';
95+ if (!is_valid_path(head.path))
96+ {
97+ std::cerr << "Warning: invalid path" << '\n';
98+ continue;
99+ }
80100
81101 if (head.is_symlink())
82102 std::cout << "-> " << head.link_path.string() << '\n';
--- hamigaki/trunk/libs/archivers/example/unlha.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/unlha.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // unlha.cpp: a simple LZH decompressing program
22
3-// Copyright Takeshi Mouri 2006-2008.
3+// Copyright Takeshi Mouri 2006-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -38,6 +38,21 @@
3838 #endif
3939 }
4040
41+template<class Path>
42+bool is_valid_path(const Path& ph)
43+{
44+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
45+ if (ph.has_root_name() || ph.has_root_directory())
46+ return false;
47+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
48+ {
49+ if (*it == "..")
50+ return false;
51+ }
52+#endif
53+ return true;
54+}
55+
4156 inline fs_ex::timestamp make_timestamp(boost::uint64_t ft)
4257 {
4358 return fs_ex::timestamp::from_windows_file_time(ft);
@@ -62,6 +77,11 @@
6277 const ar::lha::header& head = lzh.header();
6378
6479 std::cout << head.path.string() << '\n';
80+ if (!is_valid_path(head.path))
81+ {
82+ std::cerr << "Warning: invalid path" << '\n';
83+ continue;
84+ }
6585
6686 if (!head.link_path.empty())
6787 {
--- hamigaki/trunk/libs/archivers/example/untar.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/untar.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // untar.cpp: a simple ZIP decompressing program
22
3-// Copyright Takeshi Mouri 2006-2008.
3+// Copyright Takeshi Mouri 2006-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -38,6 +38,21 @@
3838 #endif
3939 }
4040
41+template<class Path>
42+bool is_valid_path(const Path& ph)
43+{
44+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
45+ if (ph.has_root_name() || ph.has_root_directory())
46+ return false;
47+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
48+ {
49+ if (*it == "..")
50+ return false;
51+ }
52+#endif
53+ return true;
54+}
55+
4156 int main(int argc, char* argv[])
4257 {
4358 try
@@ -57,6 +72,11 @@
5772 const ar::tar::header& head = tar.header();
5873
5974 std::cout << head.path.string() << '\n';
75+ if (!is_valid_path(head.path))
76+ {
77+ std::cerr << "Warning: invalid path" << '\n';
78+ continue;
79+ }
6080
6181 if (head.type_flag == ar::tar::type_flag::link)
6282 {
--- hamigaki/trunk/libs/archivers/example/unzip.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/unzip.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // unzip.cpp: a simple ZIP decompressing program
22
3-// Copyright Takeshi Mouri 2006-2008.
3+// Copyright Takeshi Mouri 2006-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -38,6 +38,21 @@
3838 #endif
3939 }
4040
41+template<class Path>
42+bool is_valid_path(const Path& ph)
43+{
44+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
45+ if (ph.has_root_name() || ph.has_root_directory())
46+ return false;
47+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
48+ {
49+ if (*it == "..")
50+ return false;
51+ }
52+#endif
53+ return true;
54+}
55+
4156 inline fs_ex::timestamp make_timestamp(std::time_t t)
4257 {
4358 return fs_ex::timestamp::from_time_t(t);
@@ -62,6 +77,11 @@
6277 const ar::zip::header& head = zip.header();
6378
6479 std::cout << head.path.string() << '\n';
80+ if (!is_valid_path(head.path))
81+ {
82+ std::cerr << "Warning: invalid path" << '\n';
83+ continue;
84+ }
6585
6686 if (!head.link_path.empty())
6787 {
--- hamigaki/trunk/libs/archivers/example/wuniso.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/wuniso.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // uniso.cpp: a simple ISO image extractor program (Unicode version)
22
3-// Copyright Takeshi Mouri 2008.
3+// Copyright Takeshi Mouri 2008-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -39,6 +39,21 @@
3939 #endif
4040 }
4141
42+template<class Path>
43+bool is_valid_path(const Path& ph)
44+{
45+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
46+ if (ph.has_root_name() || ph.has_root_directory())
47+ return false;
48+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
49+ {
50+ if (*it == L"..")
51+ return false;
52+ }
53+#endif
54+ return true;
55+}
56+
4257 int main(int argc, char* argv[])
4358 {
4459 try
@@ -78,6 +93,11 @@
7893 const ar::iso::wheader& head = iso.header();
7994
8095 std::wcout << head.path << '\n';
96+ if (!is_valid_path(head.path))
97+ {
98+ std::cerr << "Warning: invalid path" << '\n';
99+ continue;
100+ }
81101
82102 if (head.is_symlink())
83103 std::wcout << "-> " << head.link_path << '\n';
--- hamigaki/trunk/libs/archivers/example/wunlha.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/wunlha.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // wunlha.cpp: a simple LZH decompressing program (Unicode version)
22
3-// Copyright Takeshi Mouri 2008.
3+// Copyright Takeshi Mouri 2008-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -39,6 +39,21 @@
3939 #endif
4040 }
4141
42+template<class Path>
43+bool is_valid_path(const Path& ph)
44+{
45+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
46+ if (ph.has_root_name() || ph.has_root_directory())
47+ return false;
48+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
49+ {
50+ if (*it == L"..")
51+ return false;
52+ }
53+#endif
54+ return true;
55+}
56+
4257 inline fs_ex::timestamp make_timestamp(boost::uint64_t ft)
4358 {
4459 return fs_ex::timestamp::from_windows_file_time(ft);
@@ -63,6 +78,11 @@
6378 const ar::lha::wheader& head = lzh.header();
6479
6580 std::wcout << head.path << '\n';
81+ if (!is_valid_path(head.path))
82+ {
83+ std::cerr << "Warning: invalid path" << '\n';
84+ continue;
85+ }
6686
6787 if (!head.link_path.empty())
6888 {
--- hamigaki/trunk/libs/archivers/example/wuntar.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/wuntar.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // untar.cpp: a simple tar extracting program (Unicode version)
22
3-// Copyright Takeshi Mouri 2008.
3+// Copyright Takeshi Mouri 2008-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -39,6 +39,21 @@
3939 #endif
4040 }
4141
42+template<class Path>
43+bool is_valid_path(const Path& ph)
44+{
45+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
46+ if (ph.has_root_name() || ph.has_root_directory())
47+ return false;
48+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
49+ {
50+ if (*it == L"..")
51+ return false;
52+ }
53+#endif
54+ return true;
55+}
56+
4257 int main(int argc, char* argv[])
4358 {
4459 try
@@ -58,6 +73,11 @@
5873 const ar::tar::wheader& head = tar.header();
5974
6075 std::wcout << head.path << std::endl;
76+ if (!is_valid_path(head.path))
77+ {
78+ std::cerr << "Warning: invalid path" << '\n';
79+ continue;
80+ }
6181
6282 if (head.type_flag == ar::tar::type_flag::link)
6383 {
--- hamigaki/trunk/libs/archivers/example/wunzip.cpp (revision 1781)
+++ hamigaki/trunk/libs/archivers/example/wunzip.cpp (revision 1782)
@@ -1,6 +1,6 @@
11 // wunzip.cpp: a simple ZIP decompressing program (Unicode version)
22
3-// Copyright Takeshi Mouri 2008.
3+// Copyright Takeshi Mouri 2008-2018.
44 // Distributed under the Boost Software License, Version 1.0.
55 // (See accompanying file LICENSE_1_0.txt or copy at
66 // http://www.boost.org/LICENSE_1_0.txt)
@@ -39,6 +39,21 @@
3939 #endif
4040 }
4141
42+template<class Path>
43+bool is_valid_path(const Path& ph)
44+{
45+#if !defined(HAMIGAKI_ALLOW_DIRECTORY_TRAVERSAL)
46+ if (ph.has_root_name() || ph.has_root_directory())
47+ return false;
48+ for (typename Path::iterator it = ph.begin(); it != ph.end(); ++it)
49+ {
50+ if (*it == L"..")
51+ return false;
52+ }
53+#endif
54+ return true;
55+}
56+
4257 inline fs_ex::timestamp make_timestamp(std::time_t t)
4358 {
4459 return fs_ex::timestamp::from_time_t(t);
@@ -63,6 +78,11 @@
6378 const ar::zip::wheader& head = zip.header();
6479
6580 std::wcout << head.path << '\n';
81+ if (!is_valid_path(head.path))
82+ {
83+ std::cerr << "Warning: invalid path" << '\n';
84+ continue;
85+ }
6686
6787 if (!head.link_path.empty())
6888 {
Show on old repository browser