Attached is an incomplete plugin which I would l like some help testing. It 
looks for traces of common backdoors on IIS web servers, useful in detecting 
worm infections as well trash left around by script kiddies. It has no 
script_id set, so you need to test it from the command line:

$ nasl compromised.nasl -t <ip of web server>

It ugly, its rough, and it needs some feedback before it can become a real 
plugin. If anyone actually has a compromised and/or infected machine that 
they could run this on (hopefully isolated), I would really appreciate any 
details on what it did and did not detect. 

The directory list its using is a static array for now, I am still finishing 
up another plugin which does a brute-force directory scan to determine what 
directories exist on the web server and sets knowledge base keys. The 
compromised.nasl plugin (and a whole slew of others) would depend on this 
plugin and use the directories from the KB. The current webmirror.nasl plugin 
should also feed this directory list from the pages it crawls, I will try to 
make the appropriate changes and send them back, but no guarantee that I will 
have the time for it (So any volunteers?). 

Some things I plan on adding:

* SAM file detection
* HEAD requests for 0-byte TFTP# files
* Checks for NTRESKIT files
* Common file names found on "owned" boxes (output.txt)


Some issues I have run into:

* Sometimes you can't use a GET request (reskit's shutdown.exe ;)
* Some backdoor files won't return a response with GET
* Some broken IIS servers return the "procedure not found" for all DLL's
* There may currently be duplicates
* No information is provided about the plugins findings

Any suggestions, comments, flames?

-HD


For those who can't get attachments:

http://www.digitaloffense.net/nessus/compromised.nasl
# hdm - updated - 04.16.02
# hdm - created - 03.26.02

#
# This script was written by H D Moore
# 


if(description)
{
    script_id(????);
    script_version ("$Revision: 1.0 $");
    name["english"] = "IIS Possible Compromise";
    name["francais"] = "IIS Possible Compromise";
    script_name(english:name["english"], francais:name["francais"]);


    desc["english"] = "IIS Possible Compromise";

    desc["francais"] = "IIS Possible Compromise";

    script_description(english:desc["english"], francais:desc["francais"]);


    summary["english"] = "Searches for traces of a system compromise.";
    summary["francais"] = "Searches for traces of a system compromise.";
    script_summary(english:summary["english"], francais:summary["francais"]);


    script_category(ACT_GATHER_INFO);

    script_copyright( english:"This script is Copyright (C) 2002 Digital Defense Inc.",
                        francais:"Ce script est Copyright (C) 2002 Digital Defense 
Inc.");

    family["english"] = "Backdoors";
    family["francais"] = "Backdoors";
    script_family(english:family["english"], francais:family["francais"]);
    script_dependencie("find_service.nes", "http_version.nasl");
    script_require_keys("www/iis");
    exit(0);
}


#
# The script code starts here
#

debug = 1;


function check(req, pat)
{
    str = http_get(item:req, port:port);
    soc = open_sock_tcp(port);
    if(soc)
    {
        send(socket:soc, data:str);
        r = recv_line(socket:soc, length:16384);
        while(r)
        {
            if(ereg(string:r, pattern:pat))
            {
                close(soc);
                if (debug) display("FOUND: ", url, "\n");
                return(TRUE);
            } else {
                r = recv_line(socket:soc, length:16384);
            }
        }
        close(soc);
    }
    if (debug) display("NOT FOUND: ", url, "\n");
    return(FALSE);
}


function headcheck(req)
{
    str = http_head(item:req, port:port);
    soc = open_sock_tcp(port);
    if(soc)
    {
        send(socket:soc, data:str);
        r = recv_line(socket:soc, length:16384);
        while(r)
        {
            if(ereg(string:r, pattern:"200 OK"))
            {
                close(soc);
                if (debug) display("FOUND: ", url, "\n");
                return(TRUE);
            } else {
                r = recv_line(socket:soc, length:16384);
            }
        }
        close(soc);
    }
    if (debug) display("NOT FOUND: ", url, "\n");
    return(FALSE);
}

########################
# possible directories #
########################

# directories to search
dirs[0] = "/scripts";
dirs[1] = "/scripts/tools";
dirs[2] = "/msadc";
dirs[3] = "/";
dirs[4] = "/C";
dirs[5] = "/D";

###########
# cmd.exe #
###########

# common cmd.exe names
cmd[0] = "cmd.exe";
cmd[1] = "root.exe";
cmd[2] = "bin.exe";
cmd[3] = "shell.exe";
cmd[4] = "hack.exe";
cmd[5] = "1.exe";
cmd[6] = "2.exe";
cmd[7] = "3.exe";
cmd[8] = "4.exe";

# cmd.exe args
cmd_arg = "?/c+echo+Backdoor+Check";

# cmd.exe output
pat_cmd = "Backdoor Check";


##########
# netcat #
##########

# common netcat binary names
nc[0] = "nc.exe";
nc[1] = "ncx.exe";
nc[2] = "netcat.exe";

#nc[3] = "ncx99.exe";   # cant use the -h trick
#nc[4] = "own.exe";     # cant use the -h trick

# netcat args
nc_arg = "?-h";

# netcat output
pat_nc = "this cruft";


################
# iiscrack.dll #
################

# iiscrack.dll
iiscrack_arg = "";

# iiscrack result string
pat_iiscrack = "www.digitaloffense.net";

# common iiscrack.dll names
iiscrack[0] = "iiscrack.dll";
iiscrack[1] = "httpodbc.dll";




###########
# ftp.exe #
###########

# common ftp binary names
ftp[0] = "ftp.exe";
ftp[1] = "ftpx.exe";
ftp[2] = "1.exe";
ftp[3] = "2.exe";
ftp[4] = "3.exe";
ftp[5] = "4.exe";

# ftp args
ftp_arg = "?/c+-h";

# ftp output
pat_ftp = "Suppresses display of remote server";


##################
# firedaemon.exe #
##################

# common ftp binary names
fired[0] = "FireDaemon.exe";
fired[1] = "Fire.exe";
fired[2] = "FireD.exe";

# fired args
fired_arg = "?-h";

# ftp output
pat_fired = "FireDaemon";


###################
# pwdump[1-3].exe #
###################


pwdump[0] = "pwdump.exe";
pwdump[1] = "pwdump2.exe";
pwdump[2] = "pwdump3.exe";

pwdump_arg = "?-h";
pat_pwdump = "You must be running as user|Pwdump2 - dump|software based on pwpump2";



##############
# cmdasp.asp #
##############

cmdasp[0] = "cmdasp.asp";
cmdasp[1] = "cmd.asp";
cmdasp[2] = "shell.asp";
cmdasp[3] = "own.asp";
cmdasp[4] = "0wn.asp";
cmdasp[5] = "exec.asp";

# cmdasp.asp args
cmdasp_arg = "";

# cmdasp.asp output
pat_cmdasp = ".CMD";

##############
# cmd.jsp #
##############

cmdjsp[0] = "cmd.jsp";
cmdjsp[1] = "shell.jsp";
cmdjsp[2] = "own.jsp";
cmdjsp[3] = "hack.jsp";
cmdjsp[4] = "exec.jsp";

# cmd.jsp args
cmdjsp_arg = "";

# cmd.jsp output
pat_cmdjsp = "COMMANDLINE";

#
# These checks are done via HEAD requests
#

########
# IISE #
########

iise[0] = "iise.dll";
iise[1] = "httpodbc.dll";
iise[2] = "idq.dll";
iise[3] = "httpext.dll";
iise[4] = "ssinc.dll";
iise[5] = "msw3prt.dll";
iise[6] = "author.dll";
iise[7] = "admin.dll";
iise[8] = "shtml.dll";
iise[9] = "sspifilt.dll";
iise[10] = "compfilt.dll";
iise[11] = "pwsdata.dll";
iise[12] = "md5filt.dll";
iise[13] = "fpexedll.dll";


#
# These checks are for non-ISAPI DLL's
# 

dll[0] = "admin.dll";                   # nimda and its variants
dll[1] = "vnchooks.dll";                # VNC
dll[2] = "omnithread_rt.dll";           # VNC
dll[3] = "samdump.dll";                 # pwdump2
dll[4] = "JAsfv.dll";                   # ServUFTPD
dll[5] = "LSAExt.dll";                  # pwdump3


dll_arg = "";
pat_dll = "The specified procedure could not be found";


##############
# BEGIN MAIN #
##############

report = "";
port = get_kb_item("Services/www");
if(!port)port = 80;
if(!get_port_state(port)){ exit(0); }


##########################
# outer loop - directories
for (idx_dir = 0; dirs[idx_dir]; idx_dir = idx_dir + 1)
{
    cur_dir = dirs[idx_dir];
    
    
    ##########################
    # cmd.exe
    for (idx_cmd = 0; cmd[idx_cmd]; idx_cmd = idx_cmd + 1)
    {
        cur_cmd = cmd[idx_cmd];
        url = string(cur_dir, "/", cur_cmd);
        request = string(url, cmd_arg);
        
        if (check(req:request, pat:pat_cmd))
        {
            report = string(report, "cmd.exe - ", url, "\n");
        }
    }
    
    ##########################
    # netcat.exe
    for (idx_nc = 0; nc[idx_nc]; idx_nc = idx_nc + 1)
    {
        cur_nc = nc[idx_nc];
        url = string(cur_dir, "/", cur_nc);
        request = string(url, nc_arg);
        
        if (check(req:request, pat:pat_nc))
        {
            report = string(report, "netcat.exe - ", url, "\n");
        }
    }    
    
    ##########################
    # iiscrack.dll
    for (idx_iiscrack = 0; iiscrack[idx_iiscrack]; idx_iiscrack = idx_iiscrack + 1)
    {
        cur_iiscrack = iiscrack[idx_iiscrack];
        url = string(cur_dir, "/", cur_iiscrack);
        request = string(url, iiscrack_arg);
        
        if (check(req:request, pat:pat_iiscrack))
        {
            report = string(report, "iiscrack.dll - ", url, "\n");
        }
    }
        
    ##########################
    # ftp.exe
    for (idx_ftp = 0; ftp[idx_ftp]; idx_ftp = idx_ftp + 1)
    {
        cur_ftp = ftp[idx_ftp];
        url = string(cur_dir, "/", cur_ftp);
        request = string(url, ftp_arg);
        
        if (check(req:request, pat:pat_ftp))
        {
            report = string(report, "ftp.exe - ", url, "\n");
        }
    }    
        
    ##########################
    # firedaemon.exe
    for (idx_fired = 0; fired[idx_fired]; idx_fired = idx_fired + 1)
    {
        cur_fired = fired[idx_fired];
        url = string(cur_dir, "/", cur_fired);
        request = string(url, fired_arg);
        
        if (check(req:request, pat:pat_fired))
        {
            report = string(report, "FireDaemon.exe - ", url, "\n");
        }
    }
        
    ##########################
    # pwdump.exe
    for (idx_pwdump = 0; pwdump[idx_pwdump]; idx_pwdump = idx_pwdump + 1)
    {
        cur_pwdump = pwdump[idx_pwdump];
        url = string(cur_dir, "/", cur_pwdump);
        request = string(url, pwdump_arg);
        
        if (check(req:request, pat:pat_pwdump))
        {
            report = string(report, "pwdump.exe - ", url, "\n");
        }
    }
        
    ##########################
    # cmdasp.asp
    for (idx_cmdasp = 0; cmdasp[idx_cmdasp]; idx_cmdasp = idx_cmdasp + 1)
    {
        cur_cmdasp = cmdasp[idx_cmdasp];
        url = string(cur_dir, "/", cur_cmdasp);
        request = string(url, cmdasp_arg);
        
        if (check(req:request, pat:pat_cmdasp))
        {
            report = string(report, "cmdasp.asp - ", url, "\n");
        }
    }
    
    
    ##########################
    # cmd.jsp
    for (idx_cmdjsp = 0; cmdjsp[idx_cmdjsp]; idx_cmdjsp = idx_cmdjsp + 1)
    {
        cur_cmdjsp = cmdjsp[idx_cmdjsp];
        url = string(cur_dir, "/", cur_cmdjsp);
        request = string(url, cmdjsp_arg);
        
        if (check(req:request, pat:pat_cmdjsp))
        {
            report = string(report, "cmd.jsp - ", url, "\n");
        }
    }
    
    ##########################
    # various "bad" dll's
    for (idx_dll = 0; dll[idx_dll]; idx_dll = idx_dll + 1)
    {
        cur_dll = dll[idx_dll];
        url = string(cur_dir, "/", cur_dll);
        request = string(url, dll_arg);
        
        if (check(req:request, pat:pat_dll))
        {
            report = string(report, cur_dll, " - ", url, "\n");
        }
    }      
    
    #
    # BEGIN HEAD CHECKS
    #
 
    ##########################
    # IISE
    for (idx_iise = 0; iise[idx_iise]; idx_iise = idx_iise + 1)
    {
        cur_iise = iise[idx_iise];
        url = string(cur_dir, "/", cur_iise);
        request = string(url);
        
        if (headcheck(req:request))
        {
            report = string(report, "iise.dll - ", url, "\n");
        }
    }
   
}


if (strlen(report))
{
    report = string("Possible Backdoors:\n", report);
    security_hole(port:port, data:report);
}












Reply via email to