From 81429d0e8ab889927c600b0e486d0024185ecebd Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sun, 30 Apr 2017 11:04:59 +0200 Subject: [PATCH] Fixes #12: Using kernel ftrace extension to hook to execve calls and prevent path manipulation. --- README.md | 5 -- opensnitch/.app.py.swo | Bin 0 -> 20480 bytes opensnitch/.connection.py.swo | Bin 0 -> 12288 bytes opensnitch/.proc.py.swo | Bin 0 -> 12288 bytes opensnitch/.procmon.py.swo | Bin 0 -> 20480 bytes opensnitch/.rule.py.swo | Bin 0 -> 16384 bytes opensnitch/.snitch.py.swo | Bin 0 -> 16384 bytes opensnitch/app.py | 30 ++++--- opensnitch/connection.py | 16 +++- opensnitch/proc.py | 15 +++- opensnitch/procmon.py | 158 ++++++++++++++++++++++++++++++++++ opensnitch/snitch.py | 19 ++-- opensnitch/ui.py | 4 +- opensnitch/version.py | 2 +- 14 files changed, 217 insertions(+), 32 deletions(-) create mode 100644 opensnitch/.app.py.swo create mode 100644 opensnitch/.connection.py.swo create mode 100644 opensnitch/.proc.py.swo create mode 100644 opensnitch/.procmon.py.swo create mode 100644 opensnitch/.rule.py.swo create mode 100644 opensnitch/.snitch.py.swo create mode 100644 opensnitch/procmon.py diff --git a/README.md b/README.md index 26952b0a21..41974895fb 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,6 @@ OpenSnitch is a GNU/Linux port of the Little Snitch application firewall. grep -r TODO opensnitch | cut -d '#' -f 2 | sort -u -## Known Limitations - -As [pointed out in this thread](https://github.com/evilsocket/opensnitch/issues/12), OpenSnitch relies on the `/proc` filesystem in order to link a connection to a process. Being this information relatively easy to manipulate by an attacker, the path and the list of arguments shown in the UI might not match the real -context of the process. - ## License This project is copyleft of [Simone Margaritelli](http://www.evilsocket.net/) and released under the GPL 3 license. diff --git a/opensnitch/.app.py.swo b/opensnitch/.app.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..e78dd614d288ac6404058b612e212f7a00a4d555 GIT binary patch literal 20480 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 OlI@-+^1Au7MEn~8;H9|$ literal 0 HcmV?d00001 diff --git a/opensnitch/.connection.py.swo b/opensnitch/.connection.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..0b184115da58d36e02a3c6c5b893e8f754454a7e GIT binary patch literal 12288 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 literal 0 HcmV?d00001 diff --git a/opensnitch/.procmon.py.swo b/opensnitch/.procmon.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..d343a140e25aea191d6ca751e6b100813298f3dd GIT binary patch literal 20480 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 B_9p-U literal 0 HcmV?d00001 diff --git a/opensnitch/.rule.py.swo b/opensnitch/.rule.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..08877375de8e20684a933986bd9cfa86a7cc74e7 GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/opensnitch/.snitch.py.swo b/opensnitch/.snitch.py.swo new file mode 100644 index 0000000000000000000000000000000000000000..bb94c05d69bb4bca4feeb2a5572825af4a7c0c42 GIT binary patch literal 16384 zcmeHNO>84c6)tucm<9Gnv%qO*^d`|Lp2hCi8FpqB$r7H#ne~u3nb_H3Kw3|`yKMKQ z-PO}oos2KLbAbaZBm@_Pb`MDWh!r<(AkcCGgv5cGiv(ZwkKJ(+2sebv z(HD1jy;t?#_g=lKZg;=>N^6T=vZ@T9XBm6`8&BMQ#GYnvU1W?Oc)k?QK3BT&^iSU& z+2i;>2toa|S%=HwFj(_N>@IKG{biRQEQ^o_GVqi$Djud+tZ;Jr=%&RmU>GGHFkl!k3>XIf2N|$k#y$?a{-|&G z@%w*%|Nr}E82cUYL*Px|5%3!DGH@Pv7I^n*#=Z%>3akPz0q;M>*iV2rfKA{Aa20qG z`0d9S`zi2U;5)zy$3#gO4V_~&+ zx{Vu~%}#H35C2!07IXQ4q!M9Ca({4Tl_eK-gFd$&SWz65uFPFjJv$7umTA*eCyazM z7J(&|9jSuuF##UfeV-R3yaDY%c?-&(>Ag^i@(LPf}>>_jX8%nNNqF z@00G5JjIeRvVS=pUN8_~V;v%)X5+G?K_tc*i6wGG5R{Yu)(|Ej@V&quBWi@dX^)89 z0gqg&*J&3lTI;*pJ9E*>2jmYm4W0-vYBN735#-i8w(s}h$m&9&|5S;l@?`>Z)6t85 zrDmkrs}0uYo}*Gn3O(jJX%J5ADz`Y#m^BgmE(Jni(kSjI(wWXB2*W(nJmDJrvWkY! zh59B|P#22<(m`Ey`6gte(BuUoB+FEm`%d}Ox8e+Ef@+3?qa~W5Pl`-Nfj)ElN zky$6FVd9%EC>a$vLJF31r7~e6`I8qqFFBSg(U8Y~h+0c#yeMr#4pu z&sRLU9rL)j>Lne4%|x+Q~(@O{)05zY6OkN~+f{&K!q)2n-_(!lN$K#mq$r0(|m_9}JaFcgu(ygImcY39EcDSQ^T_qscKU8+=&DrxyqPDqt;x&T!w z$vRY{%6-~x-fFIOPb!01e~Yxs?4bpnr>HEVesPN)DQ)=V2Cvv zHs~6r_Y3>5&r#TVC{FF>9c@i}rX;k%7yZ2qb<@+EUCKt zw7O@@lsrv-q1B#aDR#k91*H%azj*b(wCL!T4UsJ&Y}z8E3FQS=GRKD#*)|VVE?L26 zFV|XGB`0s3Sdr!GF)^K9xy&w(%gJIckICs|&AKXP>oK_kYnk|LjX5S9dwHM9Ov{{* zjvY=cl*qjCg;Y_EB5u3M_AT{EXMEa}zP+5wH#T~$cC%Zi?BH4%8)B5LKnXjQ$5}ct zlk~{-j!svW*`F=V`Kgd>kzTCPMq~&3zTRl7h;vn@4R3&&x8VyBmFWg5r@$s^t3lP3 zTCG~CU9Hy2wAX1^P{-ckF!GSDSfbU4qc6^>BL?cwj&LU8081OT6=iA#j#Y*RqB)H0 zu|=(c-i?%L2u(pFrNY(a<-@~6YZ%0qh=$9)=imivE|-U)Z;jO0hxT0&lN=>mnGx0r zB$30t157>}SsqSE3=%VL?rf6n3+xD!@~!umY!T{1fx;YU;v;W3Qj+YzCEpu+m~yaE zYM1!K5UDA(Yv9fIxNA`dUTODqzk0u zZ%a>>=}xQrG71pgY3%Mc+TFXfy+MukUHWXRy^hTwRu~>Zd&-;ZNfmkhSivzc$kPEg zQ$F-+QxHh}y4l{tyb5?^`?M4H!5rn%ukc91HLMOLZS}o-@L_4`iuSatx82Adj#4zC zJ_i#Ci@BcrAd-*Q_`u-ocuF2 %s:%s" % ( self.pid, self.app_path, self.proto, self.dst_addr, self.dst_port ) diff --git a/opensnitch/proc.py b/opensnitch/proc.py index 3673f7b01d..d7e95f6432 100644 --- a/opensnitch/proc.py +++ b/opensnitch/proc.py @@ -20,7 +20,7 @@ import logging import psutil -def get_pid_by_connection( src_addr, src_p, dst_addr, dst_p, proto = 'tcp' ): +def get_pid_by_connection( procmon, src_addr, src_p, dst_addr, dst_p, proto = 'tcp' ): connections_list = [connection for connection in psutil.net_connections(kind=proto) if connection.laddr==(src_addr, src_p) and connection.raddr==(dst_addr, dst_p)] # We always take the first element as we assume it contains only one, because @@ -28,7 +28,18 @@ def get_pid_by_connection( src_addr, src_p, dst_addr, dst_p, proto = 'tcp' ): if connections_list: pid = connections_list[0][-1] try: - return ( pid, os.readlink( "/proc/%s/exe" % pid ) ) + appname = None + if procmon.running: + appname = procmon.get_app_name(pid) + + if appname is None: + appname = os.readlink( "/proc/%s/exe" % pid ) + if procmon.running: + logging.debug( "Could not find pid %s with ProcMon, faiiling back to /proc/%s/exe -> %s" % ( pid, pid, appname ) ) + else: + logging.debug( "ProcMon(%s) = %s" % ( pid, appname ) ) + + return ( pid, appname ) except OSError: return (None, "Unknown") else: diff --git a/opensnitch/procmon.py b/opensnitch/procmon.py new file mode 100644 index 0000000000..761e1b099a --- /dev/null +++ b/opensnitch/procmon.py @@ -0,0 +1,158 @@ +# This file is part of OpenSnitch. +# +# Copyright(c) 2017 Simone Margaritelli +# evilsocket@gmail.com +# http://www.evilsocket.net +# +# This file may be licensed under the terms of of the +# GNU General Public License Version 2 (the ``GPL''). +# +# Software distributed under the License is distributed +# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either +# express or implied. See the GPL for the specific language +# governing rights and limitations. +# +# You should have received a copy of the GPL along with this +# program. If not, go to http://www.gnu.org/licenses/gpl.html +# or write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +import select +import re +from collections import defaultdict +import os +import threading +import logging + +class ProcMon(threading.Thread): + PROBE_NAME = "opensnitch_sys_execve" + + def __init__(self): + threading.Thread.__init__(self) + self.pids = defaultdict(dict) + self.lock = threading.Lock() + self.running = False + self.daemon = True + + @staticmethod + def enable(): + ProcMon.disable(False) + logging.info( "Enabling ProcMon ..." ) + + open("/sys/kernel/debug/tracing/events/sched/sched_process_fork/enable", 'w').write("1") + open("/sys/kernel/debug/tracing/events/sched/sched_process_exec/enable", 'w').write("1") + open("/sys/kernel/debug/tracing/events/sched/sched_process_exit/enable", 'w').write("1") + + # Create the custom execve kprobe consumer + with open("/sys/kernel/debug/tracing/kprobe_events", "w") as f: + f.write( "p:kprobes/%s sys_execve" % ProcMon.PROBE_NAME ) + #Command line args will be in %si, we're asking ftrace to give them to us + for i in range(1, 16): + f.write(" arg%d=+0(+%d(%%si)):string" % (i, i*8)) + + open("/sys/kernel/debug/tracing/events/kprobes/%s/enable" % ProcMon.PROBE_NAME, 'w').write('1') + + @staticmethod + def disable(verbose=True): + if verbose: + logging.info( "Disabling ProcMon ..." ) + + try: + open("/sys/kernel/debug/tracing/events/sched/sched_process_fork/enable", 'w').write("0") + open("/sys/kernel/debug/tracing/events/sched/sched_process_exec/enable", 'w').write("0") + open("/sys/kernel/debug/tracing/events/sched/sched_process_exit/enable", 'w').write("0") + open("/sys/kernel/debug/tracing/events/kprobes/%s/enable" % ProcMon.PROBE_NAME, 'w').write('0') + open("/sys/kernel/debug/tracing/kprobe_events", 'a+').write("-:"+ ProcMon.PROBE_NAME) + open("/sys/kernel/debug/tracing/trace", 'w').write('') + except: + pass + + @staticmethod + def is_ftrace_available(): + try: + with open( '/proc/sys/kernel/ftrace_enabled', 'rt' ) as fp: + return fp.read().strip() == '1' + except: + pass + + return False + + def get_app_name( self, pid ): + pid = int(pid) + with self.lock: + if pid in self.pids and 'filename' in self.pids[pid]: + return self.pids[pid]['filename'] + + return None + + def get_cmdline( self, pid ): + pid = int(pid) + with self.lock: + if pid in self.pids and 'args' in self.pids[pid]: + return self.pids[pid]['args'] + + return None + + def _dump( self, pid, e ): + logging.debug( "(pid=%d) %s %s" % ( pid, e['filename'], e['args'] if 'args' in e else '' ) ) + + def _on_exec( self, pid, filename ): + with self.lock: + self.pids[pid]['filename'] = filename + self._dump( pid, self.pids[pid] ) + + def _on_args( self, pid, args ): + with self.lock: + self.pids[pid]['args'] = args + + def _on_exit( self, pid ): + with self.lock: + if pid in self.pids: + del self.pids[pid] + + def run(self): + logging.info( "ProcMon running ..." ) + self.running = True + + with open("/sys/kernel/debug/tracing/trace_pipe") as pipe: + while True: + try: + r, w, e = select.select([pipe], [], [], 0) + if pipe not in r: + continue + line = pipe.readline() + + if ProcMon.PROBE_NAME in line: + m = re.search(r'^.*?\-(\d+)\s*\[', line) + + if m is not None: + pid = int(m.group(1)) + #"walk" over every argument field, 'fault' is our terminator. + # If we see it it means that there are more cmdline args. + if '(fault)' in line: + line = line[:line.find('(fault)')] + + args = ' '.join(re.findall(r'arg\d+="(.*?)"', line)) + + self._on_args( pid, args ) + + else: + m = re.search(r'sched_process_(.*?):', line) + if m is not None: + event = m.group(1) + + if event == 'exec': + filename = re.search(r'filename=(.*?)\s+pid=', line).group(1) + pid = int(re.search(r'\spid=(\d+)', line).group(1)) + + self._on_exec( pid, filename ) + + elif event == 'exit': + mm = re.search(r'\scomm=(.*?)\s+pid=(\d+)', line) + command = mm.group(1) + pid = int(mm.group(2)) + + self._on_exit( pid ) + + except Exception as e: + logging.warning(e) + diff --git a/opensnitch/snitch.py b/opensnitch/snitch.py index 5796889848..bdb5b93a44 100644 --- a/opensnitch/snitch.py +++ b/opensnitch/snitch.py @@ -27,6 +27,7 @@ from opensnitch.connection import Connection from opensnitch.dns import DNSCollector from opensnitch.rule import Rule, Rules +from opensnitch.procmon import ProcMon class Snitch: IPTABLES_RULES = ( # Get DNS responses @@ -38,11 +39,12 @@ class Snitch: # TODO: Support IPv6! def __init__( self ): - self.lock = Lock() - self.rules = Rules() - self.dns = DNSCollector() - self.q = NetfilterQueue() - self.qt_app = QtApp() + self.lock = Lock() + self.rules = Rules() + self.dns = DNSCollector() + self.q = NetfilterQueue() + self.procmon = ProcMon() + self.qt_app = QtApp() self.q.bind( 0, self.pkt_callback, 1024 * 2 ) @@ -69,7 +71,7 @@ def pkt_callback(self,pkt): self.dns.add_response(packet) else: - conn = Connection(data) + conn = Connection( self.procmon, data ) if conn.proto is None: logging.debug( "Could not detect protocol for packet." ) @@ -95,6 +97,10 @@ def start(self): logging.debug( "Applying iptables rule '%s'" % r ) os.system( "iptables -I %s" % r ) + if ProcMon.is_ftrace_available(): + self.procmon.enable() + self.procmon.start() + self.qt_app.run() self.q.run() @@ -103,4 +109,5 @@ def stop(self): logging.debug( "Deleting iptables rule '%s'" % r ) os.system( "iptables -D %s" % r ) + self.procmon.disable() self.q.unbind() diff --git a/opensnitch/ui.py b/opensnitch/ui.py index 950c2a26a8..6e43317497 100644 --- a/opensnitch/ui.py +++ b/opensnitch/ui.py @@ -55,8 +55,8 @@ def __init__( self, connection, parent=None ): def setup_labels(self): self.app_name_label.setText( self.connection.app.name ) - message = "%s (pid=%s) wants to connect to %s on %s port %s%s" % ( \ - self.connection.app_path, + message = "%s (pid=%s) wants to connect to %s on %s port %s%s" % ( \ + self.connection.get_app_name_and_cmdline(), self.connection.app.pid, self.connection.hostname, self.connection.proto.upper(), diff --git a/opensnitch/version.py b/opensnitch/version.py index 70623d0569..9259a86ea6 100644 --- a/opensnitch/version.py +++ b/opensnitch/version.py @@ -16,4 +16,4 @@ # program. If not, go to http://www.gnu.org/licenses/gpl.html # or write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -VERSION = '0.0.1a1' +VERSION = '0.0.2'