refactor readme

This commit is contained in:
Dominic Breuker
2018-02-18 22:29:07 +01:00
parent c56430d8c4
commit 06788d5a31

107
README.md
View File

@@ -1,42 +1,89 @@
<img src="images/logo.svg" align="left" /> <img src="images/logo.svg" align="left" />
# pspy - process monitoring without root # pspy - unprivileged linux process snooping
pspy is a command line tool allowing you to snoop on Linux processes without being root. pspy is a command line tool designed to snoop on processes without needing root permissions.
It can help you to find and analyse cron jobs or other background processes that would otherwise be hidden from you (e.g., a cron job in `/var/spool/cron/root`). It allows you to see commands run by other users, cron jobs, etc. as they execute.
pspy works by using inotify to monitor file system events and a simple scan of `/proc` to find processes. Great for enumeration of linux systems in CTFs.
Inotify events are used as a trigger for `/proc` scanning to not miss short-lived processes.
The tool gathers it's info from procfs scans.
Inotify watchers placed on selected parts of the file system trigger these scans to increase the chance of catching short-lived processes.
## Getting started ## Getting started
Get the tool onto the machine you want to inspect. Get the tool onto the Linux machine you want to inspect.
You can choose between the 32 and 64 bit version. You must choose between the 32 and 64 bit versions.
Files are in the `/bin` folder of this repository. The files are (for now) in the `/bin` folder of this repository.
- 32 bit version: [download](bin/pspy32) - 32 bit version: [download](bin/pspy32)
- 64 bit version: [download](bin/pspy64) - 64 bit version: [download](bin/pspy64)
All files are statically compiled and should run without any libraries.
It will only work on Linux.
No other OS is supported as the project relies on Linux kernel features.
You can run `pspy --help` to learn about the flags and their meaning. You can run `pspy --help` to learn about the flags and their meaning.
The summary is as follows: The summary is as follows:
- -p: enables printing commmands to stdout (enabled by default) - -p: enables printing commands to stdout (enabled by default)
- -f: enables printing file system events to stdout (disabled by default) - -f: enables printing file system events to stdout (disabled by default)
- r: list of directories to watch. pspy will watch all these subdirectories recursively. - -r: list of directories to watch with inotify. pspy will watch all subdirectories recursively (by default, watches /usr, /tmp, /etc, /home, /var, and /opt).
- -d: list of directories to watch. pspy will only watch these directories. No watchers are placed on the subdirectories. - -d: list of directories to watch with inotify. pspy will watch these directories only, not the subdirectories (empty by default).
### Examples Default settings should be fine for most applications.
Watching files inside `/usr` is most important since many tools will access libraries inside it.
Some more complex examples:
```bash ```bash
# print both commands and file system events, but watch only two directories (one recursive, one not) # print both commands and file system events, but watch only two directories (one recursive, one not)
pspy64 -pf -r /path/to/my/dir -d /path/to/my/other/dir pspy64 -pf -r /path/to/my/dir -d /path/to/my/other/dir
# disable printing commands but enable file system events # disable printing commands but enable file system events
go run pspy/main.go -p=false -f pspy64 -p=false -f
``` ```
This is an example from the machine Shrek by [Hack The Box](https://www.hackthebox.eu/). ### Examples
### Cron job watching
To see the tool in action, just clone the repo and run `make example` (Docker needed).
The example starts a debian container in which a cron job changes a user password every minute.
After starting cron, it runs pspy in foreground.
You should see output similar to this:
```console
~/pspy (master) $ make example
[...]
docker run -it --rm local/pspy-example:latest
[+] cron started
[+] Running as user uid=1000(myuser) gid=1000(myuser) groups=1000(myuser),27(sudo)
[+] Starting pspy now...
Watching recursively : [/usr /tmp /etc /home /var /opt] (6)
Watching non-recursively: [] (0)
Printing: processes=true file-system events=false
2018/02/18 21:00:03 Inotify watcher limit: 524288 (/proc/sys/fs/inotify/max_user_watches)
2018/02/18 21:00:03 Inotify watchers set up: Watching 1030 directories - watching now
2018/02/18 21:00:03 CMD: UID=0 PID=9 | cron -f
2018/02/18 21:00:03 CMD: UID=0 PID=7 | sudo cron -f
2018/02/18 21:00:03 CMD: UID=1000 PID=14 | pspy
2018/02/18 21:00:03 CMD: UID=1000 PID=1 | /bin/bash /entrypoint.sh
2018/02/18 21:01:01 CMD: UID=0 PID=20 | CRON -f
2018/02/18 21:01:01 CMD: UID=0 PID=21 | CRON -f
2018/02/18 21:01:01 CMD: UID=0 PID=22 | python3 /root/scripts/password_reset.py
2018/02/18 21:01:01 CMD: UID=0 PID=25 |
2018/02/18 21:01:01 CMD: UID=??? PID=24 | ???
2018/02/18 21:01:01 CMD: UID=0 PID=23 | /bin/sh -c /bin/echo -e "KI5PZQ2ZPWQXJKEL\nKI5PZQ2ZPWQXJKEL" | passwd myuser
2018/02/18 21:01:01 CMD: UID=0 PID=26 | /usr/sbin/sendmail -i -FCronDaemon -B8BITMIME -oem root
2018/02/18 21:01:01 CMD: UID=101 PID=27 |
2018/02/18 21:01:01 CMD: UID=8 PID=28 | /usr/sbin/exim4 -Mc 1enW4z-00000Q-Mk
```
First, pspy prints all currently running processes.
It prints PID, UID and the command line.
Each time pspy detects a new PID, it adds a line to this log.
In this example, you find a process with PID 23 which seems to change the password of myuser.
This is the result of a Python script used in roots private crontab `/var/spool/cron/crontabs/root`, which executes this shell command (check [crontab](docker/var/spool/cron/crontabs/root) and [script](docker/root/scripts/password_reset.py)).
Note that myuser can neither see the crontab nor the Python script.
With pspy, it can see the commands nevertheless.
### CTF example from Hach The Box
Below is an example from the machine Shrek from [Hack The Box](https://www.hackthebox.eu/).
In this CTF challenge, the task is to exploit a hidden cron job that's changing ownership of all files in a folder. In this CTF challenge, the task is to exploit a hidden cron job that's changing ownership of all files in a folder.
With pspy, the cron job is easy to find and analyse: With pspy, the cron job is easy to find and analyse:
@@ -44,29 +91,29 @@ With pspy, the cron job is easy to find and analyse:
## How it works ## How it works
Linux comes with tools to monitor processes spawned on the system. Several tools exist to list all processes executed on Linux systems, including those that have finished.
One example I know is called [forkstat](http://smackerelofopinion.blogspot.de/2014/03/forkstat-new-tool-to-trace-process.html). For instance there is [forkstat](http://smackerelofopinion.blogspot.de/2014/03/forkstat-new-tool-to-trace-process.html).
It received notifications from the kernel on process-related events such as fork and exec. It receives notifications from the kernel on process-related events such as fork and exec.
Unfortunately, the tool required root priviledges so you cannot use it to right away. Unfortunately, the tool requires root privileges so you cannot use it to right away.
However, nothing stop you in general from snooping on the processes running on the system. However, nothing stop you in general from snooping on the processes running on the system.
All data is visible as long as the process is running. All data is visible as long as the process is running.
The only problem is you have to catch short-lived processes in the very short timeframe in which they are alive. The only problem is you have to catch short-lived processes in the very short time span in which they are alive.
Scanning the `/proc` directory for new PIDs in an infinite loop allows doing that but consumes a lot of CPU. Scanning the `/proc` directory for new PIDs in an infinite loop does the trick but consumes a lot of CPU.
A stealthier way is to use the following trick. A stealthier way is to use the following trick.
Process tend to access files such as libraries in `/usr`, temporary files in `/tmp`, log files in `/var`, ... Process tend to access files such as libraries in `/usr`, temporary files in `/tmp`, log files in `/var`, ...
Without root permissions, you can get notifications whenever these files are touched. Without root permissions, you can get notifications whenever these files are touched.
The API for this is[inotify](http://man7.org/linux/man-pages/man7/inotify.7.html). The API for this is called [inotify](http://man7.org/linux/man-pages/man7/inotify.7.html).
While we cannot monitor processes direclty, we can monitor their interactions with the file system. While we cannot monitor processes directly, but we can monitor their interactions with the file system.
The trick now is to use these file system events as a trigger to scan `/proc`, hoping that we can do it fast enough to catch the process. We can use the file system events as a trigger to scan `/proc`, hoping that we can do it fast enough to catch the processes.
This is essentially what pspy does. This is what pspy does.
Thus, it has a good chance of capturing most processes, but there is no guarantee you won't miss one. Thus, there is no guarantee you won't miss one, but chances seem to be good in my experiments.
In general, the longer the processes run, the bigger the chance of catching them is. In general, the longer the processes run, the bigger the chance of catching them is.
Besides using the events, pspy will also scan `/proc` every 100ms, just to be sure. Besides using the events, pspy will also scan `/proc` every 100ms, just to be sure.
My initial experiments suggest the CPU usage is quite low for this value. CPU usage seems to be quite low for this interval.
Making the interval configurable is on the roadmap. Making the interval configurable is on the roadmap.
# Misc # Misc