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);
}