home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
ckscripts.zip
/
portlog
< prev
next >
Wrap
Text File
|
2002-01-19
|
9KB
|
230 lines
#!/usr/local/bin/wermit +
; (change the first line to point to C-Kermit 8.0 or later executable)
; (and give this file execute permission)
; p o r t l o g
;
; Absorbs and logs attacks on a given TCP Port, such as 80.
; Sends hourly summaries to the selected e-mail address.
; Uploads hourly logs to the selected FTP destination.
;
; Default port is 80. You can specify a different port as the
; first command-line arg, or you can tell kermit to "define port 443"
; (or whatever) and then "take portlog" or simply "take portlog 443".
; Runs forever. Stop it with Ctrl-C. To run in background, redirect
; stdout and stderr to a file or to /dev/null.
;
; Requires C-Kermit 8.0 later.
;
; Default port is 80 (HTTP). Works for any HTTP attack: Code Red,
; Nimba, etc. Requires privilege for ports < 1000 in UNIX.
; Requires that no other process is listening on the same port.
;
; IMPORTANT: Change all lines marked (*) as needed.
;
; F. da Cruz, Columbia University, September 2001.
; Last update: Fri Sep 21 09:44:38 2001
;
if < \v(version) 800200 exit 1 Fatal - C-Kermit 8.0 required.
local ftppass ; So it will disappear automatically when script terminates.
; PARAMETERS - ADJUST AS NEEDED
.truncate := 0 ;(*) Truncate log records at 79 cols?
.doftp := 1 ;(*) Upload full logs with FTP?
.ftpuser := fdc ;(*) FTP info... CHANGE THIS
.ftphost := ftp.kermit.columbia.edu ;(*) CHANGE THIS
.ftpdir := ~kermit/cu/port80logs ;(*) CHANGE THIS
.address := security@columbia.edu ;(*) E-mail address for summary
.mailcmd := Mail ;(*) External mail command
if match \v(platform) *HP-UX* .mailcmd = mailx
if k-95 .mailcmd = echo ; No way to mail from Windows
if def \%1 .port := \%1 ; Listen port
if not def port .port := 80 ;(*) Default listen port
;(*) The following macro checks if its argument string contains
;(*) an IP address or IP hostname in the local administrative domain.
;(*) CHANGE THE PATTERN to match your own site's addresses.
def CHKLOCAL { ;(*)
if match \%1 *{128.59.*.,160.39.*.,columbia.edu,barnard.edu}* end 0
end 1
}
; END OF ADJUSTABLE PARAMETERS
def NEWLOGNAME { ; Make new log file name
.logfile := \v(host)_\m(port)_\v(ndate)_\freplace(\v(time),:,).log
}
.\%n = 0 ; Event count
.hour := \fstripx(\fstripx(\v(time),:),:) ; Start hour
.start := \fcvtdate() ; Start date-time
newlogname ; Get new log name
define ON_CTRLC { ; Ctrl-C trap
echo INTERRUPTED AT \v(time)...
echo Connections: \%n in \fdiffdate(now,\m(start))
getok "Do dump? [yes or no] "
if success dodump
getok "Debug? [yes or no] "
if success prompt Debug>
getok "Exit? [yes or no] "
if success exit
}
; Routine to summarize, upload, and reset log.
define DODUMP { ; Send summary and start new log
local a \%u \%c \%x
echo "-----------------"
echo REPORTING AT \v(time)...
if ( doftp ) {
set flag off
ftp open \m(ftphost) /user:\m(ftpuser) /password:\m(ftppass)
if \v(ftp_loggedin) {
ftp cd \m(ftpdir)
if success {
ftp put \m(logfile)
if success {
set flag on
ftp chmod 664 \m(logfile)
}
}
}
if not flag echo WARNING: FTP UPLOAD LOG FAILED
ftp bye
}
fopen /read \%c \m(logfile) ; Open current log
if fail end 1 \m(logfile): \f_errmsg() ; Check that we did
.\%n := 0 ; Init record counter
while not \f_eof(\%c) { ; Loop to read each record
fread /line \%c line ; Read one record
if fail break ; Check
incr \%n ; Count
.a := \s(line[19]) ; Remove timestamp
.\%x ::= \findex({"},\m(a)) - 1 ; Remove attack string
.a := \ftrim(\s(a[1:\%x])) ; Remove any surrounding whitespace
.a := \fltrim(\m(a))
_increment aa<\m(a)> ; Count a hit from this host
}
fclose \%c ; Close log file
.\%k := \faaconvert(aa,&a,&b) ; Convert to pair of regular arrays
.\%u := 0 ; Local domain counter
array sort /reverse /numeric b a ; Sort in descending order of hits
.tmpfile := \freplace(\m(logfile),.log,.txt)
fopen /write \%c \m(tmpfile)
if fail end 1 Can't create report file
for \%i 1 \%k 1 { ; Count hits from local domain
chklocal {\&a[\%i]}
if success incr \%u
}
fwrite /line \%c Port \m(port) probe summary on \v(host) -
[\fname2addr(\v(host))]
fwrite /line \%c Interval: \m(start) - \fcvtdate()
fwrite /line \%c
fwrite /line \%c " Hits: \flpad(\%n,5)"
fwrite /line \%c " Unique hosts: \flpad(\%k,5)"
fwrite /line \%c " Unique local hosts: \flpad(\%u,5)"
fwrite /line \%c
for \%i 1 \%k 1 {
fwrite /line \%c \frpad(\&a[\%i],60) \flpad(\&b[\%i],5)
}
fclose \%c
!\m(mailcmd) -s "Port \m(port) Probe Summary" \m(address) < \m(tmpfile)
newlogname ; Get new log name
.start := \fcvtdate() ; New start time etc
.hour := \fstripx(\fstripx(\v(time),:),:)
.\%n := 0
echo NEW LOG: \m(logfile)
}
if K-95 { ; K95: Appropriate window color
set command color white red
cls
}
echo LISTENING ON PORT \m(port)...
; Get FTP access info.
if DOFTP {
echo For uploading logs...
echo Logs will be uploaded hourly by FTP to:
echo Host: \m(ftphost) Directory: \m(ftpdir)
getok " OK? [yes or no] "
if fail .doftp := 0
while doftp {
undef ftppass
while not def ftppass {
askq ftppass { FTP password for \m(ftpuser) at \m(ftphost): }
}
echo Testing...
ftp open \m(ftphost) /user:\m(ftpuser) /password:\m(ftppass)
if success if \v(ftp_loggedin) {
ftp bye
break
}
ftp bye
echo { Test failed - try again.}
}
}
; Here goes...
set input echo off ; Input is logged to a file
set xfer display brief ; No showing off
set tcp reverse-dns off ; For accurate source reporting
while true { ; Loop forever
.x := \fstripx(\fstripx(\v(time),:),:) ; Current hour
if ( != \m(x) \m(hour) ) { ; If hour turned over
dodump ; Send report and reset
if fail echo WARNING: Report failed
}
echo "-----------------"
.stamp := \fcvtdate()
xecho \m(stamp)...
set host * \m(port) ; Wait for incoming connection
if fail {
echo Net Open Failure: \v(errstring)
if ( == \v(errno) 13 || == \v(errno) 48 ) exit 1
hangup
continue
}
clear input ; Capture the attack string
input 8 \10 ; (terminate at linefeed = ASCII 10)
increment \%n ; Count this probe
echo \flpad(\%n,4). \m(stamp): \v(line) ; Log to screen
if ( = 0 \fverify(0123456789.,\v(line)) ) { ; Have IP address
.addr := \v(line)
.name := \faddr2name(\m(addr)) ; Lookup name in DNS
} else { ; Have IP name
.name := \v(line)
.addr := \fname2addr(\m(name)) ; Get its address
}
hangup ; Close connection quickly
.record := \m(stamp): \m(name) [\m(addr)] "\ftrim(\v(input))"
if \m(truncate) if > \flen(\m(record)) 79 .record := \s(record[1:76]).."
set flag off
for \%i 1 3 1 { ; Write to log
fopen /append \%c \m(logfile) ; It might be busy
if fail { ; (can happen in Windows)
echo LOG APPEND FAILURE: \f_errmsg()
sleep \%i
continue
}
fwrite /line \%c \m(record)
if success set flag on
fclose \%c
if flag break
}
if not flag echo RECORD LOST: \m(record)
}