Printable version
Simplified HTML, no CSS
Home

wormstat

    Status : stable
Download : wormstat (6 KB)

This is a simple Perl script I wrote to count the number of attacks from infected MS/IIS reaching my little HTTP server. Since these worms find new targets with simple class C scans, once a client of my ISP is infected, all other clients are attacked. I only focused on MS/IIS worms, because I didn't find any trace of Apache exploits in my logs. Anyway, it is very easy to add a worm signature into the script.

Usage is trivial : edit the first line of code to define where your server log reside. The script only expect the address field (IP or resolved Internet name) to be the first one on every line, which is the default of most HTTP servers.

Displaying results with HTML

If you want to display the live results on a web page, as seen on the home page of this site, I suggest the following setup :

  1. Define a cron job to gather wormstat results in a file every day :
    00 1 * * * root wormstat >/var/lib/wormstat

  2. Insert this PHP code snippet : (download here)
    <table>
     <tr>
      <th>Name</th>
      <th>Hits</th>
      <th>Distinct attackers</th>
      <th>Last hit</th>
     </tr>
    <?php
      
    function disp_worm ($name$url$hits$attackers$last_hit)
      {
        echo 
    " <tr>\n";
        echo 
    "  <td><a href=\"$url\">$name</a>\n";
        echo 
    "  <td>$hits</td>\n";
        echo 
    "  <td>$attackers</td>\n";
        echo 
    "  <td>$last_hit</td>\n";
        echo 
    " </tr>\n";
      }

      
    $statfile fopen ("/var/lib/wormstat""r");
      while (
    $statfile != FALSE && !feof ($statfile))
      {
        
    $line rtrim (fgets ($statfile1024));

        
    // Let's parse wormstat output ('key: value')
        
    list ($key$value) = split (':'$line2);
        
    $value ltrim ($value);
        switch (
    $key)
        {
          case 
    'name'     $w_name $value; break;
          case 
    'URL'      $w_url $value; break;
          case 
    'hits'     $w_hits $value; break;
          case 
    'attackers'$w_attackers $value; break;
          case 
    'last hit' $w_last_hit $value; break;
          case 
    ''         :
            if (
    $prev_key != '')
            {
              
    disp_worm ($w_name$w_url$w_hits$w_attackers$w_last_hit);
              
    $w_last_hit ""// 'last hit' is not always defined, re-init here
            
    }
            break;
        }
        
    $prev_key $key;
      }
      
    fclose ($statfile);
    ?>
    </table>
Contact : Vincent Caron <vincent _at_ zerodeux.net> Last modified on Sunday 26 Jun 2005 15:11