diff options
author | Julian Andres Klode <jak@debian.org> | 2015-08-21 18:00:37 +0200 |
---|---|---|
committer | Julian Andres Klode <jak@debian.org> | 2015-08-21 19:34:02 +0200 |
commit | 130f34b7bc48bb05cc192ca6c66606fd99509b3e (patch) | |
tree | e57170b6cd02ab57ba635bfd6e9bf938ee9cc125 | |
parent | 990af3c952676eaa51ccd614ab2d4234693da397 (diff) |
Do not parse Status fields from remote sources
This could allow an attacker to mark a package as installed in a
remote package index, as long as the package was not listed in
the dpkg status file.
This way, an attacker could force the installation of a package
during a dist-upgrade, by providing two packages in an index,
an older marked as installed, and a newer - apt would "upgrade"
to the newer version.
-rw-r--r-- | apt-pkg/deb/debindexfile.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 7 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.h | 7 | ||||
-rwxr-xr-x | test/integration/test-security-no-remote-status | 30 |
4 files changed, 44 insertions, 2 deletions
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 504db919b..de6371ace 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -621,7 +621,7 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension); if (_error->PendingError() == true) return false; - debListParser Parser(&Pkg); + debStatusListParser Parser(&Pkg); if (_error->PendingError() == true) return false; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 6d4fd9ac1..336414775 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -333,7 +333,7 @@ unsigned short debListParser::VersionHash() return Result; } /*}}}*/ -// ListParser::ParseStatus - Parse the status field /*{{{*/ +// StatusListParser::ParseStatus - Parse the status field /*{{{*/ // --------------------------------------------------------------------- /* Status lines are of the form, Status: want flag status @@ -345,6 +345,11 @@ unsigned short debListParser::VersionHash() bool debListParser::ParseStatus(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) { + return true; +} +bool debStatusListParser::ParseStatus(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver) +{ const char *Start; const char *Stop; if (Section.Find("Status",Start,Stop) == false) diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index db7afa73c..d479997a3 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -117,4 +117,11 @@ class debTranslationsParser : public debListParser : debListParser(File, Arch) {}; }; +class APT_HIDDEN debStatusListParser : public debListParser +{ + public: + virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + debStatusListParser(FileFd *File) + : debListParser(File) {}; +}; #endif diff --git a/test/integration/test-security-no-remote-status b/test/integration/test-security-no-remote-status new file mode 100755 index 000000000..b7cd0b0d1 --- /dev/null +++ b/test/integration/test-security-no-remote-status @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Test that packages from remote sources cannot set the Status field. +# +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +TMPDIR=$(readlink -f .) + +insertpackage 'unstable' 'pretends-installed' 'all' '1' 'Status: install ok installed' +insertinstalledpackage 'really-installed' 'all' '1' +setupaptarchive + +testequal "pretends-installed: + Installed: (none) + Candidate: 1 + Version table: + 1 0 + 500 file:${TMPDIR}/aptarchive/ unstable/main amd64 Packages" aptcache policy pretends-installed + +testequal "really-installed: + Installed: 1 + Candidate: 1 + Version table: + *** 1 0 + 100 ${TMPDIR}/rootdir/var/lib/dpkg/status" aptcache policy really-installed |