DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

BScan - Simple Web Aplications Scanner

02.03.2008
| 5315 views |
  • submit to reddit
        // Web application scanner (ex: phpBB, myCMS, myBlog, mySite etc..) - Only in PHP !
// Find XSS, sql injection, remote file inclusion

#####################################################################################
#	Black_H  / Nooz -- 30:01:07 
#	Bl4ck.H<>gmail<>com
#

class BScan

#####################################################################################
#	Regex
#

@@space    = '([[:space:]]*)'

@@userdat  = '('
@@userdat += '(\$_SERVER\[([\'\"]*)HTTP_)|'
@@userdat += '(\$_GET)|'
@@userdat += '(\$_POST)|'
@@userdat += '(\$_COOKIE)|'
@@userdat += '(\$_REQUEST)|'
@@userdat += '(\$_FILES)|'
@@userdat += '(\$_ENV)|'
@@userdat += '(\$_HTTP_COOKIE_VARS)|'
@@userdat += '(\$_HTTP_ENV_VARS)|'
@@userdat += '(\$_HTTP_GET_VARS)|'
@@userdat += '(\$_HTTP_POST_FILES)|'
@@userdat += '(\$_HTTP_POST_VARS)|'
@@userdat += '(\$_HTTP_SERVER_VARS\[([\'\"]*)HTTP_)'
@@userdat += ')'

@@regex = Hash.new
@@regex = 
	{'TYPE' => 'vars overwrite','LEVEL' => '2','REGEX' => /extract#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'vars overwrite','LEVEL' => '2','REGEX' => /import_request_variables#{@@space}\((.*)\)/i},
	{'TYPE' => 'fopen vuln','LEVEL' => '3','REGEX' => /fopen#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'copy vuln','LEVEL' => '3','REGEX' => /copy#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'fwrite vuln','LEVEL' => '3','REGEX' => /fwrite#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'sql injection','LEVEL' => '2','REGEX' => /(mysql_query|mssql_query|mysqli_query)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'crlf injection','LEVEL' => '1','REGEX' => /mail#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'cross site scripting','LEVEL' => '1','REGEX' => /\<\?\=#{@@space}(.*)#{@@userdat}/i},
	{'TYPE' => 'cross site scripting','LEVEL' => '1','REGEX' => /(print|echo|print_r|var_dump)#{@@space}(|\(|\")(.*)#{@@userdat}/i},
	{'TYPE' => 'php code execution','LEVEL' => '3','REGEX' => /eval#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'php code execution','LEVEL' => '3','REGEX' => /file_put_contents#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'variable attribution', 'LEVEL' => '2','REGEX' => /(.*)\$#{@@userdat}(.*)/i},
	{'TYPE' => 'chmod affectation','LEVEL' => '1','REGEX' => /chmod#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'file disclosure','LEVEL' => '2','REGEX' => /(readfile|file_get_contents|file)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'file disclosure','LEVEL' => '2','REGEX' => /(show_source|highlight_file)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'bzopen vuln','LEVEL' => '2','REGEX' => /bzopen#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'file deletion','LEVEL' => '2','REGEX' => /(rmdir|unlink|delete)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'command execution','LEVEL' => '3','REGEX' => /(exec|system|passthru|shell_exec|proc_open|pcntl_exec)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'buffer overflow','LEVEL' => '3','REGEX' => /(confirm_phpdoc_compiled|mssql_pconnect|mssql_connect|crack_opendict|snmpget|ibase_connect)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'ip falsification','LEVEL' => '1','REGEX' => /(.*)(HTTP_CLIENT_IP|HTTP_X_FORWARDED_FOR|HTTP_PC_REMOTE_ADDR)(.*)/i},
	{'TYPE' => 'putenv vuln','LEVEL' => '2','REGEX' => /putenv#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'full path disclosure','LEVEL' => '1','REGEX' => /(htmlentities|htmlspecialchars)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'magic_quotes_gpc bypass','LEVEL' => '1','REGEX' => /(stripslashes|urldecode)#{@@space}\((.*)#{@@userdat}(.*)\)/i},
	{'TYPE' => 'file inclusion','LEVEL' => '3','REGEX' => /(include|include_once|require|require_once)#{@@space}(|\(|\")(.*)#{@@userdat}/i}

#####################################################################################
#	Main
#

  def initialize()

	################
	#	Usage

if (ARGV.length < 4)
puts  '
 ---------------------------------------------------------------------
|             Credits: Black_H <bl4ck.h@gmail.com>                    |
|                 URL: Lemon-Inside.sup.fr                            |
|                Note: Premier code Ruby                              |
 ---------------------------------------------------------------------

 ---------------------------------------------------------------------
|   Usage:  scan.rb -d <Dossier> -i <Save.html>                       |
|   Ex:  scan.rb -d ./ -i output.html                                 |
 ---------------------------------------------------------------------		
 '
 end
 
	################
	#	Options & Vars
	
	@@scan_alldir =  self.options('d')
	@@out_file =  self.options('i')
	
	@@ban = [".", "..", "scan.rb", @@out_file.to_s]

	@@scan_buffer = Array.new
	
	################
	#	Options Error ?
	
	if (@@scan_alldir != false and @@scan_alldir.empty? == false)
	self.dscan(@@scan_alldir)
	self.output(@@scan_buffer)
	@@scan_buffer = ''
	end


	

  end

#####################################################################################
#	Dir Scan 
#
  
  def dscan(dir)
      
	d = Dir.open(dir.to_s)
	d = d.sort - @@ban
	
      d.each { |fichier|

      case File.ftype(dir+fichier)
        when "directory"
          self.dscan(dir + fichier + "/")
        when "file"
		  puts  'Scan => ' + dir + fichier 
          self.fscan(dir + fichier)
      end

	  }
  end

#####################################################################################
#	File Scan 
#
  
  def fscan(file)

	fichier = File.readlines(file)
	i = 1

	fichier.each { |line|
						
		@@regex.each  { |info|
			
			test = (line  =~ info['REGEX']) 
		
				if (test) 
			
				@@scan_buffer += ['FILE' => file, 'LINE' => i.to_s, 'MATCH' => line, 'LEVEL' => info['LEVEL'], 'TYPE' => info['TYPE']]
				#	5 , 1 , 3 , 4 , 2
				next @@scan_buffer
				end
		}

	i += 1
  	} 
	
  end

#####################################################################################
#	Output buffer
#
  
  def output(buffer)
  
	@html_hmodel = '<html>'
	@html_hmodel += '<style type="text/css">'
	@html_hmodel += '<!--'
	@html_hmodel += '.level0 {background-color: #CCCCCC;}'
	@html_hmodel += '.level1 {background-color: #33FF66;}'
	@html_hmodel += '.level2 {background-color: #FFFF33;}'
	@html_hmodel += '.level3 {background-color: #FF0000;}'
	@html_hmodel += '--></style><body><h1>BScan v1.0</h1><pre>'

	code = @html_hmodel
	
	buffer.each { |infos|
	
	keys = infos.keys
	code += "<span class='level" + infos["LEVEL"] + "'>" + keys[1].to_s + ' : ' + infos["TYPE"] + '</span><br />'
	code += "<span class='" + infos["LEVEL"] + "'>" + keys[3].to_s + ' : ' + infos["LEVEL"] + '</span><br />'
	code += "<span class='" + infos["LEVEL"] + "'>" + keys[4].to_s + ' : ' + infos["FILE"] + '</span><br />'
	code += "<span class='" + infos["LEVEL"] + "'>" + keys[0].to_s + ' : ' + infos["LINE"] + '</span><br />'
	code += "<span class='" + infos["LEVEL"] + "'>" + keys[2].to_s + ' : ' + infos["MATCH"] + '</span><br />'
	

	}
		code += "</pre></body></html>"
		fhtml = File.open(@@out_file.to_s, "w")
		fhtml.write code
		code = ''

	
  end
#####################################################################################
#	Parse & Get Options
#
 
  def options(param)
  
	i = 0
		ARGV.each  { |valeur|
		
    		if (valeur == '-' + param.to_s)
				return ARGV[i+1]
			elseif (valeur != '-' + param.to_s)
				return false
			end
		i += 1
		}
		
	end
  
end

scan = BScan.new