Security Enhancement



stealth - Stealthy File Integrity Scanner


`<uds>' represents the location of the used Unix Domain Socket.

stealth --daemon <uds> --dry-run --log <file-spec> --logmail
--max-size <size>[BKMG] --no-mail --parse-policy-file
--random-interval <seconds> --repeat <seconds>
--skip-files <file-spec> --syslog
--syslog-facility <fac> --syslog-priority <pri> --syslog-tag <tag>
--verbosity <value> policy

stealth --dry-run --log <file-spec> --logmail
--max-size <size>[BKMG] --no-mail --parse-policy-file
--random-interval <seconds> --repeat <seconds>
--run-command <nr> --skip-files <file-spec> --stdout --syslog
--syslog-facility <fac> --syslog-priority <pri> --syslog-tag <tag>
--verbosity <value> policy

stealth {--ping,--reload,--rerun,--resume,--suspend,--terminate} <uds>

stealth --help --version


The name of the stealth program is an acronym of:

SSH-based Trust Enforcement Acquired through a Locally Trusted Host.
Stealth is based on an idea by Hans Gankema and Kees Visser, both at the Center for Information Technology of the University of Groningen. Hopko Meijering provided valuable suggestions for improvement.

Stealth's main task is to perform file integrity tests. However, the testing itself will leave no sediments on the tested computer. Therefore, stealth has stealthy characteristics. This is considered an important feature, improving the security (integrity) of the software of computers monitored by stealth.

Please realize that stealth intends to be just another security tool: other security measures like firewalls, portscanners, intrusion detection systems, dropping unencrypted protocols, etc. are usually required to improve the security of a group of computers that are connected to the Internet. Stealth is a file integrity scanner, and file integrity scanners offer no substitute for those tools (and vv.).

Stealth uses a policy file to determine the actions to perform. Each policy file is uniquely associated with a host being monitored. This host (called the client below) trusts the computer on which stealth runs, called the monitor (hence: a Locally Trusted Host). The monitor performs tasks (normally file integrity tests) that Enforce the Trust we have in the client computer. Since almost all integrity tests can be run on the client, one monitor can control many clients, even if the monitor itself uses aged hard- and software components.

As the monitor and the client are (i.e., should be) different computers, the monitor must communicate with the client in a secure fashion. This is realized through SSH. So, there's another element of `local trust' involved here: the client should permit the monitor to set up a secure SSH connection allowing the monitor to access sensitive elements in the client's file system.

It is important to ensure that public access to the monitor is prevented. No incoming services should be allowed. The only access to the monitor should be via its console and the monitor should be placed in a physically secure location. Sensitive information of clients are stored in the monitor's file system. To access the clients stealth in daemon mode can use a passphrase-protected ssh-key, allowing stealth to perform its tasks thereafter. This, too, makes it important to prevent the monitor from being accessed by unauthorized persons.

If, instead of running stealth in daemon mode it is preferred to let stealth perform single, but automated integrity scans, then new ssh(1) connections may be difficult to establish if the used ssh-key is passphrase-protected. To implement this scenario (i.e., automated integrity scans using passphrase protected ssh-keys) the program ssh-cron(1) can profitably be used.

Stealth's current way of connecting to clients uses a single ssh(1) connection, which results in only a single sshd(1) entry in the client's logfiles, which lasts for the duration of stealth's run. When using stealth in daemon mode this too minimizes the `footprint' stealth has on the client hosts.

The monitor itself normally only requires two types of outgoing services: SSH to reach its clients, and some mail transport agent (e.g., sendmail(1)) to forward its outgoing mail to some mail-hub.

Here is what happens when stealth running using the first synopsis:

If stealth should not be run as a daemon process the second synopsis can be used. In this case stealth performs one or more integrity scans (the latter when the --repreat option was specified). When a single integrity scan is requested stealth terminates after the scan. When --repeat is specified stealth shows a prompt (i.e., `? ') and terminates after pressing the Enter-key.

The third synopsis is used for communication with a stealth daemon. In this case the the Unix Domain Socket defined by the stealth daemon process must be specified after the option specifying the requested command.


Short options are provided between parentheses, immediately following their long option equivalents.

Option descriptions showing (C) can only be used on the command-line, and are ignored when specified in the second section of the policy file.

In the overview of options `<uds>' represents the name of the Unix Domain Socket to use, and `<file-spec>' refers to a (relative or absolute) specification of a file location.

With the first and second synopses relative locations (of the Unix Domain Socket and of other file-specifications) are interpreted relative to the current working directory.

Command-line options overrule options defined in the policy-file.

Only one of the options --daemon, --reload, --resume, --suspend or --terminate can be specified. The options --reload, --rerun, --resume, --suspend, and --terminate ignore any other options.

The following options are still recognized for backward compatibility with stealth pre-3.00 versions and will be removed in a future stealth version. They generate error messages suggesting alternatives:

The following options were discontinued starting since stealth version 3.00.00:

When specifying long options in policy files initial hyphens should be omitted. Here are some examples:

    log /tmp/stealth.log
    verbosity 3


When requesting an IPC command or when starting stealth as a daemon 0 is returned if the command was successfully completed. Otherwise a non-0 value is returned.


Once stealth has started as a foreground or daemon process performing file integrity scans ssh(1) is used to connect to the client(s) monitored by stealth. While stealth runs only one ssh(1) connection is opened to each client. This connection remains active during stealth's lifetime to minimize the number of sshd entries in the client's log files.


The policy file consists of two sections, the second section is optional, and starts at a line merely containing %%.

The policy file's first section consists of two sets of data: use directives (starting with the keyword USE) and commands. Blank lines and information beyond hash-marks (#) are ignored, while lines following lines terminating in backslashes (\) are concatenated (en passant removing these trailing backslashes). Leading white space on lines of the policy file is ignored.

The (optional) second section starts at a line merely containing %%. Following this separating line several long option specifications can be entered (see below at section OPTIONS). Options specified on the command-line take priority over options specified in the policy file. Although the --reload option reloads the policy file, it will not change option values originally specified as command-line options. This section may contain specifications of the skip-files and log options. Relative file locations specified for these options are interpreted relative to the location of the policy file. E.g., if the policy file argument is specified as /root/client/policy then the specification log: client.log results in stealth writing its logs into the file /root/client/client.log.


DEFINE directives are used to associate longer strings of text with certain symbols. E.g., after DEFINE FINDARGS -xdev -type f -exec /usr/bin/sha256sum {} \; the specification ${FINDARGS} may be used in USE DIRECTIVES and commands (see below) to use the text associated with the FINDARGS symbol.

Note that DEFINE symbols may also be used in the definition of other DEFINE symbols as well. Direct or indirect circular definitions should be avoided, as they are either not or incompletely expanded.


The following USE directives may be specified (directives are written in capitals, and should appear exactly as written below: letter casing is preserved). Specifications in angular brackets (like <this>) represent specifications to be provided by stealth's users:

In some installations stealth is used to inspect the monitor itself, even though this is not recommended, as it breaks one of the main reasons for stealth's existence. But in those situations (so, where stealth is used to monitor the integrity of the localhost), /bin/bash could be specified at the USE SSH directive. For example:

    # For stealth inspecting localhost:
        USE SSH /bin/bash --noprofile


Following the USE specifications, commands can be specified. The commands are executed in their order of appearance in the policy file. Processing continues until the last command has been processed or until a tested command (see below) returns a non-zero return value.


The following LABEL commands are available:


LOCAL commands are executed on the monitor itself:

Note that the scp(1) command can be used to copy files between the client and the monitor, using a local command. This, however, is discouraged, as a separate ssh(1)-connection is required for each separate scp(1) command. This subtlety was brought to the author's attention by Hopko Meijerink (

To copy files between the client and the monitor, the GET and PUT commands (described below) should be used instead, as these commands use the existing ssh(1) connection. In general, LOCAL commands should not be used to establish additional ssh(1) connections to a client.


Remote commands are commands executed on the client using the SSH shell. These commands are executed using the standard PATH set for the SSH shell. However, it is advised to specify the full pathname to the programs to be executed, to prevent ``trojan approaches'' where a trojan horse is installed in an `earlier' directory of the PATH-specification than the intended program.

Two special remote commands are GET and PUT, which can be used to copy files between the client and the monitor. Internally, GET and PUT use the DD specification. If a non-default specification is used, one should ensure that the alternate program accepts dd(1)'s if=, of=, bs= and count= options. With GET the options bs=, count= and of= are used, with PUT the options bs=, count= and if= are used. Normally there should be no need to alter the default DD specification.

The GET command may be used as follows:

The PUT command may be used as follows:

Plain commands can be executed on the client computer by merely specifying them. Of course, this implies that programs on the client which are named, e.g., LABEL, LOCAL or USE, cannot be executed, since these names are interpreted otherwise by stealth. It's unlikely that this restriction presents much of a problem....

The following commands are available for execution on the client:

The maximum download size (using GET or CHECK) can be specified using the --max-size option, see below. By default this size is set at 10M.


Since stealth only appends information to the report file, the report file's size may eventually become prohibitively large, and log-rotation may be desirable. It is of course possible to issue a --terminate command, rotate the logfiles, and restart stealth, but stealth also offers a facility to temporarily suspend integrity scans performed by a stealth daemon process: Here is an example of logrotate(1) specification rotating stealth log-files:

/root/stealth/clienthost/small/report /var/log/stealth/clienthost-small.log {
    rotate 4
        /usr/bin/stealth --suspend /root/stealth/client/small.uds
        /usr/bin/stealth --resume /root/stealth/client/small.uds


Here is what happens when stealth is run using the third synopsis:


When using rsyslogd(1) property based filters may be used to filter syslog messages and write them to a file of your choice. E.g., to filter messages starting with the syslog message tag (e.g., STEALTH) use

:syslogtag, isequal, "STEALTH:"   /var/log/stealth.log
:syslogtag, isequal, "STEALTH:"   stop
Note that the colon is part of the tag, but is not specified with the syslog-tag option.

This causes all messages having the STEALTH: tag to be written on /var/log/stealth.log after which they are discarded. More extensive filtering is also supported, see, e.g., and

Time stamps written by rsyslogd are not controlled by stealth's --time-stamp option, but, e.g., by a TZ specification in /etc/default/rsyslog. Simply add the line

    export TZ=UTC
to /etc/default/rsyslog, followed by restarting rsyslogd configures rsyslogd to generate time stamps using UTC.


The following summarizes the advised steps to perform when installing stealth. All these steps are elaborated upon in stealth's User Guide (chapter Running `stealth'):


the policy file;
files under the BASE directory as defined in the policy file;
the report file as defined by the policy's USE REPORT directive.


cron(1), dd(1), diff(1), dpkg(1), find(1), logrotate(1), ls(1), mail(1), sha256sum(1), passwd(5), rsyslog(1), sendmail(1), sh(1), ssh(1), ssh-cron(1)


By default, executed commands are echoed to stderr. Use -q to suppress this echoing.


None reported


This is free software, distributed under the terms of the `GNU General Public License'. Copyright remains with the author. Stealth is found at


Center for Information Technology, University of Groningen.


Frank B. Brokken (