Browse Source

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.
tags/debian/1.1.exp11
Julian Andres Klode 6 years ago
parent
commit
1c73b0fc41
5 changed files with 56 additions and 1 deletions
  1. +11
    -0
      apt-pkg/deb/debindexfile.cc
  2. +2
    -0
      apt-pkg/deb/debindexfile.h
  3. +6
    -1
      apt-pkg/deb/deblistparser.cc
  4. +7
    -0
      apt-pkg/deb/deblistparser.h
  5. +30
    -0
      test/integration/test-security-no-remote-status

+ 11
- 0
apt-pkg/deb/debindexfile.cc View File

@@ -145,6 +145,17 @@ uint8_t debStatusIndex::GetIndexFlags() const
{
return pkgCache::Flag::NotSource;
}

pkgCacheListParser * debStatusIndex::CreateListParser(FileFd &Pkg)
{
if (Pkg.IsOpen() == false)
return NULL;
_error->PushToStack();
pkgCacheListParser * const Parser = new debStatusListParser(&Pkg);
bool const newError = _error->PendingError();
_error->MergeWithStack();
return newError ? NULL : Parser;
}
/*}}}*/
// DebPkgFile Index - a single .deb file as an index /*{{{*/
debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile)


+ 2
- 0
apt-pkg/deb/debindexfile.h View File

@@ -43,6 +43,8 @@ public:
// Abort if the file does not exist.
virtual bool Exists() const APT_OVERRIDE {return true;};

virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE;

debStatusIndex(std::string const &File);
virtual ~debStatusIndex();
};


+ 6
- 1
apt-pkg/deb/deblistparser.cc View File

@@ -362,7 +362,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
@@ -373,6 +373,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;


+ 7
- 0
apt-pkg/deb/deblistparser.h View File

@@ -119,4 +119,11 @@ class APT_HIDDEN debTranslationsParser : public debListParser
: debListParser(File) {};
};

class APT_HIDDEN debStatusListParser : public debListParser
{
public:
virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);
debStatusListParser(FileFd *File)
: debListParser(File) {};
};
#endif

+ 30
- 0
test/integration/test-security-no-remote-status View File

@@ -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

Loading…
Cancel
Save