Table of Contents

Ubuntu - Processes - List all non-kernel processes

Usually kernel processes are safe and clean.

For kernel processes, either PID (process id) is 2 or PPID (parent process id) is 2.

Here is how to get all non-kernel processes.

ps --ppid 2 -p 2 -p 1 \
   --deselect -o uid,pid,rss,%cpu,command

returns:

UID   PID   RSS %CPU COMMAND
   0   411  1848  0.0 /lib/systemd/systemd-
   0   572  2904  0.0 dhclient -1 -v -pf /r
 102   902  1244  0.0 dbus-daemon --system
   0   912  1948  0.0 /lib/systemd/systemd-
   0  5869   388  0.0 upstart-socket-bridge
 200  1953   904  0.0 /usr/sbin/apache2 -k
 200  3463  3700  0.0 /usr/sbin/apache2 -k
  ...  ...
  ...  ...
   0  5098  4224  0.0 sshd: ubuntu [priv]
   0  5139  1748  0.0 /usr/bin/python /usr/
 200  5140  3484  0.0 /usr/bin/python /usr/
 200  5176  1904  0.0 sshd: ubuntu@pts/3
 200  5177  3860  0.0 -bash
 200  5193  1200  0.0 tmux attach -t denny
   0  5297  4224  0.0 sshd: ubuntu [priv]
  ...  ...
  ...  ...

NOTE:


Rule out trusted procsses

We may have many processes running, which are expected and trusted. e.g apache2, tomcat7, mysqld, etc.

To avoid distraction, build a white list especial for your project.


Sort processes by memory and cpu

We’re more concerned about suspicious processes using noticeable resource.

# Sort by memory first, then cpu
ps --ppid 2 -p 2 -p 1 --deselect \
  -o uid,pid,rss,%cpu,command, \
  --sort -rss,-cpu

Automate Detection Process and Get Alerts

We hide all the complexities and white list configuration in a python script (detect_suspicious_process.py).

If you issue the python command, you may see output like “Identified processes count: XXX.” Define a scheduled task to run periodical check and confirm the number.

If the number is not 0 or it changes, send alerts.

It might take a while to build a suitable white list.

Once it’s done, your servers are always more secured and managed!

wget -O /tmp/detect_suspicious_process.py \
https://raw.githubusercontent.com/\
DennyZhang/devops_public/tag_v2/python/\
detect_suspicious_process/\
detect_suspicious_process.py
 
# Detect suspicious process
python /tmp/detect_suspicious_process.py
 
# Detect by customized whitelist
python /tmp/detect_suspicious_process.py \
   --whitelist_file /tmp/whitelist.txt

detect_suspicious_process.py

# -*- coding: utf-8 -*-
#!/usr/bin/python
##-------------------------------------------------------------------
## @copyright 2015 DennyZhang.com
## File : detect_suspicious_process.py
## Author : DennyZhang.com <denny@dennyzhang.com>
## Description : http://www.dennyzhang.com/suspicious_process/
##        python ./detect_suspicious_process.py
##        python ./detect_suspicious_process.py --whitelist_file /tmp/whitelist.txt
## --
## Created : <2016-01-15>
## Updated: Time-stamp: <2016-08-20 13:32:55>
##-------------------------------------------------------------------
import argparse
import subprocess
import os, sys
 
################################################################################
# TODO: move to common library
def string_in_regex_list(string, regex_list):
    import re
    for regex in regex_list:
        regex = regex.strip()
        if regex == "":
            continue
        if re.search(regex, string) is not None:
            # print "regex: %s, string: %s" % (regex, string)
            return True
    return False
 
################################################################################
DEFAULT_WHITE_LIST = '''
/sbin/getty -.*
dbus-daemon .*
 acpid -c /etc/acpi/events -s /var/run/acpid.socket$
 atd$
 cron$
 /lib/systemd/systemd-udevd --daemon$
 /lib/systemd/systemd-logind$
 dbus-daemon --system --fork$
 /usr/sbin/sshd -D$
 rsyslogd$
 /usr/sbin/mysqld$
 /usr/sbin/apache2 -k start$
'''
 
COMMAND_GET_NONKERNEL = '''
sudo ps --ppid 2 -p 2 -p 1 --deselect \
-o uid,pid,rss,%cpu,command \
--sort -rss,-cpu
'''
 
def get_nonkernel_process():
    process_list = subprocess.check_output(COMMAND_GET_NONKERNEL, shell=True)
    return process_list
 
def load_whitelist(fname):
    white_list = ""
    if fname is None:
        print "No white list file is given. Use default value."
        white_list = DEFAULT_WHITE_LIST
    else:
        print "load white list from %s" % (fname)
        with open(fname) as f:
            white_list = f.readlines()
    return white_list
 
def list_process(process_list, white_list):
    import re
    l = []
    for line in process_list.split("\n"):
        line = line.strip()
        if line == "":
            continue
        if not string_in_regex_list(line, white_list.split("\n")):
            l.append(line)
    return l
 
################################################################################
if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--whitelist_file', required=False,
                        help="config file for whitelist", type=str)
    args = parser.parse_args()
    white_list = load_whitelist(args.whitelist_file)
    nonkernel_process_list = get_nonkernel_process()
    process_list = list_process(nonkernel_process_list, white_list)
 
    # Remove header
    print "Identified processes count: %d." % (len(process_list) - 1)
    print "\n".join(process_list)
## File : detect_suspicious_process.py ends