Add epylog role to log01.

This commit is contained in:
Kevin Fenzi 2014-07-18 17:50:29 +00:00
parent 8adb643de6
commit 7efe08a558
34 changed files with 3102 additions and 0 deletions

View file

@ -36,6 +36,7 @@
- collectd/base
- collectd/server
- sudo
- epylog
tasks:
- include: "{{ tasks }}/yumrepos.yml"

View file

@ -0,0 +1,6 @@
#!/bin/sh
# Run epylog daily.
#
# just disable this so we don't run the global one anywhere
# better to run a specific one (or ones)
#/usr/sbin/epylog --cron

View file

@ -0,0 +1 @@
30 2,8,14,20 * * * root /usr/sbin/epylog --cron -c /etc/epylog/merged/epylog.conf --last 6h

View file

@ -0,0 +1,15 @@
Alias /epylog /srv/web/epylog
# need these to do the auth
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_file_module modules/mod_authn_file.so
<Directory /srv/web/epylog>
Options FollowSymLinks Indexes
AuthType Basic
AuthName "Fedora Log Server"
AuthBasicProvider file
AuthUserFile /srv/web/epylog/.htpasswd
Require valid-user
</Directory>

View file

@ -0,0 +1,32 @@
##
# Main Epylog configuration file. See epylog.conf(5) for more info.
#
[main]
cfgdir = /etc/epylog/merged
tmpdir = /var/tmp
vardir = /var/lib/epylog/merged
[report]
title = Merged system events: @@LOCALTIME@@
template = /etc/epylog/merged/report_template.html
include_unparsed = yes
publishers = file
[mail]
method = mail
smtpserv = /usr/sbin/sendmail -t
mailto = sysadmin-logs-members@fedoraproject.org
format = plain
lynx = /usr/bin/lynx
include_rawlogs = no
rawlogs_limit = 200
[file]
method = file
path = /srv/web/epylog/merged/
dirmask = %Y-%b-%d_%a
filemask = %H%M
expire_in = 7
notify = sysadmin-logs-members@fedoraproject.org
smtpserv = /usr/sbin/sendmail -t
pubroot = https://admin.fedoraproject.org/epylog/merged

View file

@ -0,0 +1,14 @@
[module]
desc = Common Unparsed Similar Strings Module
exec = /usr/share/epylog/modules/common_unparsed_mod.py
files = /var/log/merged/messages.log[.#.gz], /var/log/merged/secure.log[.#.gz]
enabled = no
internal = yes
outhtml = yes
priority = 10
[conf]
# how similar the strings need to be 0-100 - 0 being not at all (bad idea) 100 being almost exactly.
match_percentage = 95
debug_dump = 0

View file

@ -0,0 +1,10 @@
[module]
desc = KojiLoad summary
exec = /usr/share/epylog/modules/kojiload_mod.py
files = /var/log/merged/messages.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 7
[conf]

View file

@ -0,0 +1,50 @@
[module]
desc = Logins
exec = /usr/share/epylog/modules/logins_mod.py
files = /var/log/merged/messages.log[.#.gz], /var/log/merged/secure.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 0
[conf]
##
# Only enable things useful for your configuration to speed things
# up. The more stuff you enable, the slower matching will be.
#
enable_pam = 1
enable_xinetd = 1
enable_sshd = 1
enable_uw_imap = 0
enable_dovecot = 0
enable_courier = 0
enable_imp = 0
enable_proftpd = 0
##
# This is a fun setting. You can list domains that are "safe" here.
# E.g. if your org's domain is example.com and you generally don't
# expect logins from hosts in example.com domain to be suspicious, you
# can add "example.com$" as a safe domain. This way anyone logging in from
# a remote host not matching *.example.com will be flagged in red and the
# full hostname of the connecting machine will be printed in the report.
# List multiple values separated by comma.
# E.g.: safe_domains = example.com$, foo.edu$
# The default is .*, meaning all domains are considered safe. To turn
# this off specify something like:
# safe_domains = !.*
safe_domains = .*
##
# If you have too many systems, wide-scale probing may turn ugly. This
# will collapse the reports.
systems_collapse = 10
# comma/space separated list of users to ignore - unknown is the internal "no user given"
ignore_users = unknown
# path to where we keep the logins db
loginsdb_path = /var/lib/epylog/logins_db.sqlite
# clean up entries in the db which are more than this many days old
remove_older_than = 14
# time fuzz - default time (in minutes) which is valid fuzzy match for a login to not be listed
time_fuzz = 60

View file

@ -0,0 +1,20 @@
[module]
desc = Mail Report
exec = /usr/share/epylog/modules/mail_mod.py
files = /var/log/merged/mail.log[.#.gz]
enabled = no
internal = yes
outhtml = yes
priority = 5
[conf]
##
# Enable sendmail, postfix, or both
#
enable_sendmail = 1
enable_postfix = 1
enable_qmail = 0
##
# Report at most this many "top things"
#
top_report_limit = 5

View file

@ -0,0 +1,26 @@
[module]
desc = Notices
exec = /usr/share/epylog/modules/notices_mod.py
files = /var/log/merged/messages.log[.#.gz], /var/log/merged/secure.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 7
[conf]
##
# Where is your notice_dist.xml file?
#
notice_dist = /etc/epylog/merged/notice_dist.xml
##
# Add your own notices into notice_local.xml, not into notice_dist.xml!
# This way you don't risk missing future revisions to notice_dist.xml
#
notice_local = /etc/epylog/merged/notice_local.xml
##
# You can list the ids of <notice> members from notice_dist.xml here
# namely, or you can use ALL to enable all of them. There is no need
# to add members from notice_local.xml here -- they will be enabled
# automatically.
#
enable = ALL

View file

@ -0,0 +1,33 @@
[module]
desc = Packet Filter
exec = /usr/share/epylog/modules/packets_mod.py
files = /var/log/merged/messages.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 1
[conf]
##
# Where to look for the trojans list.
#
trojan_list = /etc/epylog/merged/trojans.list
##
# If a remote host hits this many systems, then don't list them namely,
# but collapse them into a nice report, e.g.: [50 hosts]
#
systems_collapse = 5
##
# Useful for massive portscans. Don't list all the ports namely, but
# present them in a collapsed view. E.g.: [50 ports]
ports_collapse = 5
##
# Enable iptables, ipchains, ipfilter, or all three.
#
enable_iptables = 1
enable_ipchains = 1
enable_ipfilter = 0
##
# Sort by any of the following: packets, source, system, port
#
sortby=port

View file

@ -0,0 +1,16 @@
[module]
desc = Rsyncd
exec = /usr/share/epylog/modules/rsyncd_mod.py
files = /var/log/merged/messages.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 7
[conf]
##
# Report this many "top ranking hosts"
#
report_top = 10
ignore_hosts = log02.vpn.fedoraproject.org log02.phx2.fedoraproject.org proxy3.vpn.fedoraproject.org proxy04.vpn.fedoraproject.org proxy6.vpn.fedoraproject.org proxy01.phx2.fedoraproject.org proxy07.vpn.fedoraproject.org proxy02.vpn.fedoraproject.org proxy03.vpn.fedoraproject.org proxy06.vpn.fedoraproject.org collab04.fedoraproject.org hosted04.fedoraproject.org admin.fedoraproject.org proxy01.stg.phx2.fedoraproject.org proxy08.vpn.fedoraproject.org proxy09.vpn.fedoraproject.org

View file

@ -0,0 +1,11 @@
[module]
desc = SELinux Report
exec = /usr/share/epylog/modules/selinux_mod.py
files = /var/log/merged/messages.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 5
[conf]
enable_selinux = 1

View file

@ -0,0 +1,28 @@
[module]
desc = Spamassassin
exec = /usr/share/epylog/modules/spamd_mod.py
files = /var/log/merged/mail.log[.#.gz]
enabled = no
internal = yes
outhtml = yes
priority = 7
[conf]
##
# Report this many "top ranking users"
#
report_top = 10
##
# Consider this the spam threshold when reporting the scores.
# Anything above this will be flagged as spam. The last column shows
# the score and then non-spam/spam in the parenthesis. E.g.:
# -1.3 (10/3) -- the mean score is -1.3, 10 messages under spam_threshold,
# and 3 messages over it.
#
spam_threshold = 5
##
# Rank the top users according to this parameter. Valid entries are:
# "most spammed" -- sorts by users with the topmost score
# "most messages" -- sorts by users who received most messages
#
sort_by = most spammed

View file

@ -0,0 +1,11 @@
[module]
desc = Sudo Report
exec = /usr/share/epylog/modules/sudo_mod.py
files = /var/log/merged/secure.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 5
[conf]
enable_sudo = 1

View file

@ -0,0 +1,30 @@
[module]
desc = Weedeater
exec = /usr/share/epylog/modules/weeder_mod.py
files = /var/log/merged/messages.log[.#.gz], /var/log/merged/secure.log[.#.gz]
enabled = yes
internal = yes
outhtml = yes
priority = 9
[conf]
##
# Where to look for a weed_dist.cf file.
#
weed_dist = /etc/epylog/merged/weed_dist.cf
##
# Where to look for a weed_local.cf file
#
weed_local = /etc/epylog/merged/weed_local.cf
##
# This is where it gets interesting.
# If you look into weed_dist.cf, you will notice that the entries
# are listed by section titles. List here only the sections that are
# relevant to your setup to speed things up. The more sections you
# enable, the slower matching will go, as it has to try more
# regexes. Note that [ADD] and [REMOVE] sections in weed_local are
# special, any other sections in that file will be ignored.
#
# You can use 'ALL' to enable all sections.
#
enable = ALL

View file

@ -0,0 +1,87 @@
<?xml version="1.0"?>
<!--
CAUTION:
It is not advised to edit this file! You may miss any future
revisions made to it. Instead, create/edit notice_local.xml and
add your rules to it following the same XML layout as presented in
this file. All members of notice_local.xml will be added
indiscriminately, i.e. you don't have to specify the id of the
<notice> in notices.conf: any notices added in notice_local.xml
will be enabled in the module automatically.
$Revision: 1.4.2.5 $
-->
<notices>
<notice id="gconfd">
<regex>gconfd.*: Failed to get lock.*Failed to create</regex>
<regex>gconfd.*: Error releasing lockfile</regex>
<regex>gconfd.*: .* Could not lock temporary file</regex>
<regex>gconfd.*: .* another process has the lock</regex>
<report>GConf locking errors</report>
</notice>
<notice id="fatalx">
<regex>Fatal X error</regex>
<report>Fatal X errors</report>
</notice>
<notice id="floppy">
<regex>floppy0:|\(floppy\)</regex>
<report>Misc floppy errors</report>
</notice>
<notice id="ypserv">
<regex>ypserv.*:\srefused\sconnect\sfrom\s(\S+):\d+\sto\sprocedure\s(\S+)</regex>
<report>%s denied for %s</report>
</notice>
<notice id="linux_boot" critical="yes">
<regex>kernel:\sLinux\sversion\s(\S*)</regex>
<report>Rebooted with Linux kernel %s</report>
</notice>
<notice id="cdrom_vfs">
<regex>VFS: busy inodes on changed media</regex>
<report>dirty CDROM mount</report>
</notice>
<notice id="cdrom">
<regex>kernel: cdrom: This disc doesn</regex>
<regex>kernel: .*Make sure there is a disc in the drive.</regex>
<report>Misc CDROM errors</report>
</notice>
<notice id="dirty_floppy">
<regex>attempt to access beyond end of device</regex>
<regex>rw=\d+, want=\d+, limit=\d+</regex>
<regex>Directory sread .* failed</regex>
<regex>kernel: bread in fat_access failed</regex>
<report>Dirty floppy mount [non-indicative]</report>
</notice>
<notice id="nfs_timeout" critical="yes">
<regex>nfs: server (\S+) not responding</regex>
<regex>nfs: server (\S+) OK</regex>
<report>NFS timeouts to server %s</report>
</notice>
<notice id="insmod">
<regex>insmod: Hint: insmod errors</regex>
<report>insmod errors</report>
</notice>
<notice id="selinux-denied">
<regex>audit\S+:\s+avc:\s+denied\s+\{\s([^\}]+)\s\}.*exe=(\S+).*scontext=(\S+)</regex>
<report>SELinux: denied "%s" for "%s" (scontext=%s)</report>
</notice>
<notice id="crond">
<regex>CROND\S+: \((\S+)\) CMD \(([^\)]+)\)</regex>
<regex>crond\S+: \((\S+)\) CMD \(([^\)]+)\)</regex>
<report>Cron: user '%s' (%s)</report>
</notice>
</notices>

View file

@ -0,0 +1,94 @@
<?xml version="1.0"?>
<!--
This is where you should put your own notice rules. The format is
simple:
<notice id="uniqueid" [critical="yes"]>
<regex>python compliant regex string</regex>
<regex>another regex, if more than one string is needed</regex>
<report>What should go into the report</report>
</notice>
See notice_dist.xml for examples. Any custom notices you add here do
not need to be added into the notices.conf file, as they will be
enabled automatically.
-->
<notices>
<notice id="oom-killer">
<regex>kernel: (\S+) invoked oom-killer.*</regex>
<report>%s invoked oom-killer - see unparsed</report>
</notice>
<notice id="kerneltrace" critical="yes">
<regex>kernel: Call Trace</regex>
<report>kernel call trace - see unparsed for details</report>
</notice>
<!--
<notice id="auditd-down" critical="yes">
<regex>kernel: type=.*audit\(.*</regex>
<report>auditd appears to be down</report>
</notice>
-->
<notice id="Rootkit-hunter-warning" critical="yes">
<regex>Rootkit Hunter:.*Please inspect this machine, because it may be infected.*</regex>
<report>Rootkit Hunter has noticed a potential issue</report>
</notice>
<notice id="brokenpuppetnodetyaml">
<regex>puppet_yamltest: cleaning damaged puppet yaml file:(.*)</regex>
<report>Corrupted yaml file %s</report>
</notice>
<notice id="nf_conntrack" critical="yes">
<regex>kernel: nf_conntrack: table full.*</regex>
<report>Connection tracking table full.</report>
</notice>
<notice id="openvpn_reconnect" critical="yes">
<regex>openvpn\[\d+\]: .*:\d+ \[(.*)\] Peer Connection Initiated with .*:\d+</regex>
<report>openvpn [re]connect from %s.</report>
</notice>
<notice id="openvpn_tls_failed" critical="yes">
<regex>openvpn\[\d+\]: (.*)/.* TLS Error: TLS handshake failed</regex>
<report>openvpn TLS handshake failed: %s</report>
</notice>
<notice id="openvpn_tls_failed_time" critical="yes">
<regex>openvpn\[\d+\]: (.*)/.* TLS Error: TLS key negotiation failed ot occur within.*</regex>
<report>openvpn TLS handshake failed - timeout: %s</report>
</notice>
<notice id="openvpn_bad_packet_id" critical="yes">
<regex>openvpn\[\d+\]: (.*)/.* Authenticate/Decrypt packet error: bad packet ID.*</regex>
<report>openvpn auth/decrypt - bad packet id: %s</report>
</notice>
<notice id="stunnel_websocket" critical="no">
<regex>stunnel:.*websockets accepted connection from (.*):.*</regex>
<report>stunnel: websocket connection from %s</report>
</notice>
<notice id="nagios_alerts" critical="yes">
<regex>nagios:.*HOST.*ALERT:.*</regex>
<report>nagios alerts: </report>
</notice>
<notice id="nagios_pages" critical="yes">
<regex>nagios:.*HOST.*NOTIFICATION:.*kevin-emergency.*</regex>
<report>nagios pages: </report>
</notice>
<notice id="totp-success">
<regex>totp\.cgi.*: Success: user=(\S+),.*host=(\S+),</regex>
<report>totpcgi: %s from %s (Success)</report>
</notice>
<notice id="totp-failure" critical="yes">
<regex>totp\.cgi.*: Failure: user=(\S+),.*host=(\S+),</regex>
<report>totpcgi: %s from %s (Failure)</report>
</notice>
<notice id="EXT4-error" critical="yes">
<regex>kernel:.* EXT4-fs error.*</regex>
<report>EXT4 Error/disk failure noticed</report>
</notice>
</notices>

View file

@ -0,0 +1,22 @@
<html>
<head>
<title>@@TITLE@@</title>
<style type="text/css">
h1 {color: gray; border-bottom: 3px double silver}
h2,h3 {color: gray; border-bottom: 1px solid silver}
</style>
</head>
<body>
<h1>@@HOSTNAME@@</h1>
<p>First event: <strong>@@STARTTIME@@</strong><br />
Last event: <strong>@@ENDTIME@@</strong></p>
<hr />
@@MODULE_REPORTS@@
<hr />
<h2>Unparsed Strings:</h2>
@@UNPARSED_STRINGS@@
<hr />
<p align="right">Brought to you by
<a href="http://linux.duke.edu/projects/epylog/">@@VERSION@@</a></p>
</body>
</html>

View file

@ -0,0 +1,410 @@
1/udp Sockets des Troie
2/tcp Death
30/tcp Agent 40421
31/tcp Agent 31
41/tcp Deep Throat
48/tcp DRAT
58/tcp DMSetup
59/tcp DMSetup
79/tcp CDK
81/tcp RemoConChubo
99/tcp Hidden Port
121/tcp Attack Bot
133/tcp Farnaz
142/tcp NetTaxi
146/tcp Infector
146/udp Infector
170/tcp A-trojan
334/tcp Backage
411/tcp Backage
420/tcp Breach
421/tcp TCP Wrappers trojan
455/tcp Fatal Connections
456/tcp Hackers Paradise
513/tcp Grlogin
514/tcp RPC Backdoor
531/tcp Net666, Rasmin
555/tcp Seven-Eleven
605/tcp Secret Service
666/tcp The Ripperz
667/tcp SniperNet
669/tcp DP trojan
692/tcp GayOL
777/tcp AimSpy
808/tcp WinHole
911/tcp Dark Shadow
999/tcp Deep Throat
1000/tcp Der Spaeher
1001/tcp Der Spaeher
1010/tcp Doly Trojan
1011/tcp Doly Trojan
1012/tcp Doly Trojan
1015/tcp Doly Trojan
1016/tcp Doly Trojan
1020/tcp Vampire
1024/tcp NetSpy
1025/tcp Remote Storm
1025/udp Remote Storm
1035/tcp Multidropper
1042/tcp BLA trojan
1045/tcp Rasmin
1049/tcp /sbin/initd
1050/tcp MiniCommand
1053/tcp The Thief
1054/tcp AckCmd
1080/tcp WinHole
1081/tcp WinHole
1082/tcp WinHole
1083/tcp WinHole
1090/tcp Xtreme
1095/tcp RAT
1097/tcp RAT
1098/tcp RAT
1099/tcp RAT
1150/tcp Orion
1151/tcp Orion
1170/tcp PSS
1200/udp NoBackO
1201/udp NoBackO
1207/tcp SoftWAR
1208/tcp Infector
1212/tcp Kaos
1234/tcp SubSeven
1243/tcp BackDoor-G
1245/tcp VooDoo Doll
1255/tcp Scarab
1256/tcp Project nEXT
1269/tcp Matrix
1272/tcp The Matrix
1313/tcp NETrojan
1338/tcp Millenium Worm
1349/tcp Bo dll
1394/tcp GoFriller
1441/tcp Remote Storm
1492/tcp FTP99CMP
1524/tcp Trinoo
1568/tcp Remote Hack
1600/tcp Shivka-Burka
1703/tcp Exploiter
1777/tcp Scarab
1807/tcp SpySender
1966/tcp Fake FTP
1967/tcp WM FTP Server
1969/tcp OpC BO
1981/tcp Bowl, Shockrave
1999/tcp SubSeven
2000/tcp Der Spaeher
2001/tcp Der Späher
2023/tcp Ripper Pro
2080/tcp WinHole
2115/tcp Bugs
2130/udp Mini Backlash
2140/tcp The Invasor
2140/udp Deep Throat
2155/tcp Illusion Mailer
2255/tcp Nirvana
2283/tcp Hvl RAT
2300/tcp Xplorer
2311/tcp Studio 54
2330/tcp Contact
2331/tcp Contact
2332/tcp Contact
2333/tcp Contact
2334/tcp Contact
2335/tcp Contact
2336/tcp Contact
2337/tcp Contact
2338/tcp Contact
2339/tcp Contact
2339/udp Voice Spy
2345/tcp Doly Trojan
2565/tcp Striker trojan
2583/tcp WinCrash
2600/tcp Digital RootBeer
2716/tcp The Prayer
2773/tcp SubSeven
2774/tcp SubSeven
2801/tcp Phineas Phucker
2989/udp RAT
3000/tcp Remote Shut
3024/tcp WinCrash
3031/tcp Microspy
3128/tcp Ringzero
3129/tcp Masters Paradise
3150/tcp The Invasor
3150/udp Deep Throat
3456/tcp Terror trojan
3459/tcp Eclipse 2000
3700/tcp Portal of Doom
3777/tcp PsychWard
3791/tcp Total Solar Eclypse
3801/tcp Total Solar Eclypse
4000/tcp SkyDance
4092/tcp WinCrash
4242/tcp VHM
4321/tcp BoBo
4444/tcp Prosiak
4567/tcp File Nail
4590/tcp ICQ Trojan
4950/tcp ICQ Trogen (Lm)
5000/tcp Back Door Setup
5001/tcp Back Door Setup
5002/tcp cd00r
5010/tcp Solo
5011/tcp OOTLT
5025/tcp WM Remote KeyLogger
5031/tcp Net Metropolitan
5032/tcp Net Metropolitan
5321/tcp Firehotcker
5333/tcp Backage
5343/tcp wCrat
5400/tcp Back Construction
5401/tcp Back Construction
5402/tcp Back Construction
5512/tcp Illusion Mailer
5534/tcp The Flu
5550/tcp Xtcp
5555/tcp ServeMe
5556/tcp BO Facil
5557/tcp BO Facil
5569/tcp Robo-Hack
5637/tcp PC Crasher
5638/tcp PC Crasher
5742/tcp WinCrash
5760/tcp Portmap Remote Root Linux Exploit
5880/tcp Y3K RAT
5882/tcp Y3K RAT
5882/udp Y3K RAT
5888/tcp Y3K RAT
5888/udp Y3K RAT
5889/tcp Y3K RAT
6000/tcp The Thing
6006/tcp Bad Blood
6272/tcp Secret Service
6400/tcp The Thing
6661/tcp TEMan
6666/tcp Dark Connection Inside
6667/tcp Dark FTP
6669/tcp Host Control, Vampire
6670/tcp BackWeb Server
6711/tcp BackDoor-G
6712/tcp Funny trojan
6713/tcp SubSeven
6723/tcp Mstream
6771/tcp Deep Throat
6776/tcp 2000 Cracks
6838/udp Mstream
6883/tcp Delta Source DarkStar (??)
6912/tcp Shit Heep
6939/tcp Indoctrination
6969/tcp GateCrasher
6970/tcp GateCrasher
7000/tcp Exploit Translation Server
7001/tcp Freak88
7215/tcp SubSeven
7300/tcp NetMonitor
7301/tcp NetMonitor
7306/tcp NetMonitor
7307/tcp NetMonitor
7308/tcp NetMonitor
7424/tcp Host Control
7424/udp Host Control
7597/tcp Qaz
7626/tcp Glacier
7777/tcp God Message, Tini
7789/tcp Back Door Setup, ICKiller
7891/tcp The ReVeNgEr
7983/tcp Mstream
8080/tcp Brown Orifice
8787/tcp Back Orifice 2000
8988/tcp BacHack
8989/tcp Rcon
9000/tcp Netministrator
9325/udp Mstream
9400/tcp InCommand
9872/tcp Portal of Doom
9873/tcp Portal of Doom
9874/tcp Portal of Doom
9875/tcp Portal of Doom
9876/tcp Cyber Attacker, Rux
9878/tcp TransScout
9989/tcp Ini-Killer
9999/tcp The Prayer
10000/tcp OpwinTRojan
10005/tcp OpwinTRojan
10067/udp Portal of Doom
10085/tcp Syphillis
10086/tcp Syphillis
10100/tcp Control Total
10101/tcp BrainSpy
10167/udp Portal of Doom
10520/tcp Acid Shivers
10528/tcp Host Control
10607/tcp Coma
10666/udp Ambush
11000/tcp Senna Spy Trojan Generator
11050/tcp Host Control
11051/tcp Host Control
11223/tcp Progenic trojan
12076/tcp Gjamer
12223/tcp Hack-99 KeyLogger
12345/tcp Ashley
12346/tcp Fat Bitch
12349/tcp BioNet
12361/tcp Whack-a-mole
12362/tcp Whack-a-mole
12363/tcp Whack-a-mole
12623/udp DUN Control
12624/tcp ButtMan
12631/tcp Whack Job
12754/tcp Mstream
13000/tcp Senna Spy
13010/tcp Hacker Brasil - HBR
13013/tcp PsychWard
13014/tcp PsychWard
13223/tcp Hack´99 KeyLogger
13473/tcp Chupacabra
14500/tcp PC Invader
14501/tcp PC Invader
14502/tcp PC Invader
14503/tcp PC Invader
15000/tcp NetDemon
15092/tcp Host Control
15104/tcp Mstream
15382/tcp SubZero
15858/tcp CDK
16484/tcp Mosucker
16660/tcp Stacheldraht
16772/tcp ICQ Revenge
16959/tcp SubSeven
16969/tcp Priority
17166/tcp Mosaic
17300/tcp Kuang2 the virus
17449/tcp Kid Terror
17499/tcp CrazzyNet
17500/tcp CrazzyNet
17569/tcp Infector
17593/tcp Audiodoor
17777/tcp Nephron
18753/udp Shaft
19864/tcp ICQ Revenge
20000/tcp Millenium
20001/tcp Millenium
20002/tcp AcidkoR
20005/tcp Mosucker
20023/tcp VP Killer
20034/tcp NetBus
20203/tcp Chupacabra
20331/tcp BLA trojan
20432/tcp Shaft
20433/udp Shaft
21544/tcp GirlFriend, Kid Terror
21554/tcp Exploiter
22222/tcp Donald Dick
23005/tcp NetTrash
23006/tcp NetTrash
23023/tcp Logged
23032/tcp Amanda
23432/tcp Asylum
23456/tcp Evil FTP
23476/tcp Donald Dick
23476/udp Donald Dick
23477/tcp Donald Dick
23777/tcp InetSpy
24000/tcp Infector
25685/tcp Moonpie
25686/tcp Moonpie
25982/tcp Moonpie
26274/udp Delta Source
26681/tcp Voice Spy
27374/tcp Bad Blood
27444/udp Trinoo
27573/tcp SubSeven
27665/tcp Trinoo
28678/tcp Exploiter
29104/tcp NetTrojan
29369/tcp ovasOn
29891/tcp The Unexplained
30000/tcp Infector
30001/tcp ErrOr32
30003/tcp Lamers Death
30029/tcp AOL trojan
30100/tcp NetSphere
30101/tcp NetSphere
30102/tcp NetSphere
30103/tcp NetSphere
30103/udp NetSphere
30133/tcp NetSphere
30303/tcp Sockets des Troie
30947/tcp Intruse
30999/tcp Kuang2
31335/tcp Trinoo
31336/tcp Bo Whack, Butt Funnel
31337/tcp Back Fire
31337/udp Back Orifice
31338/tcp Back Orifice
31338/udp Deep BO
31339/tcp NetSpy (DK)
31666/tcp BOWhack
31785/tcp Hack´a´Tack
31787/tcp Hack´a´Tack
31788/tcp Hack´a´Tack
31789/udp Hack´a´Tack
31790/tcp Hack´a´Tack
31791/udp Hack´a´Tack
31792/tcp Hack´a´Tack
32001/tcp Donald Dick
32100/tcp Peanut Brittle
32418/tcp Acid Battery
33270/tcp Trinity
33333/tcp Blakharaz
33577/tcp Son of PsychWard
33777/tcp Son of PsychWard
33911/tcp Spirit 2000
34324/tcp Big Gluck
34444/tcp Donald Dick
34555/udp Trinoo
35555/udp Trinoo
37237/tcp Mantis
37651/tcp Yet Another Trojan - YAT
40412/tcp The Spy
40421/tcp Agent 40421
40422/tcp Masters Paradise
40423/tcp Masters Paradise
40425/tcp Masters Paradise
40426/tcp Masters Paradise
41337/tcp Storm
41666/tcp RBT
44444/tcp Prosiak
44575/tcp Exploiter
47262/udp Delta Source
49301/tcp OnLine KeyLogger
50130/tcp Enterprise
50505/tcp Sockets des Troie
50766/tcp Fore
51966/tcp Cafeini
52317/tcp Acid Battery 2000
53001/tcp RWS
54283/tcp SubSeven
54320/tcp Back Orifice 2000
54321/tcp Back Orifice 2000
55165/tcp File Manager trojan
55166/tcp WM Trojan Generator
57341/tcp NetRaider
58339/tcp Butt Funnel
60000/tcp Deep Throat
60001/tcp Trinity
60068/tcp Xzip 6000068
60411/tcp Connection
61348/tcp Bunker-Hill
61466/tcp TeleCommando
61603/tcp Bunker-Hill
63485/tcp Bunker-Hill
64101/tcp Taskman
65000/tcp Devil
65390/tcp Eclypse
65421/tcp Jade
65432/tcp The Traitor (= th3tr41t0r)
65432/udp The Traitor (= th3tr41t0r)
65534/tcp /sbin/initd
65535/tcp RC1 trojan

View file

@ -0,0 +1,179 @@
##
# NOTE:
# Editing this file is not recommended. If you do, you might miss newer
# revisions of this list in the future versions.
# See weed_local.cf for instructions on how to add or delete rules.
#
[pam]
\(pam_unix\).*: session closed for
\(pam_unix\).*: check pass;
[dhcpd]
dhcpd: DHCPREQUEST
dhcpd: DHCPACK
dhcpd: DHCPDISCOVER
dhcpd: DHCPOFFER
dhcpd: DHCPRELEASE
dhcpd: DHCPINFORM
[rpc]
rpc.mountd: authenticated mount request from
rpc.mountd: authenticated unmount request
rpc.statd.*: Version .* Starting
rpc.statd.*: Caught signal 15, un-registering and exiting
[automount]
automount.*: expired
automount.*: attempting to mount entry
automount.*: lookup\(file\): .* failed
automount.*: starting automounter
automount.*: using kernel protocol
automount.*: shutting down
automount.*: .* No such key in map
[crond]
CROND.*: \(mailman\) CMD \(/usr/bin/python
CROND.*: \(root\) CMD \(.*/sbin/rmmod -as\)
CROND.*: \(root\) CMD \(/usr/lib/sa/sa\d
CROND.*: \(root\) CMD \(run-parts
anacron.*: Updated timestamp for job
[bind]
named.*: lame server resolving
named.*: .* NS points to CNAME
named.*: Response from unexpected source
named.*: .* All possible A RR's lame
named.*: bad referral
named.*: Cleaned cache
named.*: USAGE
named.*: NSTATS
named.*: XSTATS
named.*: .* points to a CNAME
named.*: denied update from
named.*: .* Bogus LOOPBACK
[gnome]
gnome-name-server.*: input condition is:
gnome-name-server.*: name server starting
gnome-name-server.*: starting
gnome-name-server.*: name server was running
gconfd.*: Resolved address
gconfd.*: GConf server is not in use
gconfd.*: Exiting
gconfd.*: starting
gconfd.*: .* shutting down cleanly
gdm.*: Couldn't authenticate user
xscreensaver.*: FAILED LOGIN
[sshd]
sshd.*: Generating new .* key.
sshd.*: .* key generation complete
sshd.*: Connection closed
sshd.*: Could not reverse map address
sshd.*: Received disconnect from
sshd.*: error: Could not get shadow information for
sshd.*: Invalid user .* from
[xinetd]
xinetd.*: .* Transport endpoint is not connected
xinetd.*: EXIT:
[uw-imap]
imapd.*: AUTHENTICATE
imapd.*: Logout
imapd.*: Killed
imapd.*: imap.*service init
imapd.*: Command stream end of file
imapd.*: Autologout
imapd.*: Connection reset by peer
ipop3d.*: AUTHENTICATE
ipop3d.*: Logout
ipop3d.*: Killed
ipop3d.*: Autologout
ipop3d.*: pop3.*service init
[courier-imap]
imapd.*: Connection, ip=\[\S+\]
imapd.*: LOGOUT, user=\S+, ip=\[\S+\]
imapd.*: Disconnected, ip=\[\S+\]
imapd.*: DISCONNECTED, user=\S+, ip=\[\S+\]
imapd.*: LOGOUT, ip=\[\S+\]
pop3d.*: Connection, ip=\[\S+\]
pop3d.*: LOGOUT, user=\S+, ip=\[\S+\]
pop3d.*: Disconnected, ip=\[\S+\]
pop3d.*: DISCONNECTED, user=\S+, ip=\[\S+\]
pop3d.*: LOGOUT, ip=\[\S+\]
[postfix]
postfix/smtp\[\d+\]: connect to
postfix/smtp\[\d+\]: warning: no MX host
postfix/smtp\[\d+\]: warning: numeric domain name in resource data
postfix/smtp\[\d+\]: warning: host .* with my own hostname
postfix/smtpd.*: connect from
postfix/smtpd.*: disconnect from
postfix/smtpd.*: TLS connection established
postfix/smtpd.*: lost connection
postfix/cleanup
postfix/pickup
[sendmail]
sendmail\[.*:.*NOQUEUE: Null connection from
sendmail\[.*:.*timeout waiting for input
[qmail]
qmail:.* new msg
qmail:.* end msg
qmail:.* status:
[spamd]
spamd\[.*: info:
spamd\[.*: processing message
spamd\[.*: checking message
spamd\[.*: connection from
spamd\[.*: Creating default_prefs
[printer]
printer: ready to print
printer: status change
printer: printing
printer: peripheral low-power state
[pumpd]
pumpd.*: renewed lease for interface
pumpd.*: configured interface
[afpd]
afpd.*: ASIP session:
afpd.*: afp_flushfork:
afpd.*: .*B read,.*B written
[ntpd]
ntpd.*: kernel time discipline status change
[kernel]
kernel: application .* uses obsolete OSS audio interface
kernel: SELinux: initialized
kernel: device .* left promiscuous mode
kernel: .*: disabled promiscuous mode
usb-uhci.c: interrupt, status
PCI: Found IRQ
PCI: Sharing IRQ
PCI: Setting latency timer
kernel: agpgart: Found
kernel: agpgart: Putting
[misc]
modprobe: Can't locate module
logger: punching nameserver .* through the firewall
HORDE\[\S*\s*\[imp\] Logout
LOGIN ON tty.
dhclient: DHCPREQUEST
dhclient: DHCPACK
dhclient: DHCPDISCOVER
dhclient: bound to
dbus: avc: .* buckets used
## $Revision: 1.14.2.4 $ ##

View file

@ -0,0 +1,305 @@
[ADD]
##
# Here is where you add your own rules
#
ansible.*: Invoked.*
ansible-accelerate:.*
auditd.*: Audit daemon rotating log files
collectd.*: Filter subsystem.*
collectd.*: Value too old.*
collectd.*: processes plugin: Failed to read from.*
dbus.*:.*avc:.*received.*
dbus.*:.*Reloaded configuration.*
dbus.*:.*Successfully activated service 'org.fedoraproject.Setroubleshootd'.*
dbus.*:.*\[system\].*Activating.*using servicehelper.*
dbus-daemon.*:.*Successfully activated service \'org.fedoraproject.Setroubleshootd\'.*
dhclient.*: bound to.*
dhclient.*: DHCPDISCOVER.*
dhclient.*: DHCPACK.*
dhclient.*: DHCPREQUEST.*
dhcpd:.*Wrote.*leases file.*
dnsmasq-dhcp.*
# work around bug https://bugzilla.redhat.com/show_bug.cgi?id=947989
dhclient.*: send_packet: Operation not permitted
dhclient.*: dhclient.c:2663: Failed to send 300 byte long packet over fallback interface.
dhclient.*: Internet Systems Consortium DHCP Client.*
dhclient.*: Copyright 2004-2013 Internet Systems Consortium.
dhclient.*: All rights reserved.
dhclient.*: For info, please visit https://www.isc.org/software/dhcp/
dhclient.*: Listening on.*
dhclient.*: Sending on.*
dhclient.*: Sending on.*
dhclient.*: $
freshclam.*: Can't connect to port 80 of host.*
freshclam.*: connect_error:.*
freshclam.*: Downloading.*
freshclam.*:.*is up to date.*
freshclam.*:.*updated.*
freshclam.*: Database updated.*
freshclam.*: ClamAV update process started
git-daemon.*: Connection from.*
git-daemon.*: Connection reset by peer
git-daemon.*: .* does not appear to be a git repository
git-daemon.*: Extended attributes.*
git-daemon.*: Request upload-pack.*
git-daemon.*: The remote end hung up unexpectedly
git-daemon.*: userpath.*
git-daemon.*: Request upload-archive for.*
git-daemon.*: fatal: write error: Connection timed out
groupadd.*: group added to.*: name=(mockbuild|dialout|floppy|cdrom|tape|utmp|utempter|dbus|avahi-autoipd|rpc|rpcuser|nfsnobody|ssh_keys).*
(group|user)add.*: new (user|group): name=(mockbuild|dialout|floppy|cdrom|tape|utmp|utempter|dbus|avahi-autoipd|rpc|rpcuser|nfsnobody|ssh_keys).*
heartbeat.* info:.*
heartbeat.*:info.*
heartbeat.*:WARN: Gmain_timeout_dispatch: Dispatch function for retransmit request took too long to execute.*
in.tftpd.*: tftp: client does not accept options
kernel:.*CPU.*power limit.*
kernel:.*dma-pl330 fff3d000.dma: Reset Channel.*
kernel: TCPv6: Possible SYN flooding on port 80. Sending cookies.
kernel: TCPv6: Possible SYN flooding on port 80. Dropping request.
kernel: possible SYN flooding on port 80. Sending cookies.
kernel: EXT4-fs \(.*\): mounted filesystem with ordered data mode.*
kernel: ioctl32\(e2fsck.*
kernel: ioctl32\(resize2fs.*
kernel: md: data-check of RAID array.*
kernel: md: delaying data-check of.*
kernel: md: md.*: data-check done.
kernel: md: minimum _guaranteed_ speed.*
kernel: md: using 128k window.*
kernel: md: using maximum available idle IO bandwidth.*
kernel: printk.*suppressed.
kernel: __ratelimit:.*callbacks suppressed
kernel:.*subj=.*
kernel:.*exe=.* \(sauid=.*, hostname=.* addr=.* terminal=.*\)
kernel:.*type=.*audit\(.*
kernel:.*audit_printk_skb:.*callbacks suppressed
lvm.*: Another thread is handling an event. Waiting...*
nagios: Auto-save of retention data completed successfully
nagios: CURRENT.*
nagios: EXTERNAL COMMAND.*
nagios: LOG.*
nagios: PASSIVE SERVICE CHECK.*
nagios: SERVICE ALERT.*
nagios: SERVICE FLAPPING ALERT.*
nagios: SERVICE NOTIFICATION.*
nagios: Warning:.*Passive check result was received for service.*
nagios: Warning: The results of service.* are stale.*
named.*: .* general: info:.*
named.*: .* notify: info:.*
named.*: .* general: error: zone.*unchanged. zone may fail to transfer to slaves.
named.*: .* resolver: notice: DNS format error from.*: invalid response
named.*: .* resolver: notice: DNS format error from.*: non-improving referral
named.*: .* security: info: client.*: view.*: query (cache).*denied
named.*: .* edns-disabled: info: success resolving.*after.*
named.*: .* security: info: client.*denied
named.*: .* rate-limit: info:.*
named.*: .* general: warning: checkhints: view.*
NetworkManager.*: \<info\>.*
NetworkManager.*: \<warn\>.*
ntpd.*: synchronized.*
ntpd.*: time reset.*
openvpn.*: Auth read bytes.*
openvpn.*: CLIENT_LIST.*
openvpn.*: END
openvpn.*: event_wait : Interrupted system call.*
openvpn.*: GLOBAL_STATS.*
openvpn.*: HEADER.*
openvpn.*: OpenVPN STATISTICS
openvpn.*: post-compress bytes.*
openvpn.*: post-decompress bytes.*
openvpn.*: pre-compress bytes.*
openvpn.*: pre-decompress bytes.*
openvpn.*: ROUTING_TABLE.*
openvpn.*: TCP/UDP.*
openvpn.*: TCP/UDP.*
openvpn.*: TIME.*
openvpn.*: TITLE.*
openvpn.*: TUN/TAP.*
openvpn.*: UDPv4 link (local|remote).*
openvpn.*: SIGUSR1.*
openvpn.*: Updated.*
openvpn.*:.*Re-using SSL/TLS context.*
openvpn.*:.*LZO compression.*
openvpn.*: NOTE: the current --script-security setting may allow this configuration to call user-defined scripts.*
openvpn.*: WARNING: No server certificate verification method has been enabled.*
pam_unix\(.*\): account .* has password changed in future
postfix/anvil.*: statistics.*
postfix/bounce.*sender non-delivery notification.*
postfix/error.*:.*delivery temporarily suspended.*Connection timed out.*
postfix/error.*:.*delivery temporarily suspended.*No route to host.*
postfix/error.*:.*delivery temporarily suspended.*temporarily deferred due to user complaints.*
postfix/error.*:.*delivery temporarily suspended.*while receiving the initial server greeting.*
postfix/error.*:.*delivery temporarily suspended.*Host or domain name not found.*
postfix/error.*:.*delivery temporarily suspended.*Connection refused.*
postfix/error.*:.*delivery temporarily suspended.*conversation with.*
postfix/error.*:.*delivery temporarily suspended.*service not available, closing transmission channel.*
postfix/error.*:.*delivery temporarily suspended.*Network is unreachable.*
postfix/error.*:.*refused to talk to me.*
postfix/lmtp.*:.*250.*Ok.*
postfix/lmtp.*: 503.*
postfix/local.*: table.*has changed -- restarting.*
postfix/master.*: daemon started.*
postfix/master.*: terminating on signa.*
postfix/pipe.*:.*delivered via spamassassin.*
postfix/postfix-script.*: starting the Postfix mail system
postfix/postfix-script.*: stopping the Postfix mail system
postfix/postfix-script.*: waiting for the Postfix mail system to terminate
postfix/scache.*: statistics.*
postfix/smtp.*: 400.*
postfix/smtp.*: 421.*
postfix/smtp.*: 450.*
postfix/smtp.*: 451.*
postfix/smtp.*: 452.*
postfix/smtp.*: 454.*
postfix/smtp.*: 503.*
postfix/smtp.*: conversation.* timed out.*
postfix/smtpd.*: table.*has changed -- restarting.*
postfix/smtpd.*: timeout.*
postfix/smtpd.*: too many errors after RCPT.*
postfix/smtp.*: enabling PIX.*
postfix/smtp.*: lost connection.*
postfix/smtp.*:.*refused to talk to me.*
postfix/smtp.*: warning: malformed domain name.*
postfix/smtp.*: warning: valid_hostname:.*
postfix/smtp.*:.*yahoo.*refused to talk to me.*
puppet(d|-agent).*: Applying.*
puppet(d|-agent).*: Caching catalog for.*
puppet(d|-agent).*: Caching certificate for.*
puppet(d|-agent).*: Compiled.*
puppet(d|-agent).*: Could not request certificate:.*
puppet(d|-agent).*: Creating a new SSL key for
puppet(d|-agent).*: \(/File.*
puppet(d|-agent).*: FileBucket.*
puppet(d|-agent).*: Finished.*
puppet(d|-agent).*: Loading facts in datacenter
puppet(d|-agent).*: Loading facts in distrorelease
puppet(d|-agent).*: Loading facts in git_exec_path
puppet(d|-agent).*: Loading facts in libdir
puppet(d|-agent).*: Loading facts in location
puppet(d|-agent).*: Loading facts in pythonsitelib
puppet(d|-agent).*: Loading facts in pythonsitearch
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/datacenter.rb
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/distrorelease.rb
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/git_exec_path.rb
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/libdir.rb
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/location.rb
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/pythonsitelib.rb
puppet(d|-agent).*: Loading facts in /var/lib/puppet/lib/facter/pythonsitearch.rb
puppet(d|-agent).*: Retrieving plugin
puppet(d|-agent).*: Run of Puppet configuration client already in progress; skipping
puppet(d|-agent).*: \(/Stage.*
puppet(d|-agent).*: Failed to set SELinux context system_u:object_r:var_t:s0 on /srv/reviewboard/htdocs/media/rb
puppet(d|-agent).*: Failed to set SELinux context system_u:object_r:var_t:s0 on /srv/reviewboard/htdocs/media/djblets
puppet-master.*: Compiled.*
python.*: ansible-<stdin>.*
ResourceManager.*: info:.*
restorecond: Reset file context /etc/aliases.*
restorecond: Reset file context /var/db/shadow.db.*
restorecond: Unable to watch.*
Rootkit Hunter: Rootkit hunter.*
Rootkit Hunter: Scanning.*
root: time debug:.*
rpc.idmapd.*: nss_getpwnam: name.*apache.*
rpc.idmapd.*: nss_getpwnam: name.*masher.*
rpc.idmapd.*: nss_getpwnam: name.*root@fedora.*
rpc.idmapd.*: nss_getpwnam: name.*root@localdomain*
rsyncd.*: building.*
rsyncd.*: connect from.*
rsyncd.*: file has vanished:
rsyncd.*: name lookup failed for.*
rsyncd.*: rsync: connection unexpectedly closed.*
rsyncd.*: rsync error: error in rsync protocol data stream.*
rsyncd.*: sent.*
#rsync.*: rsync on.*
rsyslogd-2163:epoll_ctl failed
#goofy-ass rsyslogd error :(
^\(\':\',.*
setfiles: relabeling .*
spamc.*: connect to spamd on.*
spamc.*: skipped message, greater.*
spamd.*: bayes: cannot open bayes databases.*
spamd.*: logger: removing.*
spamd.*: prefork.*
spamd.*: pyzor:.* error: TERMINATED
spamd: result:.*
spamd.*: spamd: clean message.*
spamd.*: spamd: clean message.*
spamd.*: spamd: handled cleanup.*
spamd.*: spamd: identified spam.*
spamd.*: spamd: server killed.*
spamd.*: spamd: server pid.*
spamd.*: spamd: server started.*
spamd.*: spamd: server successfully.*
spamd.* spamd: setuid to.*
sshd.*: Address.*maps to.*but this does not map back to the address - POSSIBLE BREAK-IN ATTEMPT.*
sshd.*: Did not receive identification.*
sshd.*: Disconnecting: Too many authentication failures for root.*
sshd.*: error: connect_to
sshd.*: error: ssh_selinux_setup_pty:
sshd.*: Found matching RSA key:.*
sshd.*: input_userauth_request: invalid user.*
sshd.*: pam_unix\(sshd:session\): session closed for user.*
sshd.*: pam_unix\(sshd:session\): session opened for user.*
sshd.*: Postponed publickey for.*
sshd.*: refused connect from.*
sshd.*: reverse mapping checking getaddrinfo.*POSSIBLE BREAK-IN ATTEMPT.*
sshd.*: Server listening on.*
sshd.*: subsystem request for sftp
sshd.*: pam_namespace.*: Unmount of \/tmp failed, Device or resource busy.*
sshd.*: Set /proc/self/oom_score_adj.*
sshd.*: Connection from.* port.*
sshd.*: Transferred: sent.*, received.*bytes
sshd.*: Closing connection to.*port.*
sshd.*: User child is on pid.*
sshd.*: Read error from remote host.*: Connection reset by peer
sshd.*: error: Could not load host key: /etc/ssh/ssh_host_dsa_key
sshd.*: Starting session: command.*
stunnel:.*websockets connected remote.*
stunnel:.*SSL_read.*
stunnel:.*Connection reset.*
stunnel:.*connect_blocking.*
stunnel:.*Connection closed.*
su: pam_unix\(su-l:session\): session .* for user dbbackup.*
su: pam_unix\(su-l:session\): session .* for user postgres.*
runuser: pam_unix\(runuser-l:session\).* session opened for user postgres by.*
runuser: pam_unix\(runuser-l:session\).* session closed for user postgres
systemd-logind.*
systemd.*: Start.*
systemd.*: Stop.*
systemd.*: Reached.*
systemd: pam_unix\(systemd-user:session\): session opened for user root by (uid=0)
systemd: pam_unix\(systemd-user:session\): session closed for user root
systemd: pam_unix\(systemd-user:session\): session.*
systemd.*: Start.* Cleanup of Temporary Directories.*
systemd-machine-id-setup.*: Initializing machine ID.*
systemd.*: Created slice user-0.slice.
systemd.*: Removed slice user-0.slice.
systemd.*: Received SIGRTMIN\+24 from PID.*
unix_chkpwd.*: account .* has password changed in future
userhelper.*: running \'/usr/sbin/mock.*
groupadd.*: new group.*
groupadd.*: group added to /etc/g.*
useradd.*: new user.*
varnishd.*: Child .* said missing \)CLI.*
varnishd.*: Child .* said nothing to repeatCLI result.*
xinetd.*: Exiting.*
xinetd.*: FAIL: git per_source_limit.*
xinetd.*: readjusting service rsync
xinetd.*: Reconfigured.*
xinetd.*: Started.*
xinetd.*: Starting reconfiguration
xinetd.*: Swapping defaults
xinetd.*: xinetd Version.*
ykksm.*: SUCCESS.*
ykval.*: LOG_INFO.*
ykval.*: LOG_WARNING.*
ykval.*: SUCCESS.*
ykval.*: WARNING.*
yum.*: Installed:.*
yum.*: Updated:.*
[REMOVE]
##
# Here is where you put the rules (VERBATIM) from the weed_dist.cf file
#

View file

@ -0,0 +1,12 @@
[module]
desc = Common Unparsed Similar Strings Module
exec = /usr/share/epylog/modules/common_unparsed_mod.py
files = /var/log/messages[.#] /var/log/secure[.#]
enabled = yes
internal = yes
outhtml = yes
priority = 5
[conf]
# how similar the strings need to be 0-100 - 0 being not at all (bad idea) 100 being almost exactly.
match_percentage = 95

View file

@ -0,0 +1,118 @@
#!/usr/bin/python -tt
"""
This module should run after all other modules.
Takes the remaining logs, saves them out to a tmpfile.
Uses difflib.SequenceMatcher() to return logs which occur most often and are
at least a set percentage similar. This lets you catch logs which are
from multiple machines and more or less the same or similar logs (with memory
or process id offsets) from the same machine.
"""
import sys
import re
import difflib
from operator import itemgetter
import tempfile
import os
import shutil
##
# This is for testing purposes, so you can invoke this from the
# modules directory. See also the testing notes at the end of the
# file.
#
sys.path.insert(0, '../py/')
from epylog import Result, InternalModule
class common_unparsed_mod(InternalModule):
def __init__(self, opts, logger):
InternalModule.__init__(self)
self.logger = logger
rc = re.compile
self.match_percentage = int(opts.get('match_percentage', '95'))
self.debug_dump = int(opts.get('debug_dump', '1'))
self.regex_map = {rc('^.+$'):self.expand_out_line}
self.tmpdir = tempfile.mkdtemp(prefix='epylog-common-unparsed', dir='/var/tmp')
self.matchfile = self.tmpdir + '/match_limited'
self.matchfile_f = open(self.matchfile, 'w')
self.complete = self.tmpdir + '/complete'
self.complete_f = open(self.complete, 'w')
##
# Line-matching routines
#
def expand_out_line(self, linemap):
sys, msg, mult = self.get_smm(linemap)
matchout = '%s\n' % (msg)
com_out = '%s' % (linemap['line'])
for i in range(0, int(mult)):
self.complete_f.write(com_out)
self.matchfile_f.write(matchout)
#dirty like zebra
if not os.path.exists(self.tmpdir + '/returned'):
open(self.tmpdir + '/returned', 'w').close()
return {'match':0}
else:
return None
def finalize(self, rs):
#FIXME - enable a debug mode where it writes
# out to a file all of the first line and things which match it
# and percentages of match for later investigation
self.complete_f.close()
self.matchfile_f.close()
matches = {}
full_matches = {}
lines_matched = set()
where = 0
rl = open(self.matchfile, 'r')
for l in rl:
where += 1
sub_where = 0
for ol in open(self.matchfile, 'r'):
sub_where += 1
if sub_where < where: # if we're before it in the file we've already matched it
continue
if sub_where in lines_matched:
continue
c = difflib.SequenceMatcher(isjunk=lambda x: x in ('1','2','3','4','5','6','7','8','9','0'),a=l, b=ol)
rq_ratio = int(c.real_quick_ratio()*100) # do the fast upper bound - find out if we should even glance at it.
if rq_ratio < 60:
continue
ratio = int(c.ratio()*100)
if ratio >= self.match_percentage:
lines_matched.add(sub_where)
if l not in matches:
matches[l] = 0
full_matches[l] = []
matches[l] += 1
full_matches[l].append((ol,ratio))
if self.debug_dump:
fm_db = open(self.tmpdir + '/debug-match', 'w')
for k in full_matches:
fm_db.write(k)
for (v,r) in full_matches[k]:
fm_db.write(' %s %s' % (r, v))
fm_db.close()
res = "<table border=0><tr><th>Count</th><th align=left>Log</th></tr>\n\n"
for (k,v) in sorted(matches.items(), key=itemgetter(1), reverse=True)[:20]: # take the top 20 most common provided there are more than 1
if v > 1:
res += "<tr>\n<td bgcolor='#DDDDDD'>%s</td><td>%s</td>\n</tr>" % (v, k)
res += "<tr>\n<td colspan=2>\n<h2>Complete messages</h2>\n<pre>\n"
res += ''.join(sorted(open(self.complete, 'r').readlines()))
res += "</pre>\n</td>\n</tr>\n</table>"
return res
if __name__ == '__main__':
from epylog.helpers import ModuleTest
ModuleTest(common_unparsed_mod, sys.argv)

View file

@ -0,0 +1,10 @@
[module]
desc = KojiLoad summary
exec = /usr/share/epylog/modules/kojiload_mod.py
files = /var/log/messages[.#]
enabled = no
internal = yes
outhtml = yes
priority = 7
[conf]

View file

@ -0,0 +1,102 @@
#!/usr/bin/python -tt
"""
Rsyncd log parsing module for Epylog
"""
##
# Copyright (C) 2012 by Red Hat, Inc
# Written by Seth Vidal <skvidal at fedoraproject.org>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
import sys
import re
##
# This is for testing purposes, so you can invoke this from the
# modules directory. See also the testing notes at the end of the
# file.
#
sys.path.insert(0, '../py/')
from epylog import Result, InternalModule
class kojiload_mod(InternalModule):
##
# opts: is a map with extra options set in
# [conf] section of the module config, or on the
# command line using -o flag to the module.
# logger: A logging object. API:
# logger.put(loglvl, 'Message')
# Only critical stuff needs to go onto lvl 0.
# Common output goes to lvl 1.
# Others are debug levels.
#
def __init__(self, opts, logger):
##
# Do a "super-init" so the class we are subclassing gets
# instantiated.
#
InternalModule.__init__(self)
self.logger = logger
##
# Convenience
#
rc = re.compile
#kojiload: Load: 7.1 Total: 192.0 Use: 3.7% (Very Light Load)
self.regex_map = {
rc('kojiload: Load:.*'): self.load_results
}
# dict to store all of our data
self.loads = [] # list of kojiload percentages
self.kojiloads = rc('kojiload: Load: (.*) Total: (.*) Use: (.*)\%.*')
def load_results(self, linemap):
(sys, msg, multi) = self.get_smm(linemap)
load, total, use_percent = self.kojiloads.search(msg).groups()
for i in range(multi):
self.loads.append(float(use_percent))
return {(load,total): 1}
def finalize(self, resultset):
##
# A resultset is a dictionary of all values returned by your
# handler functions -- except they are unique and show how many
# times each tuple occurs.
# See epylog.Result for some convenience methods to use when
# processing and analyzing the results.
#
if not self.loads:
return "No kojiloads returned, that seems odd."
max_load = max(self.loads)
min_load = min(self.loads)
avg_load = sum(self.loads)/len(self.loads)
foo = "Max: %s%%<br>\nMin: %s%%<br>\nAvg: %.1f%%<br>\n" % (max_load,
min_load, avg_load)
return foo
##
# This is useful when testing your module out.
# Invoke without command-line parameters to learn about the proper
# invocation.
#
if __name__ == '__main__':
from epylog.helpers import ModuleTest
ModuleTest(kojiload_mod, sys.argv)

View file

@ -0,0 +1,849 @@
#!/usr/bin/python -tt
"""
Description will eventually go here.
"""
##
# Copyright (C) 2003 by Duke University
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# $Id$
#
# @Author Konstantin Ryabitsev <icon@linux.duke.edu>
# @version $Date$
#
import sys
import re
import time
import os
import sqlite3 as sqlite
sys.path.insert(0, '../py/')
from epylog import Result, InternalModule
def executeSQL(cursor, query, params=None):
"""
Execute a python 2.5 (sqlite3) style query.
@param cursor: A sqlite cursor
@param query: The query to execute
@param params: An optional list of parameters to the query
"""
if params is None:
return cursor.execute(query)
return cursor.execute(query, params)
class logins_mod(InternalModule):
def __init__(self, opts, logger):
InternalModule.__init__(self)
self.logger = logger
self.opts = opts
rc = re.compile
self.ignore = 0
self.open = 1
self.failure = 2
self.root_open = 11
self.root_failure = 12
self.pam_ignore = []
self.xinetd_ignore = []
self.logins_db = opts.get('loginsdb_path', '/var/lib/epylog/logins_db.sqlite') # where to keep the loginsdb
self.time_fuzz = int(opts.get('time_fuzz', 60)) # how much to fuzz the time in minutes (default 60m)
remove_older_than = int(opts.get('remove_older_than', 14)) # time in days to start remove from the db
self.oldest_to_keep = time.time() - (remove_older_than*86400)
if remove_older_than == '0': # if it is zero then don't delete any, ever - hah your funeral
self.oldest_to_keep = None
ig_users = opts.get('ignore_users', '')
ig_users.replace(',',' ')
self.ignore_users = ig_users.split(' ')
self.db_cx = None
##
# PAM reports
#
pam_map = {
rc('\(pam_unix\)\S*:.*authentication\s*failure'): self.pam_failure,
rc('\(pam_unix\)\S*:\ssession\sopened\sfor'): self.pam_open,
rc('\(pam_unix\)\S*:\sbad\susername'): self.pam_baduser,
rc('\(pam_unix\)\S*:\sauth\scould\snot'): self.pam_chelper_failure,
rc('pam_krb5\S*:\s\S+\ssucceeds\sfor'): self.pam_krb5_open,
rc('pam_krb5\S*:\s\S+\sfails\sfor'): self.pam_krb5_failure
}
##
# XINETD reports
#
xinetd_map = {
rc('xinetd\S*: START:'): self.xinetd_start
}
##
# SSH reports
#
sshd_map = {
rc('sshd\[\S*: Accepted'): self.sshd_open,
rc('sshd\[\S*: Failed'): self.sshd_failure
}
##
# IMAPD and IPOP3D
#
uw_imap_map = {
rc('imapd\[\S*: Login\sfail'): self.uw_imap_failure,
rc('imapd\[\S*: Authenticated\suser'): self.uw_imap_open,
rc('imapd\[\S*: Login\suser'): self.uw_imap_open,
rc('ipop3d\[\S*: Login\sfail'): self.uw_imap_failure,
rc('ipop3d\[\S*: Login\suser'): self.uw_imap_open,
rc('ipop3d\[\S*: Auth\suser'): self.uw_imap_open
}
##
# IMP
#
imp_map = {
rc('IMP\[\S*: Login'): self.imp2_open,
rc('IMP\[\S*: FAILED'): self.imp2_failure,
rc('HORDE\[\S*\s*\[imp\] Login'): self.imp3_open,
rc('HORDE\[\S*\s*\[imp\] FAILED'): self.imp3_failure
}
##
# DOVECOT
#
dovecot_map = {
rc('imap-login:\sLogin:\s'): self.dovecot_open,
rc('imap-login:\sAborted\slogin\s'): self.dovecot_failure
}
##
# Courier-IMAP
#
courier_map = {
rc('\sLOGIN,\suser=\S+,\sip=\[\S+\]'): self.courier_open,
rc('\sLOGIN FAILED,\sip=\[\S+\]'): self.courier_failure
}
##
# Cyrus-IMAP
#
cyrus_map = {
rc('imapd\[\S*: login:'): self.cyrus_open,
rc('pop3d\[\S*: login:'): self.cyrus_open,
rc('imapd\[\S*: badlogin:'): self.cyrus_failure,
rc('pop3d\[\S*: badlogin:'): self.cyrus_failure
}
##
# Qpopper
#
qpopper_map = {
rc('apop\[\S*:\s\S+\sat\s.*\s\(\S*\):\s-ERR\s\[AUTH\]'): self.qpopper_failure,
rc('apop\[\S*:\s\S+\sat\s.*\s\(\S*\):\s-ERR\s\[IN-USE\]'): self.qpopper_failure,
rc('apop\[\S*:\s\(\S*\)\sPOP\slogin'): self.qpopper_open
}
##
# ProFTPD
#
proftpd_map = {
rc('proftpd\[\S*:.*USER.*Login successful'): self.proftpd_open,
rc('proftpd\[\S*:.*no such user found'): self.proftpd_failure,
rc('proftpd\[\S*:.*Login failed'): self.proftpd_failure
}
regex_map = {}
if opts.get('enable_pam', "1") != "0": regex_map.update(pam_map)
if opts.get('enable_xinetd', "1") != "0": regex_map.update(xinetd_map)
if opts.get('enable_sshd', "1") != "0":
regex_map.update(sshd_map)
self.pam_ignore.append('sshd')
if opts.get('enable_uw_imap', "0") != "0":
regex_map.update(uw_imap_map)
self.xinetd_ignore.append('imaps')
if opts.get('enable_imp', "0") != "0": regex_map.update(imp_map)
if opts.get('enable_dovecot',"0") != "0": regex_map.update(dovecot_map)
if opts.get('enable_courier',"0") != "0": regex_map.update(courier_map)
if opts.get('enable_cyrus', "0") != "0": regex_map.update(cyrus_map)
if opts.get('enable_qpopper',"0") != "0": regex_map.update(qpopper_map)
if opts.get('enable_proftpd',"0") != "0":
regex_map.update(proftpd_map)
self.pam_ignore.append('ftp')
self.xinetd_ignore.append('ftp')
self.safe_domains = []
safe_domains = opts.get('safe_domains', '.*')
for domain in safe_domains.split(','):
domain = domain.strip()
if domain:
try:
domain_re = rc(domain)
self.safe_domains.append(domain_re)
except:
logger.put(0, 'Error compiling domain regex: %s' % domain)
logger.put(0, 'Check config for Logins module!')
self.regex_map = regex_map
self.pam_service_re = rc('(\S+)\(pam_unix\)')
self.pam_failure_re = rc('.*\slogname=(\S*).*\srhost=(\S*)')
self.pam_failure_user_re = rc('\suser=(\S*)')
self.pam_open_re = rc('.*for user (\S+) by\s(\S*)\s*\(uid=(\S+)\)')
self.pam_failure_more_re = rc('(\S+)\smore\sauthentication\sfailures')
self.pam_baduser_re = rc('\sbad\susername\s\[(.*)\]')
self.pam_chelper_re = rc('password\sfor\s\[(.*)\]')
self.pam_krb5_re = rc("^(\S+?)\[*\d*\]*:\spam_krb5\S*:\sauth.*\sfor\s`(\S+)'")
self.xinetd_start_re = rc('START:\s*(\S*)\s')
self.sshd_open_ruser_re = rc('Accepted\s(\S*)\sfor\s(\S*)\sfrom\s(\S*)\sport\s\d*\sruser\s(\S*)\s*(\S*)')
self.sshd_open_re = rc('Accepted\s(\S*)\sfor\s(\S*)\sfrom\s(\S*)\sport\s\d+\s*(\S*)')
self.sshd_fail_re = rc('Failed\s(\S*)\sfor.*\s(\S+)\sfrom\s(\S*)\sport\s\d*\s*(\S*)')
self.uw_imap_fail_re = rc('auth=(.*)\shost=.*\[(\S*)\]')
self.uw_imap_open_re = rc('user=(.*)\shost=.*\[(\S*)\]')
self.uw_imap_service_re = rc('^(\S*)\[\d*\]:')
self.dovecot_open_re = rc('Login:\s(\S+)\s\[(\S+)\]')
self.dovecot_failure_re = rc('Aborted\slogin\s\[(\S+)\]')
self.courier_open_re = rc('^(\S+?):.*\suser=(\S+),\sip=\[(\S+)\]')
self.courier_failure_re = rc('^(\S+?):.*,\sip=\[(\S+)\]')
self.imp2_open_re = rc('Login\s(\S*)\sto\s(\S*):\S*\sas\s(\S*)')
self.imp2_fail_re = rc('FAILED\s(\S*)\sto\s(\S*):\S*\sas\s(\S*)')
self.imp3_open_re = rc('success\sfor\s(\S*)\s\[(\S*)\]\sto\s\{(\S*):')
self.imp3_fail_re = rc('LOGIN\s(\S*)\sto\s(\S*):\S*\sas\s(\S*)')
self.proftpd_open_re = rc('proftpd\[\S*:.*\[(\S+)\].*USER\s(.*):\sLogin\ssuccessful')
self.proftpd_failure_re = rc('proftpd\[\S*:.*\[(\S+)\].*USER\s([^:\s]*)')
self.qpopper_open_re = rc('user "(.*)" at \(.*\)\s(\S*)')
self.qpopper_fail_re = rc(':\s(.*)\sat\s(\S*)')
self.cyrus_open_re = rc('login:.*\[(\S*)\]\s(\S*)\s')
self.cyrus_fail_re = rc('badlogin:.*\[(\S*)\]\s\S\s(\S*)\sSASL')
self.cyrus_service_re = rc('^(\S*)\[\d*\]:')
self.sshd_methods = {'password': 'pw',
'publickey': 'pk',
'rhosts-rsa': 'rsa',
'rsa': 'rsa',
'hostbased': 'host',
'none': 'none'}
self.report_wrap = '<table width="100%%" rules="cols" cellpadding="2">%s</table>'
self.subreport_wrap = '<tr><th align="left" colspan="3"><h3>%s</h3></th></tr>\n%s\n'
self.root_failures_title = '<font color="red">ROOT FAILURES</font>'
self.root_logins_title = '<font color="blue">ROOT Logins</font>'
self.user_failures_title = '<font color="red">User Failures</font>'
self.user_logins_title = '<font color="blue">User Logins</font>'
self.untrusted_host = '%(system)s::<font color="red">%(rhost)s</font>'
self.flip = ' bgcolor="#dddddd"'
self.line_rep = '<tr%s><td valign="top" width="15%%">%s</td><td valign="top" width="15%%">%s</td><td width="70%%">%s</td></tr>\n'
##
# LINE MATCHING ROUTINES
#
def general_ignore(self, linemap):
restuple = (self.ignore, None, None, None)
return {restuple: 1}
def pam_failure(self, linemap):
action = self.failure
self.logger.put(5, 'pam_failure invoked')
system, message, mult = self.get_smm(linemap)
service = self._get_pam_service(message)
mo = self.pam_failure_re.search(message)
if not mo:
self.logger.put(3, 'Odd pam failure string: %s' % message)
return None
byuser, rhost = mo.groups()
mo = self.pam_failure_user_re.search(message)
if mo: user = mo.group(1)
else: user = 'unknown'
if ((service == 'xscreensaver' and user == 'root')
or service == 'sshd' or service == 'imap'):
##
# xscreensaver will always fail as root.
# SSHD is better handled by sshd part itself.
# Imap failures are caught by imap routines.
# Ignore these.
#
result = self.general_ignore(linemap)
return result
mo = self.pam_failure_more_re.search(message)
if mo: mult += int(mo.group(1))
restuple = self._mk_restuple(action, system, service, user,
byuser, rhost, linemap['stamp'])
return {restuple: mult}
def pam_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
service = self._get_pam_service(message)
if service in self.pam_ignore:
##
# the service will do a much better job.
#
result = self.general_ignore(linemap)
return result
mo = self.pam_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd pam open string: %s' % message)
return None
user, byuser, byuid = mo.groups()
if byuser == '': byuser = self.getuname(int(byuid))
restuple = self._mk_restuple(action, system, service, user, byuser, '', linemap['stamp'])
return {restuple: mult}
def pam_baduser(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.pam_baduser_re.search(message)
if not mo:
self.logger.put(3, 'Odd pam bad user string: %s' % message)
return None
user = mo.group(1)
service = self._get_pam_service(message)
restuple = self._mk_restuple(action, system, service, user, '', '', linemap['stamp'])
return {restuple: mult}
def pam_chelper_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.pam_chelper_re.search(message)
if not mo:
self.logger.put(3, 'Odd pam console helper string: %s' % message)
return None
user = mo.group(1)
service = self._get_pam_service(message)
restuple = self._mk_restuple(action, system, service, user, '', '', linemap['stamp'])
return {restuple: mult}
def pam_krb5_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.pam_krb5_re.search(message)
if not mo:
self.logger.put(3, 'Odd pam_krb5 succeeds line: %s' % message)
return None
service = mo.group(1)
user = mo.group(2)
if service == 'sshd':
##
# sshd_open will do a much better job.
#
result = self.general_ignore(linemap)
return result
restuple = self._mk_restuple(action, system, service, user, '', '', linemap['stamp'])
return {restuple: mult}
def pam_krb5_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.pam_krb5_re.search(message)
if not mo:
self.logger.put(3, 'Odd pam_krb5 failure line: %s' % message)
return None
service = mo.group(1)
user = mo.group(2)
if ((service == 'xscreensaver' and user == 'root')
or service == 'sshd' or service == 'imap'):
##
# xscreensaver will always fail as root.
# SSHD is better handled by sshd part itself.
# Imap failures are caught by imap routines.
# Ignore these.
#
result = self.general_ignore(linemap)
return result
restuple = self._mk_restuple(action, system, service, user, '', '', linemap['stamp'])
return {restuple: mult}
def xinetd_start(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.xinetd_start_re.search(message)
if not mo:
self.logger.put(3, 'Odd xinetd start string: %s' % message)
return None
service = mo.group(1)
if service in self.xinetd_ignore:
##
# the service will do a much better job.
#
result = self.general_ignore(linemap)
return result
restuple = self._mk_restuple(action, system, service, '', '', '', linemap['stamp'])
return {restuple: mult}
def sshd_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
ruser = ''
mo1 = self.sshd_open_ruser_re.search(message)
mo2 = self.sshd_open_re.search(message)
if mo1: method, user, rhost, ruser, service = mo1.groups()
elif mo2: method, user, rhost, service = mo2.groups()
else:
self.logger.put(3, 'Odd sshd open string: %s' % message)
return None
method = self.sshd_methods.get(method, '??')
rhost = self.gethost(rhost)
if not service: service = 'ssh1'
service = '%s(%s)' % (service, method)
restuple = self._mk_restuple(action, system, service, user,
ruser, rhost, linemap['stamp'])
return {restuple: mult}
def sshd_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.sshd_fail_re.search(message)
if not mo:
self.logger.put(3, 'Odd sshd FAILURE string: %s' % message)
return None
method, user, rhost, service = mo.groups()
method = self.sshd_methods.get(method, '??')
rhost = self.gethost(rhost)
if not service: service = 'ssh1'
service = '%s(%s)' % (service, method)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def uw_imap_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
service = self._get_uw_imap_service(message)
service = '%s(uw)' % service
mo = self.uw_imap_fail_re.search(message)
if not mo:
self.logger.put(3, 'Odd imap FAILURE string: %s' % message)
return None
user, rhost = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def uw_imap_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
service = self._get_uw_imap_service(message)
service = '%s(uw)' % service
mo = self.uw_imap_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd imap open string: %s' % message)
return None
user, rhost = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def dovecot_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
service = 'imap(dc)'
mo = self.dovecot_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd dovecot OPEN string: %s' % message)
return None
user, rhost = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def dovecot_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
service = 'imap(dc)'
mo = self.dovecot_failure_re.search(message)
if not mo:
self.logger.put(3, 'Odd dovecot FAILURE string: %s' % message)
return None
rhost = mo.group(1)
rhost = self.gethost(rhost)
user = 'unknown'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def courier_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.courier_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd courier OPEN string: %s' % message)
return None
service, user, rhost = mo.groups()
service = '%s(cr)' % service
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def courier_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.courier_failure_re.search(message)
if not mo:
self.logger.put(3, 'Odd courier FAILURE string: %s' % message)
return None
service, rhost = mo.groups()
service = '%s(cr)' % service
rhost = self.gethost(rhost)
user = 'unknown'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def proftpd_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.proftpd_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd ProFTPD OPEN string: %s' % message)
return None
service = 'ftp(pro)'
rhost, user = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def proftpd_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.proftpd_failure_re.search(message)
if not mo:
self.logger.put(3, 'Odd ProFTPD FAILURE string: %s' % message)
return None
service = 'ftp(pro)'
rhost, user = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def imp2_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.imp2_fail_re.search(message)
if not mo:
self.logger.put(3, 'Odd IMP failure string: %s' % message)
return None
rhost, system, user = mo.groups()
rhost = self.gethost(rhost)
service = 'IMP2'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def imp2_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.imp2_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd IMP open string: %s' % message)
return None
rhost, system, user = mo.groups()
rhost = self.gethost(rhost)
service = 'IMP2'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def imp3_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.imp3_fail_re.search(message)
if not mo:
self.logger.put(3, 'Odd IMP failure string: %s' % message)
return None
rhost, system, user = mo.groups()
rhost = self.gethost(rhost)
service = 'IMP3'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def imp3_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.imp3_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd IMP open string: %s' % message)
return None
user, rhost, system = mo.groups()
rhost = self.gethost(rhost)
service = 'IMP3'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def cyrus_failure(self,linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
service = self._get_cyrus_service(message)
mo = self.cyrus_fail_re.search(message)
if not mo:
self.logger.put(3, 'Odd cyrus FAILURE string: %s' % message)
return None
rhost, user = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def cyrus_open(self,linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
service = self._get_cyrus_service(message)
mo = self.cyrus_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd cyrus open string: %s' % message)
return None
rhost, user = mo.groups()
rhost = self.gethost(rhost)
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def qpopper_failure(self, linemap):
action = self.failure
system, message, mult = self.get_smm(linemap)
mo = self.qpopper_fail_re.search(message)
if not mo:
self.logger.put(3, 'Odd qpopper FAILURE string: %s' % message)
return None
user, rhost = mo.groups()
rhost = self.gethost(rhost)
service = 'qpopper'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
def qpopper_open(self, linemap):
action = self.open
system, message, mult = self.get_smm(linemap)
mo = self.qpopper_open_re.search(message)
if not mo:
self.logger.put(3, 'Odd qpopper open string: %s' % message)
return None
user, rhost = mo.groups()
rhost = self.gethost(rhost)
service = 'qpopper'
restuple = self._mk_restuple(action, system, service, user, '', rhost, linemap['stamp'])
return {restuple: mult}
##
# HELPER METHODS
#
def _mk_restuple(self, action, system, service, user, byuser, rhost, stamp):
if user == '': user = 'unknown'
if user == 'root' or user == 'ROOT':
action += 10
remote = self._mk_userat(byuser, rhost)
restuple = (action, system, service, remote, stamp)
else:
if rhost:
match = 0
for domain_re in self.safe_domains:
if domain_re.search(rhost):
match = 1
break
if not match:
tmp = {'system': system, 'rhost': rhost}
system = self.untrusted_host % tmp
restuple = (action, user, service, system, stamp)
return restuple
def _mk_dots(self, str, lim):
if len(str) > lim:
start = -(lim-2)
str = '..' + str[start:]
return str
def _get_pam_service(self, str):
service = 'unknown'
mo = self.pam_service_re.search(str)
if mo: service = mo.group(1)
return service
def _get_uw_imap_service(self, str):
service = 'unknown'
mo = self.uw_imap_service_re.search(str)
if mo: service = mo.group(1)
return service
def _mk_userat(self, user, host):
if user and host: userat = '%s@%s' % (user, host)
elif user: userat = user
elif host: userat = '@%s' % host
else: userat = 'unknown'
return userat
def _get_cyrus_service(self, str):
service = 'unknown'
mo = self.cyrus_service_re.search(str)
if mo: service = mo.group(1)
return service
def _check_for_login(self, username, service, hostname, tid):
# check if we have a login which matches in the db,
if not os.path.exists(self.logins_db):
return False
p = (username, service, hostname, self.last_entry)
q = "select * from logins where username=? and service=? and host=? and pkey <= ?"
if not self.db_cx:
self._db_cx()
cur = self.db_cx.cursor()
ob = executeSQL(cur, q, p)
for i in ob:
# if we get any matches if they match within the fuzzed time then
# don't show it
if abs(tid - i[7]) <= self.time_fuzz*60:
return True
return False
def _add_login(self, username, action, hostname, timestamp, service, u_from=None):
if not self.db_cx:
self._db_cx()
cur = self.db_cx.cursor()
t_st = time.localtime(int(timestamp))
time_in_day = int(t_st[3]*60) + int(t_st[4])
q = "insert into logins values (NULL, ?, ?, ?, ?, ?, ?, ?)"
p = (action, username, hostname, u_from, service, timestamp, time_in_day)
cur.execute(q, p)
def _db_cx(self):
if not os.path.exists(self.logins_db):
self.db_cx = self._setup_logins_db()
else:
self.db_cx = sqlite.Connection(self.logins_db)
q = "select max(pkey) from logins"
last_e = executeSQL(self.db_cx.cursor(), q)
val = last_e.fetchone()[0]
if not val:
self.last_entry = 0
else:
self.last_entry = val
def _setup_logins_db(self):
schema = [
"""PRAGMA synchronous="OFF";""",
"""CREATE TABLE logins ( pkey INTEGER PRIMARY KEY, action INTEGER,
username TEXT, host TEXT, u_from TEXT, service TEXT,
stamp INTEGER, time_in_day INTEGER);""",
]
cx = sqlite.Connection(self.logins_db)
cursor = cx.cursor()
for cmd in schema:
executeSQL(cursor, cmd)
return cx
##
# FINALIZE!!
#
def finalize(self, rs):
logger = self.logger
##
# Prepare report
#
report = ''
rep = {}
# FIXME
# go through each item in the rs
# feed them into the db
# pull back from the db all the info you need for the report
# simplifies a lot of this code
# chuck it all into the db
for (rt,count) in rs.items():
if rt[0] in (self.root_failure, self.root_open):
(action, host, service, remote, stamp) = rt
user = 'root'
elif rt[0] in (self.open, self.failure):
(action, user, service, host, stamp) = rt
remote = 'NULL'
else:
continue
if user in self.ignore_users:
continue
for num in range(0, count):
self._add_login(user, action, host, stamp, service, remote)
self.db_cx.commit()
#return "lalallala"
for action in [self.root_failure, self.root_open,
self.failure, self.open]:
rep[action] = ''
per_user = {}
flipper = ''
q = """select distinct username, service, host from logins where action = ? and pkey > ?"""
p = (action, self.last_entry)
act_tuple = [(i[0],i[1], i[2]) for i in executeSQL(self.db_cx.cursor(), q, p)]
for entry in act_tuple:
username = entry[0]
if username not in per_user:
per_user[username] = {}
service = entry[1]
if service not in per_user[username]:
per_user[username][service] = []
hn = entry[2]
q = """select time_in_day from logins where username = ? and host = ? and service = ? and action = ? and pkey > ?"""
p = (username, hn, service, action, self.last_entry)
this_logins_times = [row[0] for row in executeSQL(self.db_cx.cursor(), q, p)]
count = 0
for t in this_logins_times:
if not self._check_for_login(username, service, hn, t):
# DEBUG print 'new login %s %s %s %s' % (username, service, hn, t)
count += 1
if count:
per_user[username][service].append('%s(%d)' % (hn, count))
blank = 0
for username in sorted(per_user):
if flipper: flipper = ''
else: flipper = self.flip
for (svc,reps) in per_user[username].items():
if blank: key = '&nbsp;'
else: blank = 1
if reps:
rep[action] += self.line_rep % (flipper, username,
svc, ', '.join(reps))
if rep[self.root_failure]:
report += self.subreport_wrap % (self.root_failures_title,
rep[self.root_failure])
if rep[self.root_open]:
report += self.subreport_wrap % (self.root_logins_title,
rep[self.root_open])
if rep[self.failure]:
report += self.subreport_wrap % (self.user_failures_title,
rep[self.failure])
if rep[self.open]:
report += self.subreport_wrap % (self.user_logins_title,
rep[self.open])
report = self.report_wrap % report
if self.oldest_to_keep:
q = """delete from logins where stamp < ?"""
p = (self.oldest_to_keep,)
executeSQL(self.db_cx.cursor(), q, p)
self.db_cx.commit()
return report
if __name__ == '__main__':
from epylog.helpers import ModuleTest
ModuleTest(logins_mod, sys.argv)

View file

@ -0,0 +1,14 @@
[module]
desc = Rsyncd
exec = /usr/share/epylog/modules/rsyncd_mod.py
files = /var/log/messages[.#]
enabled = no
internal = yes
outhtml = yes
priority = 7
[conf]
##
# Report this many "top ranking hosts"
#
report_top = 10

View file

@ -0,0 +1,219 @@
#!/usr/bin/python -tt
"""
Rsyncd log parsing module for Epylog
"""
##
# Copyright (C) 2003 by Duke University
# Written by Seth Vidal <skvidal at phy.duke.edu>
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
import sys
import re
##
# This is for testing purposes, so you can invoke this from the
# modules directory. See also the testing notes at the end of the
# file.
#
sys.path.insert(0, '../py/')
from epylog import Result, InternalModule
class rsyncd_mod(InternalModule):
##
# opts: is a map with extra options set in
# [conf] section of the module config, or on the
# command line using -o flag to the module.
# logger: A logging object. API:
# logger.put(loglvl, 'Message')
# Only critical stuff needs to go onto lvl 0.
# Common output goes to lvl 1.
# Others are debug levels.
#
def __init__(self, opts, logger):
##
# Do a "super-init" so the class we are subclassing gets
# instantiated.
#
InternalModule.__init__(self)
self.logger = logger
##
# Convenience
#
rc = re.compile
self.regex_map = {
rc('rsyncd\[\d+\]: rsync on'): self.rsync_hosts,
rc('rsyncd\[\d+\]: (?:sent|wrote)\s\S*\sbytes'): self.rsync_results
}
self.topcount = int(opts.get('report_top', 5)) #get report_top, default to 5 if not set
ig_s = opts.get('ignore_hosts', '')
ig_s.replace(',',' ')
self.ignore_hosts = ig_s.split(' ')
# dict to store all of our data
self.rsync_pid_bytes = {}
self.rsync_pid_host = {}
self.rsync_host_loc = rc('rsyncd\[(\d+)\]: rsync\son\s(\S*)\sfrom\s.*\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)')
self.rsync_bytes = rc('rsyncd\[(\d+)\]: (?:sent|wrote)\s(\d+) bytes (?:read|received)\s(\d+) bytes total size (\d+)')
def rsync_hosts(self, linemap):
(sys, msg, multi) = self.get_smm(linemap)
pid, loc, ip = self.rsync_host_loc.search(msg).groups()
host = self.gethost(ip)
if host not in self.ignore_hosts:
self.rsync_pid_host[pid] = (host, loc)
return {(loc, host): 1}
def rsync_results(self, linemap):
(sys, msg, multi) = self.get_smm(linemap)
pid, wbytes, rbytes, tbytes = self.rsync_bytes.search(msg).groups()
self.rsync_pid_bytes[pid] = (wbytes, rbytes, tbytes)
return {(pid, wbytes): 1}
def _uniq(self, s):
"""Return a list of the elements in s, but without duplicates.
For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
unique("abcabc") some permutation of ["a", "b", "c"], and
unique(([1, 2], [2, 3], [1, 2])) some permutation of
[[2, 3], [1, 2]].
For best speed, all sequence elements should be hashable. Then
unique() will usually work in linear time.
If not possible, the sequence elements should enjoy a total
ordering, and if list(s).sort() doesn't raise TypeError it's
assumed that they do enjoy a total ordering. Then unique() will
usually work in O(N*log2(N)) time.
If that's not possible either, the sequence elements must support
equality-testing. Then unique() will usually work in quadratic
time.
"""
n = len(s)
if n == 0:
return []
# Try using a dict first, as that's the fastest and will usually
# work. If it doesn't work, it will usually fail quickly, so it
# usually doesn't cost much to *try* it. It requires that all the
# sequence elements be hashable, and support equality comparison.
u = {}
try:
for x in s:
u[x] = 1
except TypeError:
del u # move on to the next method
else:
return u.keys()
# We can't hash all the elements. Second fastest is to sort,
# which brings the equal elements together; then duplicates are
# easy to weed out in a single pass.
# NOTE: Python's list.sort() was designed to be efficient in the
# presence of many duplicate elements. This isn't true of all
# sort functions in all languages or libraries, so this approach
# is more effective in Python than it may be elsewhere.
try:
t = list(s)
t.sort()
except TypeError:
del t # move on to the next method
else:
assert n > 0
last = t[0]
lasti = i = 1
while i < n:
if t[i] != last:
t[lasti] = last = t[i]
lasti += 1
i += 1
return t[:lasti]
# Brute force is all that's left.
u = []
for x in s:
if x not in u:
u.append(x)
return u
def _sortByVal(self, dict, reverse=0):
if type(dict) is not type({}): return []
keys = dict.keys()
s = map(lambda k: (dict[k], k), keys)
s.sort()
if reverse: s.reverse()
return s
def finalize(self, resultset):
##
# A resultset is a dictionary of all values returned by your
# handler functions -- except they are unique and show how many
# times each tuple occurs.
# See epylog.Result for some convenience methods to use when
# processing and analyzing the results.
#
hostloc = {} # key = host, val = [loc, loc, loc]
hosttotal = {} # key = host val = totalwbytes
foo = "<table border=0>\n\t<tr>\n"
for pid in self.rsync_pid_host.keys():
(host, loc) = self.rsync_pid_host[pid]
if self.rsync_pid_bytes.has_key(pid):
if not hostloc.has_key(host):
hostloc[host] = []
if not hosttotal.has_key(host):
hosttotal[host] = 0L
hostloc[host].append(loc)
bytes = long(self.rsync_pid_bytes[pid][0])
hosttotal[host] += bytes
for host in hostloc.keys():
hostloc[host] = self._uniq(hostloc[host])
hosts = self._sortByVal(hosttotal, 1)
count = 0L
for (tot,host) in hosts[:self.topcount]:
if count % 2:
bgcolor = "#dddddd"
else:
bgcolor = "#ffffff"
count+=1
line = '\t\t<td bgcolor=%s valign=\"top\">%s</td>\n' % (bgcolor, host)
line = line + '\t\t<td bgcolor=%s valign="top">\n' % bgcolor
for loc in hostloc[host]:
line = line + '\t\t\t%s<br>\n' % loc
line = line + '\t\t</td>\n'
size, marker = self.mk_size_unit(hosttotal[host])
line = line + '\t\t<td bgcolor=%s valign="top">%s%s</td>\n' % (bgcolor, size, marker)
line = line + '\t</tr>\n'
foo = foo + line
foo = foo + '</table>\n'
return foo
##
# This is useful when testing your module out.
# Invoke without command-line parameters to learn about the proper
# invocation.
#
if __name__ == '__main__':
from epylog.helpers import ModuleTest
ModuleTest(rsyncd_mod, sys.argv)

View file

@ -0,0 +1,11 @@
[module]
desc = SELinux Report
exec = /usr/share/epylog/modules/selinux_mod.py
files = /var/log/messages[.#]
enabled = yes
internal = yes
outhtml = yes
priority = 5
[conf]
enable_selinux = 1

View file

@ -0,0 +1,116 @@
#!/usr/bin/python -tt
"""
Reports on selinux messages
Jeremy Kindy (kindyjd at wfu.edu), Wake Forest University
"""
import sys
import re
##
# This is for testing purposes, so you can invoke this from the
# modules directory. See also the testing notes at the end of the
# file.
#
sys.path.insert(0, '../py/')
from epylog import Result, InternalModule
class selinux_mod(InternalModule):
def __init__(self, opts, logger):
InternalModule.__init__(self)
self.logger = logger
self.logger.put(3, 'initializing selinux')
rc = re.compile
self.ignore = 0
self.preventing = 1
selinux_map = {
rc('.*setroubleshoot\: SELinux is preventing'): self.selinux
}
do_selinux = int(opts.get('enable_selinux', '1'))
self.regex_map = {}
if do_selinux: self.regex_map.update(selinux_map)
self.selinux_message_re = rc('setroubleshoot: (.*). For complete SELinux')
self.selinux_title = '<font color="blue">SELinux Report</font>'
self.selinux_preventing_title = '<font color="blue">SELinux Prevention Report</font>'
self.report_wrap = '<table border="0" width="100%%" rules="cols" cellpadding="2">%s</table>'
self.subreport_wrap = '<tr><th colspan="2" align="left"><h3>%s</h3></th></tr>\n%s'
self.line_rep = '<tr%s><td valign="top" width="25%%">%s</td><td valign="top" width="75%%">%s</td></tr>\n'
self.flip = ' bgcolor="#dddddd"'
##
# Line-matching routines
#
def selinux(self, linemap):
action = self.preventing
self.logger.put(3, 'selinux invoked')
sys, msg, mult = self.get_smm(linemap)
self.logger.put(3, 'test selinux %d' % mult)
message = self._get_selinux_message(msg)
self.logger.put(3, 'selinux message: %s' % message)
restuple = self._mk_restuple(sys, action, message)
self.logger.put(3, 'selinux finished')
return {restuple: mult}
##
# Helpers
#
def _mk_restuple(self, sys, action, message):
return (action, message, sys)
def _get_selinux_message(self, str):
message = 'unknown'
mo = self.selinux_message_re.search(str)
if mo: message = mo.group(1)
return message
####
# Finalize the report
def finalize(self, rs):
logger = self.logger
##
# Prepare report
#
report = ''
rep = {}
# (action, message)
for action in [self.preventing]:
rep[action] = ''
flipper = ''
for message in rs.get_distinct((action,)):
if flipper: flipper = ''
else: flipper = self.flip
service_rep = []
for system in rs.get_distinct((action, message,)):
service_rep.append(system)
system_list = ', '.join(service_rep)
rep[action] += self.line_rep % (flipper, message, system_list)
if rep[self.preventing]:
report += self.subreport_wrap % (self.selinux_preventing_title, rep[self.preventing])
logger.put(3, 'selinux report: self.preventing added')
report = self.report_wrap % report
return report
if __name__ == '__main__':
from epylog.helpers import ModuleTest
ModuleTest(selinux_mod, sys.argv)

View file

@ -0,0 +1,11 @@
[module]
desc = Sudo Report
exec = /usr/share/epylog/modules/sudo_mod.py
files = /var/log/secure[.#]
enabled = yes
internal = yes
outhtml = yes
priority = 5
[conf]
enable_sudo = 1

View file

@ -0,0 +1,191 @@
#!/usr/bin/python -tt
"""
Reports on sudo usage by users.
Jeremy Kindy (kindyjd at wfu.edu), Wake Forest University
"""
import sys
import re
##
# This is for testing purposes, so you can invoke this from the
# modules directory. See also the testing notes at the end of the
# file.
#
sys.path.insert(0, '../py/')
from epylog import Result, InternalModule
class sudo_mod(InternalModule):
def __init__(self, opts, logger):
InternalModule.__init__(self)
self.logger = logger
self.logger.put(2, 'initializing sudo')
rc = re.compile
self.ignore = 0
self.open = 1
self.not_allowed = 2
sudo_map = {
rc('.*sudo\:\s+\S+\s\:\sTTY'): self.sudo,
rc('.*sudo:'): self.sudo_na
}
do_sudo = int(opts.get('enable_sudo', '1'))
self.regex_map = {}
if do_sudo: self.regex_map.update(sudo_map)
self.sudo_user_name_re = rc('sudo:\s*(\S*)')
self.sudo_as_user_re = rc('.*USER=(\S*)\s\;\sCOMMAND')
self.sudo_command_name_re = rc('.*COMMAND=(.*)')
self.sudo_error_message_re = rc('sudo:\s*\S*\s+:\s+(.*)\s+;\s+TTY')
self.sudo_title = '<font color="blue">User Sudo Report</font>'
self.sudo_open_title = '<font color="blue">User Sudo Report</font>'
self.sudo_not_allowed_title = '<font color="red">Disallowed Sudo Commands</font>'
self.report_wrap = '<table border="0" width="100%%" rules="cols" cellpadding="2">%s</table>'
self.subreport_wrap = '<tr><th colspan="5" align="left"><h3>%s</h3></th></tr>\n%s'
self.subreport_na_wrap = '<tr><th colspan="5" align="left"><h3>%s</h3></th></tr>\n%s'
self.line_rep = '<tr%s><td valign="top" width="15%%">%s</td><td valign="top" width="45%%" colspan="2">%s</td><td width="25%%">%s</td><td width="15%%">%s</td></tr>\n'
self.line_rep_na = '<tr%s><td valign="top" width="15%%">%s</td><td valign="top" width="30%%">%s</td><td valign="top" width="15%%">%s</td><td width="25%%">%s</td><td width="15%%">%s</td></tr>\n'
self.flip = ' bgcolor="#dddddd"'
##
# Line-matching routines
#
def sudo(self, linemap):
action = self.open
self.logger.put(2, 'sudo invoked')
sys, msg, mult = self.get_smm(linemap)
self.logger.put(3, 'test sudo %d' % mult)
user = self._get_sudo_user(msg)
self.logger.put(3, 'sudo user: %s' % user)
asuser = self._get_sudo_as_user(msg)
self.logger.put(3, 'sudo asuser: %s' % asuser)
command_name = self._get_sudo_command_name(msg)
self.logger.put(3, 'sudo command: %s' % command_name)
restuple = self._mk_restuple(sys, action, user, asuser, command_name, None)
self.logger.put(2, 'sudo finished')
return {restuple: mult}
def sudo_na(self, linemap):
action = self.not_allowed
self.logger.put(2, 'sudo_na invoked')
sys, msg, mult = self.get_smm(linemap)
self.logger.put(3, 'test sudo %d' % mult)
user = self._get_sudo_user(msg)
self.logger.put(3, 'sudo user: %s' % user)
asuser = self._get_sudo_as_user(msg)
self.logger.put(3, 'sudo asuser: %s' % asuser)
command_name = self._get_sudo_command_name(msg)
self.logger.put(3, 'sudo command: %s' % command_name)
error_message = self._get_sudo_error_message(msg)
self.logger.put(3, 'sudo error_message: %s' % error_message)
restuple = self._mk_restuple(sys, action, user, asuser, command_name, error_message)
self.logger.put(2, 'sudo finished')
return {restuple: mult}
def sudo_ignore(self, linemap):
restuple = self._mk_restuple(None, self.ignore, None, None, None, None)
return {restuple: 1}
##
# Helpers
#
def _mk_restuple(self, sys, action, user=None, asuser=None, command_name=None, error_message=None):
return (action, user, command_name, asuser, error_message, sys)
#return (sys, action, user, asuser, command_name)
def _get_sudo_user(self, str):
user = 'unknown'
mo = self.sudo_user_name_re.search(str)
if mo: user = mo.group(1)
return user
def _get_sudo_as_user(self, str):
asuser = 'unknown'
mo = self.sudo_as_user_re.search(str)
if mo: asuser = mo.group(1)
return asuser
def _get_sudo_error_message(self, str):
pass_attempts = 0
mo = self.sudo_error_message_re.search(str)
if mo: pass_attempts = mo.group(1)
return pass_attempts
def _get_sudo_command_name(self, str):
command_name = 'unknown'
mo = self.sudo_command_name_re.search(str)
if mo: command_name = mo.group(1)
return command_name
####
# Finalize the report
def finalize(self, rs):
logger = self.logger
##
# Prepare report
#
report = ''
rep = {}
# (action, user, command_name, system, error_message)
for action in [self.open, self.not_allowed]:
rep[action] = ''
flipper = ''
for user in rs.get_distinct((action,)):
#logger.put(2, 'sudo user: %s' % user)
if flipper: flipper = ''
else: flipper = self.flip
service_rep = []
blank = 0
for command_name in rs.get_distinct((action, user)):
for asuser in rs.get_distinct((action, user, command_name)):
for error_message in rs.get_distinct((action, user, command_name, asuser)):
mymap = rs.get_submap((action, user, command_name, asuser, error_message))
#logger.put(2, 'sudo command_name: %s' % command_name)
key2s = []
for key2 in mymap.keys():
hostname = key2[0]
key2s.append('%s(%d)' % (hostname, mymap[key2]))
hostnames = ', '.join(key2s)
#logger.put(2, 'sudo hostnames: %s' % hostnames)
service_rep.append([command_name, hostnames, asuser, error_message])
for svcrep in service_rep:
#logger.put(2, 'sudo svcrep: %s' % svcrep)
if blank: user = '&nbsp;'
else: blank = 1
if (action == self.open):
rep[action] += self.line_rep % (flipper, user, svcrep[0], svcrep[1], svcrep[2])
else:
rep[action] += self.line_rep_na % (flipper, user, svcrep[0], svcrep[3], svcrep[1], svcrep[2])
if rep[self.open]:
report += self.subreport_wrap % (self.sudo_open_title, rep[self.open])
logger.put(2, 'sudo report: self.open added')
if rep[self.not_allowed]:
report += self.subreport_na_wrap % (self.sudo_not_allowed_title, rep[self.not_allowed])
logger.put(2, 'sudo report: self.not_allowed added')
report = self.report_wrap % report
return report
if __name__ == '__main__':
from epylog.helpers import ModuleTest
ModuleTest(sudo_mod, sys.argv)

View file

@ -0,0 +1,48 @@
---
- name: install epylog package
yum: state=installed name=epylog
tags:
- packages
- epylog
- name: create directories needed for epylog
file: state=directory owner=root mode=755
with_items:
- /var/lib/epylog/merged
- /srv/web/epylog
- /srv/web/epylog/merged
- name: setup extra epylog modules
copy: src={{ item }} dest=/usr/share/epylog/modules/{{ item }}
with_items:
- modules/selinux_mod.py
- modules/rsyncd_mod.py
- modules/sudo_mod.py
- modules/common_unparsed_mod.py
- modules/logins_mod.py
- modules/kojiload_mod.py
- name: epylog cron
file: src=epylog-default.cron dest=/etc/cron.d/epylog.cron
tags:
- config
- cron
- name: copy in all the epylog merged files
copy: src=merged dest=/etc/epylog/merged
tags:
- config
- name: epylog merged cron
copy: src=epylog-merged.cron dest=/etc/cron.d/epylog-merged.cron
tags:
- config
- cron
- name: epylog httpd config
copy: src=epylog-web.conf dest=/etc/httpd/conf.d/epylog-web.conf
notify:
- restart httpd
tags:
- config
- apache