Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e030732f90 |
2 changed files with 126 additions and 1 deletions
119
reposync-prevent-path-traversal.patch
Normal file
119
reposync-prevent-path-traversal.patch
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
diff -up yum-utils-1.1.31/docs/reposync.1.orig yum-utils-1.1.31/docs/reposync.1
|
||||
--- yum-utils-1.1.31/docs/reposync.1.orig 2018-08-31 15:14:08.100322216 +0200
|
||||
+++ yum-utils-1.1.31/docs/reposync.1 2018-08-31 15:14:14.680403500 +0200
|
||||
@@ -47,6 +47,16 @@ Download all the non-default metadata
|
||||
Download only newest packages per-repo.
|
||||
.IP "\fB\-q, \-\-quiet\fP"
|
||||
Output as little information as possible.
|
||||
+.IP "\fB\-\-allow-path-traversal\fP"
|
||||
+Allow packages stored outside their repo directory to be synced.
|
||||
+These are packages that are referenced in metadata by using absolute paths or
|
||||
+up-level ".." symbols, and are normally skipped by \fBreposync\fR for security
|
||||
+reasons.
|
||||
+
|
||||
+\fBCAUTION:\fR Using this option has potential security implications since, by
|
||||
+providing malicious repodata, an attacker could make \fBreposync\fR write to
|
||||
+arbitrary locations on the file system that are accessible by the user running
|
||||
+it.
|
||||
.SH "EXAMPLES"
|
||||
.IP "Sync all packages from the 'updates' repo to the current directory:"
|
||||
\fB reposync \-\-repoid=updates\fP
|
||||
diff -up yum-utils-1.1.31/reposync.py.orig yum-utils-1.1.31/reposync.py
|
||||
--- yum-utils-1.1.31/reposync.py.orig 2018-08-31 15:14:08.112322364 +0200
|
||||
+++ yum-utils-1.1.31/reposync.py 2018-08-31 15:14:14.680403500 +0200
|
||||
@@ -75,6 +75,12 @@ def localpkgs(directory):
|
||||
cache[name] = {'path': fn, 'size': st.st_size, 'device': st.st_dev}
|
||||
return cache
|
||||
|
||||
+def is_subpath(path, root):
|
||||
+ root = os.path.realpath(root)
|
||||
+ path = os.path.realpath(os.path.join(root, path))
|
||||
+ # join() is used below to ensure root ends with a slash
|
||||
+ return path.startswith(os.path.join(root, ''))
|
||||
+
|
||||
def parseArgs():
|
||||
usage = _("""
|
||||
Reposync is used to synchronize a remote yum repository to a local
|
||||
@@ -117,6 +123,10 @@ def parseArgs():
|
||||
parser.add_option("", "--download-metadata", dest="downloadmd",
|
||||
default=False, action="store_true",
|
||||
help=_("download all the non-default metadata"))
|
||||
+ parser.add_option("", "--allow-path-traversal", default=False,
|
||||
+ action="store_true",
|
||||
+ help=_("Allow packages stored outside their repo directory to be synced "
|
||||
+ "(UNSAFE, USE WITH CAUTION!)"))
|
||||
(opts, args) = parser.parse_args()
|
||||
return (opts, args)
|
||||
|
||||
@@ -217,13 +227,36 @@ def main():
|
||||
else:
|
||||
local_repo_path = opts.destdir + '/' + repo.id
|
||||
|
||||
+ # Ensure we don't traverse out of local_repo_path by dropping any
|
||||
+ # packages whose remote_path is absolute or contains up-level
|
||||
+ # references (unless explicitly allowed).
|
||||
+ # See RHBZ#1600221 for details.
|
||||
+ if not opts.allow_path_traversal:
|
||||
+ newlist = []
|
||||
+ skipped = False
|
||||
+ for pkg in download_list:
|
||||
+ if is_subpath(pkg.remote_path, local_repo_path):
|
||||
+ newlist.append(pkg)
|
||||
+ continue
|
||||
+ my.logger.warning(
|
||||
+ _('WARNING: skipping package %s: remote path "%s" not '
|
||||
+ 'within repodir, unsafe to mirror locally')
|
||||
+ % (pkg, pkg.remote_path)
|
||||
+ )
|
||||
+ skipped = True
|
||||
+ if skipped:
|
||||
+ my.logger.info(
|
||||
+ _('You can enable unsafe remote paths by using '
|
||||
+ '--allow-path-traversal (see reposync(1) for details)')
|
||||
+ )
|
||||
+ download_list = newlist
|
||||
+
|
||||
if opts.delete and os.path.exists(local_repo_path):
|
||||
current_pkgs = localpkgs(local_repo_path)
|
||||
|
||||
download_set = {}
|
||||
for pkg in download_list:
|
||||
- remote = pkg.returnSimple('relativepath')
|
||||
- rpmname = os.path.basename(remote)
|
||||
+ rpmname = os.path.basename(pkg.remote_path)
|
||||
download_set[rpmname] = 1
|
||||
|
||||
for pkg in current_pkgs:
|
||||
@@ -270,8 +303,7 @@ def main():
|
||||
remote_size = 0
|
||||
if not opts.urls:
|
||||
for pkg in download_list:
|
||||
- remote = pkg.returnSimple('relativepath')
|
||||
- local = local_repo_path + '/' + remote
|
||||
+ local = os.path.join(local_repo_path, pkg.remote_path)
|
||||
sz = int(pkg.returnSimple('packagesize'))
|
||||
if os.path.exists(local) and os.path.getsize(local) == sz:
|
||||
continue
|
||||
@@ -283,10 +315,9 @@ def main():
|
||||
download_list.sort(key=lambda pkg: pkg.name)
|
||||
if opts.urls:
|
||||
for pkg in download_list:
|
||||
- remote = pkg.returnSimple('relativepath')
|
||||
- local = os.path.join(local_repo_path, remote)
|
||||
+ local = os.path.join(local_repo_path, pkg.remote_path)
|
||||
if not (os.path.exists(local) and my.verifyPkg(local, pkg, False)):
|
||||
- print urljoin(pkg.repo.urls[0], pkg.relativepath)
|
||||
+ print urljoin(pkg.repo.urls[0], pkg.remote_path)
|
||||
continue
|
||||
|
||||
# create dest dir
|
||||
@@ -295,8 +326,7 @@ def main():
|
||||
|
||||
# set localpaths
|
||||
for pkg in download_list:
|
||||
- rpmfn = pkg.remote_path
|
||||
- pkg.localpath = os.path.join(local_repo_path, rpmfn)
|
||||
+ pkg.localpath = os.path.join(local_repo_path, pkg.remote_path)
|
||||
pkg.repo.copy_local = True
|
||||
pkg.repo.cache = 0
|
||||
localdir = os.path.dirname(pkg.localpath)
|
||||
|
|
@ -10,12 +10,13 @@
|
|||
Summary: Utilities based around the yum package manager
|
||||
Name: yum-utils
|
||||
Version: 1.1.31
|
||||
Release: 513%{?dist}
|
||||
Release: 514%{?dist}
|
||||
License: GPLv2+
|
||||
Group: Development/Tools
|
||||
Source: http://yum.baseurl.org/download/yum-utils/%{name}-%{version}.tar.gz
|
||||
Patch1: yum-utils-HEAD.patch
|
||||
Patch2: yum-utils-deprecated.patch
|
||||
Patch3: reposync-prevent-path-traversal.patch
|
||||
URL: http://yum.baseurl.org/download/yum-utils/
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildArch: noarch
|
||||
|
|
@ -375,6 +376,7 @@ This plugin touches rpmdb files to work around overlayfs issues.
|
|||
%setup -q
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
|
@ -677,6 +679,10 @@ rm -rf $RPM_BUILD_ROOT
|
|||
%{pluginhome}/ovl.*
|
||||
|
||||
%changelog
|
||||
* Fri Aug 31 2018 Michal Domonkos <mdomonko@redhat.com> - 1.1.31-514
|
||||
- reposync: prevent path traversal (CVE-2018-10897)
|
||||
- Resolves: bug#1600454
|
||||
|
||||
* Thu Jul 27 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.1.31-513
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue