From ae416bc650db64008d9fbaf4c11cfb48db58e6a2 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Sat, 14 Dec 2019 13:45:18 -0600 Subject: [PATCH] added big brother security auditing to prevent some RCE and leaks --- TODO.txt => docs/TODO.txt | 0 src/bigbrother/__init__.py | 3 ++ src/bigbrother/ministry/__init__.py | 3 +- src/bigbrother/ministry/ofcommunication.py | 13 ++++-- src/bigbrother/ministry/ofexec.py | 54 ++++++++++++++++++++++ src/onionrexceptions.py | 10 ++++ 6 files changed, 79 insertions(+), 4 deletions(-) rename TODO.txt => docs/TODO.txt (100%) create mode 100644 src/bigbrother/ministry/ofexec.py diff --git a/TODO.txt b/docs/TODO.txt similarity index 100% rename from TODO.txt rename to docs/TODO.txt diff --git a/src/bigbrother/__init__.py b/src/bigbrother/__init__.py index 39a3c927..0412440c 100644 --- a/src/bigbrother/__init__.py +++ b/src/bigbrother/__init__.py @@ -35,6 +35,9 @@ def _auditing_supported(): def sys_hook_entrypoint(event, info): if event == 'socket.connect': ministry.ofcommunication.detect_socket_leaks(info) + elif event == 'exec': + # logs and block both exec and eval + ministry.ofexec.block_exec(event, info) def enable_ministries(disable_hooks: Iterable = []): diff --git a/src/bigbrother/ministry/__init__.py b/src/bigbrother/ministry/__init__.py index a7e9380d..24799bbf 100644 --- a/src/bigbrother/ministry/__init__.py +++ b/src/bigbrother/ministry/__init__.py @@ -1 +1,2 @@ -from . import ofcommunication \ No newline at end of file +from . import ofcommunication # noqa +from . import ofexec # noqa diff --git a/src/bigbrother/ministry/ofcommunication.py b/src/bigbrother/ministry/ofcommunication.py index e4683eff..7c6452b1 100644 --- a/src/bigbrother/ministry/ofcommunication.py +++ b/src/bigbrother/ministry/ofcommunication.py @@ -6,6 +6,7 @@ import ipaddress import logger +from onionrexceptions import NetworkLeak """ 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 @@ -30,9 +31,15 @@ def detect_socket_leaks(socket_event): ip_address = socket_event[1][0] # validate is valid ip address (no hostname, etc) - # raises valueerror if not - ipaddress.ip_address(ip_address) + # raises NetworkLeak if not + try: + ipaddress.ip_address(ip_address) + except ValueError: + logger.warn(f'Conn made to {ip_address} outside of Tor/similar') + raise NetworkLeak('Conn to non local IP, this is a privacy concern!') + + # Validate that the IP is localhost ipv4 if not ip_address.startswith('127'): logger.warn(f'Conn made to {ip_address} outside of Tor/similar') - raise ValueError('Conn to non loopback IP, this is a privacy concern!') + raise NetworkLeak('Conn to non local IP, this is a privacy concern!') diff --git a/src/bigbrother/ministry/ofexec.py b/src/bigbrother/ministry/ofexec.py new file mode 100644 index 00000000..dbdbbf9d --- /dev/null +++ b/src/bigbrother/ministry/ofexec.py @@ -0,0 +1,54 @@ +""" + Onionr - Private P2P Communication + + Prevent eval/exec and log it +""" +import base64 + +import logger +from utils import identifyhome +from onionrexceptions import ArbitraryCodeExec +""" + 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 3 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, see . +""" + + +def block_exec(event, info): + """Prevent arbitrary code execution in eval/exec and log it""" + # because libraries have stupid amounts of compile/exec/eval, + # We have to use a whitelist where it can be tolerated + whitelisted_code = [ + 'netrc.py', + '', + 'werkzeug/test.py', + 'multiprocessing/popen_fork.py', + 'multiprocessing/util.py', + 'multiprocessing/connection.py', + 'onionrutils/escapeansi.py' + ] + home = identifyhome.identify_home() + + for source in whitelisted_code: + if info[0].co_filename.endswith(source): + return + + if info[0].co_filename.startswith(home + 'plugins/'): + return + + code_b64 = base64.b64encode(info[0].co_code).decode() + logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True) + logger.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename) + logger.warn('Prevented exec/eval. Report this with the sample below') + logger.warn(f'{event} code in base64 format: {code_b64}') + raise ArbitraryCodeExec("Arbitrary code (eval/exec) detected.") diff --git a/src/onionrexceptions.py b/src/onionrexceptions.py index 5dd6b1b5..41fd51d8 100755 --- a/src/onionrexceptions.py +++ b/src/onionrexceptions.py @@ -105,5 +105,15 @@ class MissingAddress(Exception): class ContactDeleted(Exception): pass +# Version Errors + class PythonVersion(Exception): pass + +# Auditing exceptions + +class NetworkLeak(Exception): + pass + +class ArbitraryCodeExec(Exception): + pass