[namcap] Add RUNPATH rule

Message ID 20190929190128.25119-1-jelle@vdwaa.nl
State New
Headers show
Series
  • [namcap] Add RUNPATH rule
Related show

Commit Message

Jelle van der Waa Sept. 29, 2019, 7:01 p.m. UTC
From: Jelle van der Waa <jelle@vdwaa.nl>

Include a rule to check for vulnerable RUNPATH ELF binary entries, which
allow arbitrary code execution by loading shared libraries from an
attacker controller path.
---
 Namcap/rules/__init__.py |  1 +
 Namcap/rules/runpath.py  | 71 ++++++++++++++++++++++++++++++++++++++++
 namcap-tags              |  1 +
 namcap.1                 |  3 ++
 4 files changed, 76 insertions(+)
 create mode 100644 Namcap/rules/runpath.py

Patch

diff --git a/Namcap/rules/__init__.py b/Namcap/rules/__init__.py
index 525dbc6..ee400e2 100644
--- a/Namcap/rules/__init__.py
+++ b/Namcap/rules/__init__.py
@@ -44,6 +44,7 @@  from . import (
   permissions,
   py_mtime,
   rpath,
+  runpath,
   scrollkeeper,
   shebangdepends,
   sodepends,
diff --git a/Namcap/rules/runpath.py b/Namcap/rules/runpath.py
new file mode 100644
index 0000000..053923e
--- /dev/null
+++ b/Namcap/rules/runpath.py
@@ -0,0 +1,71 @@ 
+# namcap rules - runpath
+#
+# Copyright (C) 2019 Jelle van der Waa <jelle@archlinux.org>
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from Namcap.util import is_elf
+from Namcap.ruleclass import TarballRule
+
+from elftools.elf.elffile import ELFFile
+from elftools.elf.dynamic import DynamicSection
+
+allowed = ('/usr/lib', '/usr/lib32', '/lib', '$ORIGIN', '${ORIGIN}')
+allowed_toplevels = (s + '/' for s in allowed)
+warn = ['/usr/local/lib']
+
+
+def get_runpaths(fileobj):
+    elffile = ELFFile(fileobj)
+    for section in elffile.iter_sections():
+        if not isinstance(section, DynamicSection):
+            continue
+        for tag in section.iter_tags():
+            if tag.entry.d_tag != 'DT_RUNPATH':
+                continue
+            for path in tag.runpath.split(':'):
+                yield path
+
+
+class package(TarballRule):
+    name = "runpath"
+    description = "Verifies if RUNPATH is secure"
+
+    def analyze(self, pkgingo, tar):
+        for entry in tar:
+            if not entry.isfile():
+                continue
+
+            fileobj = tar.extractfile(entry)
+            if not is_elf(fileobj):
+                continue
+
+            for path in get_runpaths(fileobj):
+                path_ok = path in allowed
+                for allowed_toplevel in allowed_toplevels:
+                    if path.startswith(allowed_toplevel):
+                        path_ok = True
+
+                if not path_ok:
+                    self.errors.append(("insecure-runpath %s %s",
+                                       (path, entry.name)))
+                    break
+
+                if path in warn and entry.name not in insecure_rpaths:
+                    self.warnings.append(("insecure-runpath %s %s",
+                                         (path, entry.name)))
+
+
+# vim: set ts=4 sw=4 noet:
diff --git a/namcap-tags b/namcap-tags
index 84cc3f7..1f7bc69 100644
--- a/namcap-tags
+++ b/namcap-tags
@@ -44,6 +44,7 @@  incorrect-owner %s (%s:%s) :: File (%s) is owned by %s:%s
 invalid-filename :: File name %s contains non standard characters
 info-dir-file-present %s :: Info directory file (%s) should not be present
 insecure-rpath %s %s :: Insecure RPATH '%s' in file ('%s')
+insecure-runpath %s %s :: Insecure RUNPATH '%s' in file ('%s')
 libtool-file-present %s :: File (%s) is a libtool file
 library-no-package-associated %s :: Referenced library '%s' is an uninstalled dependency
 link-level-dependence %s in %s :: Link-level dependence (%s) in file %s
diff --git a/namcap.1 b/namcap.1
index fcea8ed..9243087 100644
--- a/namcap.1
+++ b/namcap.1
@@ -108,6 +108,9 @@  Checks basic file and and directory permissions.  It returns warnings about worl
 .B rpath
 Gives an error if a binary has RPATH set to something other than /usr/lib
 .TP
+.B runpath
+Gives an error if a binary has RUNPATH set to something other than /usr/lib, /usr/lib32
+.TP
 .B scrollkeeper
 Verifies that there aren't any scrollkeeper directories
 .TP