home *** CD-ROM | disk | FTP | other *** search
- #!/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)
- }
-