[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#749795: apt: no authentication checks for source packages



On Thu, May 29, 2014 at 11:04:35PM +0200, Jakub Wilk wrote:
> Package: apt
> Version: 1.0.3
> Severity: grave
> Tags: security

Thanks for your bugreport. You raise a important issue, but I agree
with David that its best if this goes through the security team for
coordination.
 
> I've been investigating how apt behaves when the repository doesn't
> contain any Release signatures (possibly because they were stripped
> off by a man-in-the-middle attacker).
> 
> This is what I found out:
> 
> | # cat /etc/apt/sources.list
> | deb http://ftp.debian.org/debian/ unstable main
> | deb-src http://ftp.debian.org/debian/ unstable main
> |
> | # apt-get update
> | Ign http://ftp.debian.org unstable InRelease
> | Ign http://ftp.debian.org unstable Release.gpg
> | Get:1 http://ftp.debian.org unstable Release [205 kB]
> | Get:2 http://ftp.debian.org unstable/main Sources [7249 kB]
> | Get:3 http://ftp.debian.org unstable/main amd64 Packages [6758 kB]
> | Fetched 14.2 MB in 29s (479 kB/s)
> | Reading package lists... Done
> |
> | # echo $?
> | 0
> 
> Hmm. There is no warning suggesting that anything fishy is going on,
> and the exit code indicates success. (Perhaps the "Ign"s could raise
> suspicion of an observant sysadmin. But who knows what "Ign" exactly
> means? At least the apt-get(1) manpage doesn't know.)

Right, I think apt should show a more prominent warning here. I will
look into this next.
 
[..]
> So far, so good. However, apt-get happily downloads unauthenticated
> source packages, with no warning:
> 
> | $ apt-get source -d nyancat
> | Reading package lists... Done
> | Building dependency tree
> | Reading state information... Done
> | Selected version '1.2.2-1' (unstable) for nyancat
> | Need to get 20.6 kB of source archives.
> | Get:1 http://ftp.debian.org/debian/ unstable/main nyancat 1.2.2-1 (dsc) [1782 B]
> | Get:2 http://ftp.debian.org/debian/ unstable/main nyancat 1.2.2-1 (tar) [14.1 kB]
> | Get:3 http://ftp.debian.org/debian/ unstable/main nyancat 1.2.2-1 (diff) [4748 B]
> | Fetched 20.6 kB in 0s (1838 kB/s)
> | Download complete and in download only mode
[..]

Indeed, this is a problem that needs fixing. Attached is a patch that
addresses the issue.

Cheers,
 Michael
>From b7f501b5cc8583f61467f0c7a0282acbb88e4b29 Mon Sep 17 00:00:00 2001
From: Michael Vogt <mvo@debian.org>
Date: Fri, 30 May 2014 14:47:56 +0200
Subject: [PATCH] Show unauthenticated warning for source packages as well

This will show the same unauthenticated warning for source packages
as for binary packages and will not download a source package if
it is unauthenticated. This can be overriden with
--allow-unauthenticated

Closes: #749795
---
 apt-private/private-download.cc                    |  5 +++++
 apt-private/private-download.h                     |  6 +++++
 cmdline/apt-get.cc                                 |  9 ++++++++
 test/integration/test-apt-get-source-authenticated | 26 ++++++++++++++++++++++
 4 files changed, 46 insertions(+)
 create mode 100755 test/integration/test-apt-get-source-authenticated

diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc
index a095f0c..be7d23c 100644
--- a/apt-private/private-download.cc
+++ b/apt-private/private-download.cc
@@ -28,6 +28,11 @@ bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser)
    if (UntrustedList == "")
       return true;
 
+   return AuthPrompt(UntrustedList, PromptUser);
+}
+
+bool AuthPrompt(std::string UntrustedList, bool const PromptUser)
+{
    ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
 
    if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
diff --git a/apt-private/private-download.h b/apt-private/private-download.h
index a108aa5..a90ac7e 100644
--- a/apt-private/private-download.h
+++ b/apt-private/private-download.h
@@ -5,7 +5,13 @@
 
 class pkgAcquire;
 
+// Check if all files in the fetcher are authenticated
 APT_PUBLIC bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser);
+
+// show a authentication warning prompt and return true if the system
+// should continue
+APT_PUBLIC bool AuthPrompt(std::string UntrustedList, bool const PromptUser);
+
 APT_PUBLIC bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure);
 
 #endif
diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc
index 0f18b0e..d74d6d5 100644
--- a/cmdline/apt-get.cc
+++ b/cmdline/apt-get.cc
@@ -76,6 +76,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/statfs.h>
 #include <sys/statvfs.h>
@@ -755,6 +756,7 @@ static bool DoSource(CommandLine &CmdL)
 
    // Load the requestd sources into the fetcher
    unsigned J = 0;
+   std::string UntrustedList;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
    {
       string Src;
@@ -763,6 +765,9 @@ static bool DoSource(CommandLine &CmdL)
       if (Last == 0) {
 	 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
       }
+
+      if (Last->Index().IsTrusted() == false)
+         UntrustedList += Src + " ";
       
       string srec = Last->AsStr();
       string::size_type pos = srec.find("\nVcs-");
@@ -846,6 +851,10 @@ static bool DoSource(CommandLine &CmdL)
 			Last->Index().SourceInfo(*Last,*I),Src);
       }
    }
+
+   // check authentication status of the source as well
+   if (UntrustedList != "" && !AuthPrompt(UntrustedList, true))
+      return false;
    
    // Display statistics
    unsigned long long FetchBytes = Fetcher.FetchNeeded();
diff --git a/test/integration/test-apt-get-source-authenticated b/test/integration/test-apt-get-source-authenticated
new file mode 100755
index 0000000..e384b3d
--- /dev/null
+++ b/test/integration/test-apt-get-source-authenticated
@@ -0,0 +1,26 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+# a "normal" package with source and binary
+buildsimplenativepackage 'foo' 'all' '2.0'
+
+setupaptarchive --no-update
+
+APTARCHIVE=$(readlink -f ./aptarchive)
+rm -f $APTARCHIVE/dists/unstable/*Release*
+
+# update without authenticated InRelease file
+testsuccess aptget update
+
+# this all should fail
+testfailure aptget install -y foo
+testfailure aptget source -y foo
+
+# allow overriding the warning
+testsuccess aptget source --allow-unauthenticated foo
-- 
1.9.1


Reply to: