Changes to 11395, 10844, 11142 and http_keepalive.inc

From: Paul Johnston (paulat_private)
Date: Fri Sep 12 2003 - 06:48:05 PDT

  • Next message: Jackson, Dennis: "RE: Changes to 11395, 10844, 11142 and http_keepalive.inc"

    Hi,
    
    I have coded up the change I suggested to stop these plugins causing 
    false positives when the XSS url appears in the response headers. I've 
    added a bodyonly option to http_keepalive_send_recv, and modified the 
    plugins to use this function.
    
    I've tested them against a simple CGI scripts that's vulnerable to all 
    XSS and they work fine, but I don't have vulnerable hosts to test 
    against. And I did check keepalive operation when keepalives disabled - 
    works fine.
    
    Best wishes,
    
    Paul
    
    -- 
    Paul Johnston
    Internet Security Specialist
    Westpoint Limited
    Albion Wharf, 19 Albion Street,
    Manchester, M1 5LN
    England
    Tel: +44 (0)161 237 1028
    Fax: +44 (0)161 237 1031
    email: paulat_private
    web: www.westpoint.ltd.uk
    
    
    
    # -*- Fundamental -*-
    # http_keepalive.inc
    # (C) Renaud Deraison
    # $Id: http_keepalive.inc,v 1.17 2003/06/05 14:08:26 renaud Exp $
    #
    #
    # The only function which should be used by an external plugin is
    # http_keepalive_send_recv(port, data) which returns the result
    # (or NULL if no connection could be established).
    #
    # Note that the file "http_func.inc" must also be included when
    # using this file.
    #
    
    
    __ka_socket = 0;
    __ka_port   = 0;
    __ka_enabled = -1;
    __ka_last_request = "";
    
    
    
    #
    # Based on the last headers we received, we determine if we need
    # to close our socket and re-open it or not
    #
    function http_keepalive_check_connection(headers)
    {
     tmp = egrep(pattern:"^Connection: [Cc]lose", string:headers);
     if(tmp)
     {
         http_close_socket(__ka_socket);
         __ka_socket = http_open_socket(__ka_port);
     }
    }
    
    function enable_keepalive(port)
    {
     __ka_enabled = 1;
     __ka_port    = port;
     __ka_socket  = http_open_socket(port);
    }
    #
    # This function determines if the remote web server is
    # keep-alive-enabled or not.
    #
    function http_keepalive_enabled(port)
    {
      local_var req, soc, r, kb;
    
      kb = get_kb_item(string("www/", port, "/keepalive"));
    
      if(kb == "yes"){
      	enable_keepalive(port:port);
    	return(1);
    	}
      else if(kb == "no")return(0);
    
      req = string("GET / HTTP/1.1\r\n",
    "Connection: Keep-Alive\r\n",
    "Host: ", get_host_name(), "\r\n",
    "Pragma: no-cache\r\n",
    "User-Agent: Mozilla/4.75 [en] (X11, U; Nessus)\r\n\r\n");
    
      soc = http_open_socket(port);
      if(!soc)return NULL;
      send(socket:soc, data:req);
      r = http_recv(socket:soc);
    
    
      # Apache
      if(egrep(pattern:"^Keep-Alive:.*", string:r))
      	{
    	http_close_socket(soc);
    	set_kb_item(name:string("www/", port, "/keepalive"), value:"yes");
    	enable_keepalive(port:port);
        	return(1);
    	}
      else
      	{
    	# IIS
    	send(socket:soc, data:req);
    	r = http_recv(socket:soc);
    	http_close_socket(soc);
    	if(strlen(r)){
    		set_kb_item(name:string("www/", port, "/keepalive"), value:"yes");
    		enable_keepalive(port:port);
    		return(1);
    		}
    	}
    
     set_kb_item(name:string("www/", port, "/keepalive"), value:"no");
     return(0);
    }
    
    
    #
    # This function is akin to http_recv() except that if the last request
    # was a HEAD, we bail out (whereas http_recv() will timeout).
    #
    function http_keepalive_recv(bodyonly)
    {
      local_var headers, body, length, tmp, chunked, killme;
    
      killme = 0;
      length = -1;
      headers = http_recv_headers(__ka_socket);
      if(strlen(headers) == 0)headers = http_recv_headers(__ka_socket);
    
      if(ereg(pattern:"^HEAD.*HTTP/.*", string:__ka_last_request))
       {
       # HEAD does not return a body
       http_keepalive_check_connection(headers:headers);
       if(bodyonly) return("");
       else return(headers);
       }
    
    
      if("Content-Length" >< headers)
      {
        tmp = egrep(string:headers, pattern:"^Content-Length: [0-9]*");
        length = int(ereg_replace(string:tmp, pattern:"^Content-Length: ([0-9]*)", replace:"\1"));
      }
    
    
    
     if((length < 0) && (egrep(pattern:"transfer-encoding: chunked", string:headers, icase:TRUE)))
     {
       while(1)
       {
       tmp = recv_line(socket:__ka_socket, length:4096);
       length = hex2dec(xvalue:tmp);
       if(length > 1024*1024*10)
       	{
       	length = 1024*1024;
    	killme = 1;
    	}
       body  = string(body, recv(socket:__ka_socket, length:length+2, min:length+2));
       if(strlen(body) > 1024*1024*10)killme = 1;
    
       if(length == 0 || killme){
       	http_keepalive_check_connection(headers:headers);
        # This is expected - don't put this line before the previous
       	if(bodyonly) return(body);
        else return(string(headers,"\r\n", body));
    	}
       }
     }
    
    
     if(length >= 0)
     {
       # Don't receive more than 10MB
       if(length > 1024*1024*10)length = 1024*1024;
    
       body = recv(socket:__ka_socket, length:length, min:length);
     }
     else {
     	# If we don't have the length, we close the connection to make sure
    	# the next request won't mix up the replies.
    
     	#display("ERROR - Keep Alive, but no length!!!\n", __ka_last_request);
    	body = recv(socket:__ka_socket, length:16384);
    	http_close_socket(__ka_socket);
    	__ka_socket = http_open_socket(__ka_port);
    	}
    
    
     http_keepalive_check_connection(headers:headers);
     if(bodyonly) return(body);
     else return(string(headers,"\r\n", body));
    }
    
    
    #----------------------------------------------------------------------#
    
    # We close our socket on exit.
    function on_exit()
    {
      if(__ka_socket)
      {
        http_close_socket(__ka_socket);
      }
    }
    
    
    
    #----------------------------------------------------------------------#
    
    
    #
    # This is our "public" Keep-Alive function. It sends <data> to the remote
    # host on port <port>, and returns the result, or NULL if no connection
    # could be established.
    #
    function http_keepalive_send_recv(port, data, bodyonly)
    {
      local_var id, n;
    
      if(__ka_enabled == -1)__ka_enabled = http_keepalive_enabled(port:port);
    
    
    
      if(__ka_enabled == 0)
      {
        local_var soc, r;
        soc = http_open_socket(port);
        if(!soc)return NULL;
        send(socket:soc, data:data);
        headers = http_recv_headers(soc);
        if(headers) body = http_recv_body(socket:soc, headers:headers, length:0);
        http_close_socket(soc);
        if(bodyonly) return(body);
        else return(string(headers, "\r\n", body));
      }
    
    
      if((port != __ka_port)||(!__ka_socket))
      {
        if(__ka_socket)http_close_socket(__ka_socket);
        __ka_port = port;
        __ka_socket = http_open_socket(port);
        if(!__ka_socket)return NULL;
      }
    
      id = stridx(data, string("\r\n\r\n"));
      data = str_replace(string:data, find:"Connection: Close", replace:"Connection: Keep-Alive", count:1);
      __ka_last_request = data;
      n = send(socket:__ka_socket, data:data);
      if(n <= 0)
      {
        http_close_socket(__ka_socket);
        __ka_socket = http_open_socket(__ka_port);
        if(__ka_socket == 0)return NULL;
        send(socket:__ka_socket, data:data);
      }
    
      return(http_keepalive_recv(bodyonly:bodyonly));
    }
    
    
    
    #
    # Same as check_win_dir_trav(), but with KA support
    #
    function check_win_dir_trav_ka(port, url, quickcheck)
    {
      local_var	soc, req, cod, buf;
      #display("check_win_dir_trav(port=", port, ", url=", url, ", quickcheck=", quickcheck, ")\n");
    
      req = http_get(item:url, port:port);
      buf = http_keepalive_send_recv(port:port, data:req);
    
      if (quickcheck)
      {
        if (ereg(pattern:"^HTTP/.* 200 ", string:buf)) return (1);
        return (0);
      }
    
      if ( ("ECHO" >< buf)          || ("SET " >< buf)             ||
           ("export" >< buf)        || ("EXPORT" >< buf)           ||
           ("mode" >< buf)          || ("MODE" >< buf)             ||
           ("doskey" >< buf)        || ("DOSKEY" >< buf)           ||
           ("[boot loader]" >< buf) || ("[fonts]" >< buf)          ||
           ("[extensions]" >< buf)  || ("[mci extensions]" >< buf) ||
           ("[files]" >< buf)       || ("[Mail]" >< buf)           ||
           ("[operating systems]" >< buf)              )
      {
        return(1);
      }
      return(0);
    }
    
    #
    #
    #
    function is_cgi_installed_ka(item, port)
    {
     local_var r, no404, dir;
    
     if(item[0] != "/")
     {
      dir = cgibin();
      item = string(dir, "/", item);
     }
    
     r = http_keepalive_send_recv(port:port, data:http_get(item:item, port:port));
     if( r == NULL ) return NULL;
    
     no404 = get_kb_item(string("www/no404/", port));
    
     if(ereg(pattern:"^HTTP.* 200 .*", string:r))
     {
      if(no404)
      {
       if(tolower(no404) >< tolower(r))return(0);
      }
      return(1);
     }
     return(0);
    }
    
    
    
    
    
    #
    # This script was written by Geoffroy Raimbault <graimbault@lynx-technologies.com>
    #
    # www.lynx-technologies.com
    #
    # See the Nessus Scripts License for details
    #
    
    
    if(description)
    {
     script_version ("$Revision: 1.4 $");
     script_id(11142);
     script_bugtraq_id(5900);
     name["english"] = "IIS XSS via error";
     name["francais"] = "IIS XSS via une erreur IDC";
     script_name(english:name["english"], francais:name["francais"]);
    
     desc["english"] = "
    This IIS Server appears to be vulnerable to a Cross
    Site Scripting due to an error in the handling of overlong requests on
    an idc file. It is possible to inject Javascript
    in the URL, that will appear in the resulting page.
    
    Risk factor : Medium
    
    See also : http://online.securityfocus.com/bid/5900
               http://www.ntbugtraq.com/default.asp?pid=36&sid=1&A2=ind0210&L=ntbugtraq&F=P&S=&P=1391
     ";
    
     script_description(english:desc["english"]);
    
     summary["english"] = "Tests for IIS XSS via IDC errors";
     summary["francais"] = "Test de la vulnérabilité XSS dans IIS via une erreur IDC";
    
    
    script_summary(english:summary["english"], francais:summary["francais"]);
    
     script_category(ACT_GATHER_INFO);
    
     script_copyright(english:"This script is Copyright (C) 2002 Geoffroy Raimbault/Lynx Technologies",
    francais:"Ce script est Copyright (C) 2002 Geoffroy Raimbault/Lynx Technologies");
     family["english"] = "CGI abuses";
     family["francais"] = "Abus de CGI";
     script_family(english:family["english"], francais:family["francais"]);
     script_dependencie("find_service.nes", "no404.nasl","http_version.nasl");
     script_require_ports("Services/www", 80);
     script_require_keys("www/iis");
     exit(0);
    }
    
    include("http_func.inc");
    include("http_keepalive.inc");
    
    port = get_kb_item("Services/www");
    if(!port)port = 80;
    if(get_port_state(port))
    {
     # We construct the malicious URL with an overlong idc filename
     filename = string("/<script></script>",crap(334),".idc");
     req = http_get(item:filename, port:port);
    
     r = http_keepalive_send_recv(port:port, data:req, bodyonly:1);
     str="<script></script>";
     if((str >< r)) security_warning(port);
    }
    
    
    #
    # This script was written by Renaud Deraison <deraisonat_private>
    #
    # See the Nessus Scripts License for details
    #
    
    if(description)
    {
     script_id(11395);
     script_version ("$Revision: 1.1 $");
     script_cve_id("CAN-2000-0746");
     script_bugtraq_id(1594, 1595);
    
     name["english"] = "Microsoft Frontpage XSS";
     script_name(english:name["english"]);
    
     desc["english"] = "
    The remote server is vulnerable to Cross-Site-Scripting (XSS)
    when the FrontPage CGI /_vti_bin/shtml.dll is fed with improper
    arguments.
    
    Solution : See http://www.microsoft.com/technet/security/bulletin/ms00-060.asp
    Risk factor : Medium";
    
    
    
     script_description(english:desc["english"]);
    
     summary["english"] = "Checks for the presence of a Frontpage XSS";
     script_summary(english:summary["english"]);
    
     script_category(ACT_GATHER_INFO);
    
    
     script_copyright(english:"This script is Copyright (C) 2003 Renaud Deraison",
    		francais:"Ce script est Copyright (C) 2003 Renaud Deraison");
     family["english"] = "CGI abuses";
     family["francais"] = "Abus de CGI";
     script_family(english:family["english"], francais:family["francais"]);
     script_dependencie("find_service.nes", "no404.nasl", "http_version.nasl");
     script_require_ports("Services/www", 80);
     script_require_keys("www/iis");
     exit(0);
    }
    
    #
    # The script code starts here
    #
    
    include("http_func.inc");
    include("http_keepalive.inc");
    
    port = get_kb_item("Services/www");
    if(!port)port = 80;
    if(!get_port_state(port))exit(0);
    
    
    req = http_get(item:"/_vti_bin/shtml.exe/<script>alert(document.domain)</script>", port:port);
    
    res = http_keepalive_send_recv(port:port, data:req, bodyonly:1);
    if( res == NULL ) exit(0);
    
    if("<script>alert(document.domain)</script>" >< res)security_warning(port);
    
    
    #
    # This script was written by Renaud Deraison <deraisonat_private>
    #
    # Script audit and contributions from Carmichael Security <http://www.carmichaelsecurity.com>
    #      Erik Anderson <eandersat_private>
    #      Added links to the Bugtraq message archive and Microsoft Knowledgebase
    #
    # See the Nessus Scripts License for details
    #
    
    if(description)
    {
     script_id(10844);
     script_version ("$Revision: 1.6 $");
     name["english"] = "ASP.NET Cross Site Scripting";
    
     script_name(english:name["english"]);
    
     desc["english"] = "
    ASP.NET is vulnerable to a cross site scripting vulnerability.
    
    Solution : There was no solution ready when this vulnerability was written;
    Please contact the vendor for updates that address this vulnerability.
    
    Reference : http://online.securityfocus.com/archive/1/254001
    Reference : http://msdn.microsoft.com/library/en-us/dncode/html/secure07152002.asp
    
    Risk factor : Medium";
    
     script_description(english:desc["english"]);
    
     summary["english"] = "Tests for ASP.NET CSS";
    
     script_summary(english:summary["english"]);
    
     script_category(ACT_GATHER_INFO);
    
     script_copyright(english:"This script is Copyright (C) 2002 Renaud Deraison",
    		francais:"Ce script est Copyright (C) 2002 Renaud Deraison");
     family["english"] = "CGI abuses";
     family["francais"] = "Abus de CGI";
     script_family(english:family["english"], francais:family["francais"]);
     script_dependencie("find_service.nes", "no404.nasl", "http_version.nasl");
     script_require_ports("Services/www", 80);
     script_require_keys("www/iis");
     exit(0);
    }
    
    
    include("http_func.inc");
    include("http_keepalive.inc");
    
    port = get_kb_item("Services/www");
    if(!port)port = 80;
    if(get_port_state(port))
    {
     str = "/~/<script>alert(document.cookie)</script>.aspx?aspxerrorpath=null";
     req= http_get(item:str, port:port);
    
     soc = http_open_socket(port);
     if(soc)
     {
     r = http_keepalive_send_recv(port:port, data:req, bodyonly:1);
     lookfor = "<script>alert(document.cookie)</script>";
     if(lookfor >< r)
      {
       security_warning(port);
      }
     }
    }
    



    This archive was generated by hypermail 2b30 : Fri Sep 12 2003 - 06:49:06 PDT