Root Crontab Changes

[posted 1999/12/08]

Last summer, we had a couple of security incidents involving root crontab changes (among other things).  Since then, we have been watching the crontabs rather closely.  For a time, whenever a root crontab appeared to have changed, because PIKT reported a change in its timestamp or size, the PIKT alert would show the latest crontab in its entirety.

Good, except that on some systems, the timestamp was being updated daily, evidently because some automated process was rewriting the crontab regularly.  And on those systems, every day we would have to inspect the crontab.  In almost every case, there was no change, else the change was small and hard to discern.

If the timestamp changes, what if instead of dumping the entire crontab we diff it against the previous day's version?  A revised CrontabChkWarning was the result:

CrontabChkWarning

        init
                status active
                level warning
                task "Check for crontab anomalies"
                input proc "=ll =crontabs | =behead"
                =lldata
                keys $name

        rule    // initialize for current crontab
                set #changed = #false()

        rule    // changed size?
                if    #defined(%size)
                   && #size != %size
                        set #changed = #true()
                        output mail "$name has changed size to $text(#size),
                                     was $text(%size)"
                endif

        rule    // changed timestamp?
                if    #defined(%time)
                   && $time ne %time
                        set #changed = #true()
                        output mail "$name has changed timestamp to
                                     $mon $date $time, was %mon %date %time"
                endif

        rule    // if changed, and we have a backup of the previous
                // crontab, diff the current against the previous,
                // else dump the current crontab
                if #changed
                        if -e "=hstdir/crontabs/$name"
                                do #popen(DIFF, "=diff =hstdir/crontabs/$name
                                                 =crontabs/$name", "r")
                                while #read(DIFF) > 0
                                        output mail $rdlin
                                endwhile
                                do #pclose(DIFF)
                                output mail =newline
                        else
                                do #fopen(CRONTAB, "=crontabs/$name", "r")
                                while #read(CRONTAB) > 0
                                        output mail $rdlin
                                endwhile
                                do #fclose(CRONTAB)
                                output mail =newline
                        endif
                endif

        rule    // save current crontab in the histories/crontabs directory
                if ! -d "=hstdir/crontabs"
                        exec wait "=mkdir =hstdir/crontabs;
                                   =chmod 750 =hstdir/crontabs"
                endif
                exec wait "cp -p =crontabs/$name =hstdir/crontabs"

        rule    // report if oddly-named
                if    $command("=egrep " . $squote() . "^?$name:" . $squote() .
                               " /etc/passwd") eq ""
                   && $command("=ypmatch $name passwd 2>/dev/null") eq ""
                        output mail "no such acct:   $inlin=newline"
                endif

        rule    // report if non-root owner
                if    $owner ne "root"
#ifndef generic
#  if db
                   && $owner ne "ingres"
#  endif
#endifdef
                        output mail "suspicious ownership: $inlin=newline"
                        do #fopen(CRONTAB, "=crontabs/$name", "r")
                        while #read(CRONTAB) > 0
                                output mail "    $rdlin"
                        endwhile
                        do #fclose(CRONTAB)
                        output mail =newline
                endif

We added three new rules:  the first, where we initialize a new variable, #changed; the fourth, where we diff the current and previous crontab; and the fifth, where we save the current crontab in the histories/crontab directory.  Note also the modifications to the second and third rules, where we set #changed to #true() if we detect crontab changes.

So, on a typical system, here are the contents of our /pikt/var/histories:

warsaw 508) find /pikt/var/histories -print
/pikt/var/histories
/pikt/var/histories/EMERGENCY.hst
/pikt/var/histories/Debug.hst
/pikt/var/histories/Urgent.hst
/pikt/var/histories/Critical.hst
/pikt/var/histories/Warning.hst
/pikt/var/histories/Info.hst
/pikt/var/histories/Notice.hst
/pikt/var/histories/crontabs
/pikt/var/histories/crontabs/adm
/pikt/var/histories/crontabs/lp
/pikt/var/histories/crontabs/root
/pikt/var/histories/crontabs/sys
/pikt/var/histories/crontabs/uucp

So, you see that your var/histories directory is a natural place to store earlier versions of files, not just .hst files, that you want to compare with their current versions.

Now we still get alerts when crontabs change their timestamp or size, but we just see their diffs, if any.

For more examples, see Developer's Notes.

 
Home | FAQ | News | Intro | Samples | Tutorial | Reference | Software
Developer's Notes | Licensing | Authors | Pikt-Users | Pikt-Workers | Related Projects | Site Index | Privacy Policy | Contact Us
Page best viewed at 1024x768 or greater.   Page last updated 2019-01-12.   This site is PIKT® powered.
Copyright © 1998-2019 Robert Osterlund. All rights reserved.
Home FAQ News Intro Samples Tutorial Reference Software
PIKT Logo
PIKT Page Title
View sample
owners &
permissions changes
script macro