On Thursday 28 November 2002 01:43 pm, Jason Haar wrote:
> >...
> > You definately want to look into it. The "iiscrack.dll" exploit needs
> > to
>
> It also may be a false positive.

Not in this case, check out the (ugly) plugin. 

> I've found that a large number of IIS installs don't return HTTP 404
> error codes on "File not found", but instead return 200 and an HTML
> page saying "File not found" :-/

Each check has a specific signature it looks for, in the case of the 
iiscrack.dll check, it specifically looks for either the link to 
digitaloffense.net or the "MFC Web Server Extension" title. The checks 
which rely on HEAD requests do false positives on servers that return 200 
OK for each request, the new version of the plugin should fix this as 
well as enhance its ability to look for a greater number of clue types.

> [Our IDS reports successful attacks against our IIS server for the
> formmail exploit, when we definitely don't have a /cgi-bin directory on
> it :-)]

Change your formmail signature to look for the response from the CGI 
instead of the request, youre not going to see the alert until its too 
late anyways.

Attached is the latest draft for the new "compromised" plugin, its not 
quite done yet, but you should get a feel for the way the signatures are 
used. Notable exclusions are the rewrites for all of the current HEAD 
request checks, which now verify that the server does not return a 200 OK 
before trying. The DLL checks are being rewritten to use the "DLL" 
method, which looks for the "procedure not found" message (emitted when 
IIS opens a non-ISAPI DLL and cant find the symbols for the version and 
execution functions). 

What really really sucks is that its impossible to remotely check for an 
executable in an executable directory without actualy running it. No 
matter which HTTP method is used (even bogis ones), the program is 
executed and no response is returned. Since some of the things it checks 
for should _never_ be executed (imagine accidently runing shutdown.exe 
when IIS has its security tokens elevated to SYSTEM [like IISE.exe 
does]). Right now I just check for associated DLL's, which are usually 
located in the same directory as the executables. A major drawback right 
now is that the checks assume an executable directory, if the directory 
is simply read only, a request for a DLL will return nthe actual content, 
so I should also look for a content-type of "octet-stream" and the "MZ" 
header in the output.

#
# The script code starts here
#

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);
            if(ereg(pattern:"^HTTP/1\.[01] [25]", string:r))
            {
            while(r)
             {
                if(ereg(string:r, pattern:pat))
                {
                    close(soc);
                    return(TRUE);
                }
                r = recv(socket:soc, length:16384);
             }
        }
        close(soc);
    }        
    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);

            if(ereg(pattern:"^HTTP/1\.[01] (2|502)", string:r))
            {
            if (debug) display("HEAD FOUND: ", req, "\n");
            return(TRUE);
        }
        close(soc);

    }        
    return(FALSE);  
}

function dllcheck(req)
{
    # cheap trick to create an options request
    str = http_get(item:req, port:port);

    soc = open_sock_tcp(port);
    if(soc)
    {
        send(socket:soc, data:str);
        r = recv(socket:soc, length:16384);

        if ("procedure could not be found" >< r)
        {
            if (debug) display("DLL FOUND: ", url, "\n");
            return(TRUE);
        }
        
        close(soc);
    }        
    return(FALSE);  
}


# this exploit hijacks the socket used to make the
# web request, spawning a command shell over it, so we
# cant use the normal detection methods
function iisecheck(req)
{
    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, timeout:20);
            if(ereg(pattern:"We Got It", string:r))
            {
            send(socket:soc, data:string("\r\n\r\nexit\r\n\r\n"));
            close(soc);
            return(TRUE);
        }
        close(soc);
    }        
    return(FALSE);  
}

function reported(url)
{
    found_it = 0;
    for (rep_idx=0; rep_idx <reported_urls_cnt; rep_idx=rep_idx+1)
    {
        if (reported_urls[rep_idx] == url)
        {
            return(1);
        }
    }
    
    reported_urls[reported_urls_cnt] = url;
    reported_urls_cnt = reported_urls_cnt + 1;
}

function add_report(name, url)
{
    if (! reported(url:url))
    {
        report = report + string(name, " - ", url, "\n");
    }
}


# for convenience
dblquot = raw_string(0x22);

# caching found urls
reported_urls[0] = 0;
reported_urls_cnt = 0;


##############
# test index #
##############

tests[0]    = "cmd.exe";
tests[1]    = "nc.exe";
tests[2]    = "iise.exe";
tests[3]    = "ftp.exe";
tests[4]    = "pwdump.exe";
tests[5]    = "cmd.asp";
tests[6]    = "upload.asp";
tests[7]    = "cmd.jsp";
tests[8]    = "radmin";
tests[9]    = "dtreg.exe";
tests[9]    = "kill.exe";
tests[10]   = "hk.exe";
tests[11]   = "list.exe";
tests[12]   = "newgina.dll";
tests[13]   = "iiscrack.dll";

################
# method table #
################

method["cmd.exe"]       = "GET";
method["nc.exe"]        = "GET";
method["iiscrack.dll"]  = "GET";
method["ftp.exe"]       = "GET";
method["pwdump.exe"]    = "GET";
method["cmd.asp"]       = "GET";
method["upload.asp"]    = "GET";
method["cmd.jsp"]       = "GET";
method["radmin"]        = "DLL";
method["dtreg.exe"]     = "GET";
method["kill.exe"]      = "GET";
method["hk.exe"]        = "GET";
method["list.exe"]      = "GET";
method["newgina.dll"]   = "DLL";
method["iise.exe"]      = "IISE";       # this one needs its own method

###################
# arguments table #
###################

args["cmd.exe"]         = "?/c+echo+Backdoor+Check";
args["nc.exe"]          = "?-h";
args["iiscrack.dll"]    = "";
args["ftp.exe"]         = "?/c+-h";
args["pwdump.exe"]      = "?-h";
args["cmd.asp"]         = "";
args["upload.asp"]      = "";
args["cmd.jsp"]         = "";
args["radmin"]          = "";
args["dtreg.exe"]       = "";
args["kill.exe"]        = "";
args["hk.exe"]          = "";
args["list.exe"]        = "";
args["newgina.dll"]     = "";
args["iise.exe"]        = "";

##################
# patterns table #
##################

pats["cmd.exe"]          = "Backdoor Check";
pats["nc.exe"]           = "this cruft";
pats["iiscrack.dll"]     = "www.digitaloffense.net|Default MFC Web Server Extension";
pats["ftp.exe"]          = "Suppresses display of remote server";
pats["pwdump.exe"]       = "You must be running as user|Pwdump2 - dump|software based 
on pwdump2";
pats["cmd.asp"]          = ".CMD";
pats["upload.asp"]       = string("type=", dblquot, "file", dblquot);
pats["cmd.jsp"]          = "COMMANDLINE";
pats["radmin"]           = "";
pats["dtreg.exe"]        = "Syntax: DtReg";
pats["kill.exe"]         = "missing pid or task name";
pats["hk.exe"]           = "lsass pid";
pats["list.exe"]         = "System Process";
pats["newgina.dll"]      = "";
pats["iise.exe"]         = ""; 

##############
# file table #
##############

files["cmd.exe_0"]      = "cmd.exe";
files["cmd.exe_1"]      = "root.exe";
files["cmd.exe_2"]      = "bin.exe";
files["cmd.exe_3"]      = "shell.exe";
files["cmd.exe_4"]      = "hack.exe";
files["cmd.exe_5"]      = "1.exe";
files["cmd.exe_6"]      = "2.exe";
files["cmd.exe_7"]      = "3.exe";
files["cmd.exe_8"]      = "4.exe";
files["cmd.exe_9"]      = "bip.exe";
files["cmd.exe_9"]      = "stromake.exe";
files["cmd.exe_10"]     = "superlol.exe";

files["nc.exe_0"]       = "nc.exe";
files["nc.exe_1"]       = "ncx.exe";
files["nc.exe_2"]       = "netcat.exe";

files["iise.exe_0"]     = "idq.dll";   
files["iise.exe_1"]     = "ida.dll";
files["iise.exe_2"]     = "httpodbc.dll";

files["iiscrack.dll_0"] = "iiscrack.dll";
files["iiscrack.dll_1"] = "httpodbc.dll";
files["iiscrack.dll_2"] = "ida.dll";
files["iiscrack.dll_3"] = "idq.dll";

files["ftp.exe_0"]      = "ftp.exe";
files["ftp.exe_1"]      = "ftpx.exe";
files["ftp.exe_2"]      = "1.exe";
files["ftp.exe_3"]      = "2.exe";
files["ftp.exe_4"]      = "3.exe";
files["ftp.exe_5"]      = "4.exe";

files["pwdump.exe_0"]   = "pwdump.exe";
files["pwdump.exe_1"]   = "pwdump2.exe";
files["pwdump.exe_2"]   = "pwdump3.exe";

files["cmd.asp_0"] = "cmdasp.asp";
files["cmd.asp_1"] = "cmd.asp";
files["cmd.asp_2"] = "shell.asp";
files["cmd.asp_3"] = "own.asp";
files["cmd.asp_4"] = "0wn.asp";
files["cmd.asp_5"] = "exec.asp";

files["upload.asp_0"] = "upload.asp";
files["upload.asp_1"] = "uploadx.asp";
files["upload.asp_2"] = "up.asp";
files["upload.asp_3"] = "file.asp";
files["upload.asp_4"] = "fx.asp";

files["cmd.jsp_0"] = "cmd.jsp";
files["cmd.jsp_1"] = "shell.jsp";
files["cmd.jsp_2"] = "own.jsp";
files["cmd.jsp_3"] = "hack.jsp";
files["cmd.jsp_4"] = "exec.jsp";

files["radmin_0"]    = "admdll.dll";
files["radmin_1"]    = "raddrv.dll";

files["dtreg.exe_0"] = "dtreg.exe";

files["kill.exe_0"] = "kill.exe";
files["kill.exe_1"] = "tkill.exe";
files["kill.exe_2"] = "pkill.exe";

files["hk.exe_0"] = "hk.exe";
files["hk.exe_1"] = "h.exe";

files["list.exe_0"] = "list.exe";
files["list.exe_1"] = "tlist.exe";
files["list.exe_2"] = "plist.exe";

files["newgina.dll_0"] = "newgina.dll";

#dirs[0] = "/"; 
#dirs[1] = "/scripts";
#dirs[2] = "/scripts/tools";
#dirs[3] = "/msadc";

dirs[0] = "/scripts";

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

debug = 1;

report = "";
port = get_kb_item("Services/www");
if(!port) port = 80;

# prevent false positives

ValidHead = 1;
if (headcheck(req:"/CompromisedScan.dll")) ValidHead = 0;

ValidDLL = 1;
if (dllcheck(req:"/CompromisedScan.dll")) ValidDLL = 0;


for (x=0; tests[x]; x=x+1)
{
    cur_test = tests[x];
    cur_meth = method[cur_test];
    cur_args = args[cur_test];
    cur_pat  = pats[cur_test];

    if(debug) display("running test ", x, " (", cur_test, ")", " [", cur_pat, "]\n");
    
    for (d=0; dirs[d]; d=d+1)
    {
        stop = 0;
        for (f=0; stop == 0; f=f+1)
        { 
            filename = files[string(cur_test, "_", f)];
            if (filename)
            {
                if (dirs[d] == "/")
                {
                    url = string("/", filename, cur_args);
                } else {
                    url = string(dirs[d], "/", filename, cur_args);
                }
                
                if (cur_meth == "GET")
                {
                    if (check(req:url, pat:cur_pat))
                    {
                        add_report(name:cur_test, url:url);
                    }
                }
                
                if ((ValidHead == 1) && (cur_meth == "HEAD"))
                {
                    if (headcheck(req:url))
                    {
                        add_report(name:cur_test, url:url);
                    }
                }
                
                if ((ValidDLL == 1) && (cur_meth == "DLL"))
                {
                    if (dllcheck(req:url))
                    {
                        add_report(name:cur_test, url:url);
                    }
                }                
                
                if (cur_meth == "IISE")
                {
                    if (iisecheck(req:url))
                    {
                        add_report(name:cur_test, url:url);
                    }
                }
                                               
            } else {
                stop = 1;
            }
        }
    }
}

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

Reply via email to