mirror of
https://github.com/falcosecurity/falco.git
synced 2025-09-14 05:51:43 +00:00
Destroyed Demo outline (markdown)
200
Demo-outline.md
200
Demo-outline.md
@@ -1,200 +0,0 @@
|
||||
This is a first stab at a demo flow. Very basic starting point right now, but will grow and evolve over time.
|
||||
|
||||
|
||||
Steps:
|
||||
|
||||
## Part 1: Introduce rules
|
||||
|
||||
The goal here is to provide a sense of what rules look like and what they allow. Depending on the audience and time, skip straight to the last example ("output functions").
|
||||
These can be shown in an text editor, or in a gist, ... whatever works.
|
||||
|
||||
Talk through:
|
||||
|
||||
- the underlying event source and its generality
|
||||
- how existing HIDS tools typically provide various subsets of this, from different vantage points
|
||||
- the flexibility of built-in scripting for outputs
|
||||
|
||||
|
||||
|
||||
|
||||
##### a) Three simple rules
|
||||
```
|
||||
# Network traffic to/from standard system utilities
|
||||
# These utils never communicate on the network - if they do, that is a strong indication
|
||||
# that something is wrong (rootkit?)
|
||||
# Note that the full rule lists all ~150 binaries from coreutils; this example only has a few.
|
||||
(fd.typechar = 4 or fd.typechar = 6) and proc.name in (ls, mkdir, cat, less, ps)
|
||||
|
||||
# System binary is modified or new file is written to standard binary dirs
|
||||
evt.type = write and fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)
|
||||
|
||||
# Shell running in container
|
||||
container.id != host and proc.name = bash
|
||||
```
|
||||
|
||||
##### b) Macros
|
||||
|
||||
```
|
||||
# Binary directories
|
||||
bin_dir: fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)
|
||||
|
||||
# Core binaries
|
||||
core_binaries: proc.name in (ls, mkdir, cat, less, ps)
|
||||
|
||||
# Network traffic to/from standard utility
|
||||
(fd.typechar = 4 or fd.typechar=6) and core_binaries
|
||||
|
||||
# System binary is modified
|
||||
evt.type = write and bin_dir
|
||||
|
||||
# Shell running in container
|
||||
container.id != host and proc.name = bash
|
||||
```
|
||||
|
||||
##### c) Output formats
|
||||
|
||||
```
|
||||
# Binary directories
|
||||
bin_dir: fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin)
|
||||
|
||||
# Core binaries
|
||||
core_binaries: proc.name in (ls, mkdir, cat, less, ps)
|
||||
|
||||
# Network traffic to/from standard utility
|
||||
(fd.typechar = 4 or fd.typechar=6) and core_binaries | %evt.time: %proc.name network with %fd.l4proto
|
||||
|
||||
# System binary is modified
|
||||
evt.type = write and bin_dir | %evt.time: System binary modified (file '%fd.filename' written by process %proc.name)
|
||||
|
||||
# Shell running in container
|
||||
container.id != host and proc.name = bash | %evt.time: Shell running in container (%proc.name, %container.id)
|
||||
```
|
||||
|
||||
|
||||
## Part 2: Demo
|
||||
|
||||
Setup:
|
||||
Ubuntu VM
|
||||
digwatch running with base ruleset (https://github.com/draios/digwatch/blob/master/rules/digwatch.conf)
|
||||
|
||||
##### Modify system binary
|
||||
|
||||
Now let's assume we have some breach in the system. Could come in via ssh, or exploiting a vuln in one of our services, etc. There are many bad things an attacker might do, one of fairly common one is installing custom binaries in place of standard system binaries.
|
||||
|
||||
Steps:
|
||||
- _before demo_ `cp /usr/sbin/chroot /usr/sbin/chroot.orig`
|
||||
- _before demo_ have a terminal with a user already logged in as root
|
||||
- run `echo "this is an exploit script" > /usr/sbin/chroot`
|
||||
- note digwatch output
|
||||
|
||||
|
||||
Talking points:
|
||||
- Of course we have a bunch of default rules that alert if anyone `sudo`s - we've bypassed that with a root login to take a look at what might happen if the attacker is already in.
|
||||
|
||||
|
||||
|
||||
##### System binary connects to outside world
|
||||
|
||||
Steps:
|
||||
- _before demo_ compile the `client.c` code below and copy the executable to `/bin/cat`
|
||||
- _before demo_ have a terminal with a user already logged in
|
||||
- run `/bin/cat` (will connect to s3.amazon.com)
|
||||
- note digwatch output
|
||||
|
||||
Talking points:
|
||||
- Simple example but demonstrates the importance of being able to look at things "from inside the host". Specifically here, connecting to s3.amazon.com in and of itself is in many cases completely legit. If we were looking just at network traffic it would be really hard to tell that this is bad. But by adding the process name to the mix, everything changes.
|
||||
|
||||
##### Failed ssh
|
||||
|
||||
Steps:
|
||||
- Run digwatch in one terminal
|
||||
- In other ssh to host with bad login or password
|
||||
- Observe messages in digwatch output
|
||||
|
||||
Talking points:
|
||||
- Other systems do this but by reading log files. This intercepts writes to `/dev/log`. Can't hide from this by clearing/diverting logs.
|
||||
- With an output script, we can do things like "conditionally alert on successful login that happens right after N failed logins"
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
// from http://www.gnu.org/software/libc/manual/html_node/Byte-Stream-Example.html#Byte-Stream-Example
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PORT 80
|
||||
#define MESSAGE "GET /dependencies/lpeg-1.0.0.tar.gz"
|
||||
#define SERVERHOST "s3.amazonaws.com"
|
||||
|
||||
void
|
||||
write_to_server (int filedes)
|
||||
{
|
||||
int nbytes;
|
||||
|
||||
nbytes = write (filedes, MESSAGE, strlen (MESSAGE) + 1);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
perror ("write");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
init_sockaddr (struct sockaddr_in *name,
|
||||
const char *hostname,
|
||||
uint16_t port)
|
||||
{
|
||||
struct hostent *hostinfo;
|
||||
|
||||
name->sin_family = AF_INET;
|
||||
name->sin_port = htons (port);
|
||||
hostinfo = gethostbyname (hostname);
|
||||
if (hostinfo == NULL)
|
||||
{
|
||||
fprintf (stderr, "Unknown host %s.\n", hostname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in servername;
|
||||
|
||||
/* Create the socket. */
|
||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
perror ("socket (client)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Connect to the server. */
|
||||
init_sockaddr (&servername, SERVERHOST, PORT);
|
||||
if (0 > connect (sock,
|
||||
(struct sockaddr *) &servername,
|
||||
sizeof (servername)))
|
||||
{
|
||||
perror ("connect (client)");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Send data to the server. */
|
||||
write_to_server (sock);
|
||||
close (sock);
|
||||
exit (EXIT_SUCCESS);
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user