#
# This script was written by John Lampe ... j_lampe@bellsouth.net
#
# Script is based on wpoison by M.Meadele mm@bzero.net
# See http://wpoison.sourceforge.net
#
# See the Nessus Scripts License for details
#
#
# re-worked Aug 20, 2004 : jwlampe -at- tenablesecurity.com adds POST checks 
#



if(description)
{
 script_id(11139);
#script_cve_id("CVE-MAP-NOMATCH");
 script_version ("$Revision: 1.22 $");
 name["english"] = "wpoison (nasl version)";
 script_name(english:name["english"]);
 
 desc["english"] = "
This script attempts to use SQL injection techniques on CGI scripts
More info at : http://www.securiteam.com/securityreviews/5DP0N1P76E.html


Solution : Modify the relevant CGIs so that they properly escape arguments.

Risk factor : High";



 script_description(english:desc["english"]);
 
 summary["english"] = "Some common SQL injection techniques";
 
 script_summary(english:summary["english"]);
 
 script_category(ACT_GATHER_INFO);
 
 
 script_copyright(english:"This script is Copyright (C) 2002 John Lampe...j_lampe@bellsouth.net");
 family["english"] = "CGI abuses";
 family["francais"] = "Abus de CGI";
 script_family(english:family["english"], francais:family["francais"]);
 script_dependencie("find_service.nes", "webmirror.nasl");
 script_require_ports("Services/www", 80);
 exit(0);
}

#
# The script code starts here
#

include("http_func.inc");
include("http_keepalive.inc");

single_quote = raw_string(0x27);

poison[0] = single_quote + "UNION" + single_quote;
poison[1] = single_quote;
poison[2] = single_quote + "%22";
poison[3] = "9%2c+9%2c+9";
poison[4] = single_quote + "bad_bad_value";
poison[5] = "bad_bad_value" + single_quote;
poison[6] = single_quote + "+OR+" + single_quote;
poison[7] = single_quote + "WHERE";
poison[8] = "%3B"; # semicolon
poison[9] = single_quote + "OR";
# methods below from http://www.securiteam.com/securityreviews/5DP0N1P76E.html
poison[10] = single_quote + " or 1=1--";
poison[11] = " or 1=1--";
poison[12] = single_quote + " or " + single_quote + "a" + single_quote + "=" + single_quote + "a";
poison[13] = single_quote + ") or (" + single_quote + "a" + single_quote + "=" + single_quote + "a";


posreply[0] = "Can't find record in";
posreply[1] = "Column count doesn't match value count at row";
posreply[2] = "error " + single_quote;
posreply[3] = "Incorrect column name";
posreply[4] = "Incorrect column specifier for column";
posreply[5] = "Invalid parameter type";
posreply[6] = "Microsoft OLE DB Provider for ODBC Drivers error";
posreply[7] = "ODBC Microsoft Access Driver";
posreply[8] = "ODBC SQL Server Driver";
posreply[9] = "supplied argument is not a valid MySQL result";
posreply[10] = "Table ";
posreply[11] = "Unknown table";
posreply[12] = "You have an error in your SQL syntax";
posreply[13] = "Microsoft VBScript runtime";
posreply[14] = "Syntax";
posreply[15] = "not a valid MySQL result resource";
posreply[16] = "unexpected end of SQL command";
posreply[17] = "mySQL error with query";
posreply[18] = "ORA-00936: missing expression";
posreply[19] = "ORA-00933: SQL command not properly ended";
posreply[20] = "Unclosed quotation mark before the character string";
posreply[21] = "Incorrect syntax near";
posreply[22] = "PostgreSQL query failed:";
posreply[23] = "not a valid PostgreSQL result";
posreply[24] = "An illegal character has been found in the statement";
posreply[25] = "[IBM][CLI Driver][DB2/6000]";
posreply[26] = "Unable to connect to PostgreSQL server:";
posreply[27] = "Can't connect to local";
posreply[28] = "Error Occurred While Processing Request";
posreply[29] = "mysql_query()";

port = get_http_port(default:80);

if(! get_port_state(port))
	exit(0);
unsafe_urls = "";
mywarningcount = 0;


name = string("www/", port, "/cgis");
cgi = get_kb_item(name);
if(! cgi)
	exit(0);

# populate two arrays param[] and data[]  
everythingrray = split(cgi, sep:" ", keep:FALSE);    

if (everythingrray[0] =~ ".*/$")
{
	isdir = 1;
}
else
{
	isdir = 0;
}

if (! isdir)
{
	pseudocount = 0;
	foreach rrayval (everythingrray)
	{
		if (pseudocount >= 2)
		{
			if ("]" >< rrayval)
			{
				tmpf = ereg_replace(pattern:"\[|\]", string:rrayval, replace:"");
				data[pseudocount] = tmpf;
				
			}
			else
			{
				param[pseudocount] = rrayval;
			}
		}	
		else
		{
			param[pseudocount] = rrayval;
		}
		pseudocount++;
	}
}



for (z=2; param[z]; z = z + 1) 
{
	url = param[z];
	req = http_get(item:url, port:port);
        res = http_keepalive_send_recv(port:port, data:req);
        if ( res == NULL ) 
		exit(0);
        for ( i = 0; posreply[i]; i ++ )
        {
         	if ( posreply[i] >< res ) 
		{
			exit(0); # Broken SQL
			#display("broken sql\n");              #remov 
		}
        }
      	for (poo=0; poison[poo]; poo = poo + 1) 
	{
        	url = string(param[0],"?");
        	for (i=2 ; param[i]; i = i + 1) 
		{
      			if (i == z) 
			{
          			if (data[i]) 
				{
        				url = string(url,param[i],"=",poison[poo]);
          			} 
				else 
				{
              				url = string(url,param[i],"=",poison[poo]);
          			}
      			} 
			else 
			{
          			if (data[i]) 
				{
              				url = string(url,param[i],"=",data[i]);
          			} 
				else 
				{
              				url = string(url,param[i],"=");
          			}
      			}
      			if (param[i + 1]) 
			{
				url = string(url,"&");
			}
        	}
        
        
		req = http_get(item:url, port:port);

		inbuff = http_keepalive_send_recv(port:port, data:req);
		if( inbuff == NULL ) 
			exit(0);
        	for (mu=0; posreply[mu]; mu = mu + 1) 
		{
            		if (posreply[mu] >< inbuff ) 
			{
          			unsafe_urls = string(unsafe_urls, url, "\n");
          			mywarningcount = mywarningcount + 1;
      			}
        	}


		if ( safe_checks() == 0 )
		{
                # create a POST req  
                tmppost = split(url, sep:"?", keep:FALSE);
                mypostdata = tmppost[1];
                postreq = http_post(item:param[0], port:port, data:mypostdata);


		# Test the POST req
		inbuff = http_keepalive_send_recv(port:port, data:postreq);
		if ( inbuff == NULL )
			exit(0);
                for (mu=0; posreply[mu]; mu = mu + 1)
                 {
                        if (posreply[mu] >< buff )
                        {
                                unsafe_urls = string(unsafe_urls, url, "\n");
                                mywarningcount = mywarningcount + 1;
                        }
                 }
		}

      	}
}			


if (mywarningcount > 0) 
{
        report = string("
The following URLs seem to be vulnerable to various SQL injection
techniques : \n\n", 
		unsafe_urls,
		"\n\n
An attacker may exploit this flaws to bypass authentication
or to take the control of the remote database.


Solution : Modify the relevant CGIs so that they properly escape arguments
Risk factor : High
See also : http://www.securiteam.com/securityreviews/5DP0N1P76E.html");

        
        security_hole(port:port, data:report);
}

