bScan - Simple Web Aplications Scanner
// Find XSS, sql injection, remote file inclusion
1 2 ##################################################################################### 3 # Black_H / Nooz -- 30:01:07 4 # Bl4ck.H<>gmail<>com 5 # 6 7 class BScan 8 9 ##################################################################################### 10 # Regex 11 # 12 13 @@space = '([[:space:]]*)' 14 15 @@userdat = '(' 16 @@userdat += '(\$_SERVER\[([\'\"]*)HTTP_)|' 17 @@userdat += '(\$_GET)|' 18 @@userdat += '(\$_POST)|' 19 @@userdat += '(\$_COOKIE)|' 20 @@userdat += '(\$_REQUEST)|' 21 @@userdat += '(\$_FILES)|' 22 @@userdat += '(\$_ENV)|' 23 @@userdat += '(\$_HTTP_COOKIE_VARS)|' 24 @@userdat += '(\$_HTTP_ENV_VARS)|' 25 @@userdat += '(\$_HTTP_GET_VARS)|' 26 @@userdat += '(\$_HTTP_POST_FILES)|' 27 @@userdat += '(\$_HTTP_POST_VARS)|' 28 @@userdat += '(\$_HTTP_SERVER_VARS\[([\'\"]*)HTTP_)' 29 @@userdat += ')' 30 31 @@regex = Hash.new 32 @@regex = 33 {'TYPE' => 'vars overwrite','LEVEL' => '2','REGEX' => /extract#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 34 {'TYPE' => 'vars overwrite','LEVEL' => '2','REGEX' => /import_request_variables#{@@space}\((.*)\)/i}, 35 {'TYPE' => 'fopen vuln','LEVEL' => '3','REGEX' => /fopen#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 36 {'TYPE' => 'copy vuln','LEVEL' => '3','REGEX' => /copy#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 37 {'TYPE' => 'fwrite vuln','LEVEL' => '3','REGEX' => /fwrite#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 38 {'TYPE' => 'sql injection','LEVEL' => '2','REGEX' => /(mysql_query|mssql_query|mysqli_query)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 39 {'TYPE' => 'crlf injection','LEVEL' => '1','REGEX' => /mail#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 40 {'TYPE' => 'cross site scripting','LEVEL' => '1','REGEX' => /\<\?\=#{@@space}(.*)#{@@userdat}/i}, 41 {'TYPE' => 'cross site scripting','LEVEL' => '1','REGEX' => /(print|echo|print_r|var_dump)#{@@space}(|\(|\")(.*)#{@@userdat}/i}, 42 {'TYPE' => 'php code execution','LEVEL' => '3','REGEX' => /eval#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 43 {'TYPE' => 'php code execution','LEVEL' => '3','REGEX' => /file_put_contents#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 44 {'TYPE' => 'variable attribution', 'LEVEL' => '2','REGEX' => /(.*)\$#{@@userdat}(.*)/i}, 45 {'TYPE' => 'chmod affectation','LEVEL' => '1','REGEX' => /chmod#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 46 {'TYPE' => 'file disclosure','LEVEL' => '2','REGEX' => /(readfile|file_get_contents|file)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 47 {'TYPE' => 'file disclosure','LEVEL' => '2','REGEX' => /(show_source|highlight_file)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 48 {'TYPE' => 'bzopen vuln','LEVEL' => '2','REGEX' => /bzopen#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 49 {'TYPE' => 'file deletion','LEVEL' => '2','REGEX' => /(rmdir|unlink|delete)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 50 {'TYPE' => 'command execution','LEVEL' => '3','REGEX' => /(exec|system|passthru|shell_exec|proc_open|pcntl_exec)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 51 {'TYPE' => 'buffer overflow','LEVEL' => '3','REGEX' => /(confirm_phpdoc_compiled|mssql_pconnect|mssql_connect|crack_opendict|snmpget|ibase_connect)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 52 {'TYPE' => 'ip falsification','LEVEL' => '1','REGEX' => /(.*)(HTTP_CLIENT_IP|HTTP_X_FORWARDED_FOR|HTTP_PC_REMOTE_ADDR)(.*)/i}, 53 {'TYPE' => 'putenv vuln','LEVEL' => '2','REGEX' => /putenv#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 54 {'TYPE' => 'full path disclosure','LEVEL' => '1','REGEX' => /(htmlentities|htmlspecialchars)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 55 {'TYPE' => 'magic_quotes_gpc bypass','LEVEL' => '1','REGEX' => /(stripslashes|urldecode)#{@@space}\((.*)#{@@userdat}(.*)\)/i}, 56 {'TYPE' => 'file inclusion','LEVEL' => '3','REGEX' => /(include|include_once|require|require_once)#{@@space}(|\(|\")(.*)#{@@userdat}/i} 57 58 ##################################################################################### 59 # Main 60 # 61 62 def initialize() 63 64 ################ 65 # Usage 66 67 if (ARGV.length < 4) 68 puts ' 69 --------------------------------------------------------------------- 70 | Credits: Black_H <bl4ck.h@gmail.com> | 71 | URL: Lemon-Inside.sup.fr | 72 | Note: Premier code Ruby | 73 --------------------------------------------------------------------- 74 75 --------------------------------------------------------------------- 76 | Usage: scan.rb -d <Dossier> -i <Save.html> | 77 | Ex: scan.rb -d ./ -i output.html | 78 --------------------------------------------------------------------- 79 ' 80 end 81 82 ################ 83 # Options & Vars 84 85 @@scan_alldir = self.options('d') 86 @@out_file = self.options('i') 87 88 @@ban = [".", "..", "scan.rb", @@out_file.to_s] 89 90 @@scan_buffer = Array.new 91 92 ################ 93 # Options Error ? 94 95 if (@@scan_alldir != false and @@scan_alldir.empty? == false) 96 self.dscan(@@scan_alldir) 97 self.output(@@scan_buffer) 98 @@scan_buffer = '' 99 end 100 101 102 103 104 end 105 106 ##################################################################################### 107 # Dir Scan 108 # 109 110 def dscan(dir) 111 112 d = Dir.open(dir.to_s) 113 d = d.sort - @@ban 114 115 d.each { |fichier| 116 117 case File.ftype(dir+fichier) 118 when "directory" 119 self.dscan(dir + fichier + "/") 120 when "file" 121 puts 'Scan => ' + dir + fichier 122 self.fscan(dir + fichier) 123 end 124 125 } 126 end 127 128 ##################################################################################### 129 # File Scan 130 # 131 132 def fscan(file) 133 134 fichier = File.readlines(file) 135 i = 1 136 137 fichier.each { |line| 138 139 @@regex.each { |info| 140 141 test = (line =~ info['REGEX']) 142 143 if (test) 144 145 @@scan_buffer += ['FILE' => file, 'LINE' => i.to_s, 'MATCH' => line, 'LEVEL' => info['LEVEL'], 'TYPE' => info['TYPE']] 146 # 5 , 1 , 3 , 4 , 2 147 next @@scan_buffer 148 end 149 } 150 151 i += 1 152 } 153 154 end 155 156 ##################################################################################### 157 # Output buffer 158 # 159 160 def output(buffer) 161 162 @html_hmodel = '<html>' 163 @html_hmodel += '<style type="text/css">' 164 @html_hmodel += '<!--' 165 @html_hmodel += '.level0 {background-color: #CCCCCC;}' 166 @html_hmodel += '.level1 {background-color: #33FF66;}' 167 @html_hmodel += '.level2 {background-color: #FFFF33;}' 168 @html_hmodel += '.level3 {background-color: #FF0000;}' 169 @html_hmodel += '--></style><body><h1>BScan v1.0</h1><pre>' 170 171 code = @html_hmodel 172 173 buffer.each { |infos| 174 175 keys = infos.keys 176 code += "<span class='level" + infos["LEVEL"] + "'>" + keys[1].to_s + ' : ' + infos["TYPE"] + '</span><br />' 177 code += "<span class='" + infos["LEVEL"] + "'>" + keys[3].to_s + ' : ' + infos["LEVEL"] + '</span><br />' 178 code += "<span class='" + infos["LEVEL"] + "'>" + keys[4].to_s + ' : ' + infos["FILE"] + '</span><br />' 179 code += "<span class='" + infos["LEVEL"] + "'>" + keys[0].to_s + ' : ' + infos["LINE"] + '</span><br />' 180 code += "<span class='" + infos["LEVEL"] + "'>" + keys[2].to_s + ' : ' + infos["MATCH"] + '</span><br />' 181 182 183 } 184 code += "</pre></body></html>" 185 fhtml = File.open(@@out_file.to_s, "w") 186 fhtml.write code 187 code = '' 188 189 190 end 191 ##################################################################################### 192 # Parse & Get Options 193 # 194 195 def options(param) 196 197 i = 0 198 ARGV.each { |valeur| 199 200 if (valeur == '-' + param.to_s) 201 return ARGV[i+1] 202 elseif (valeur != '-' + param.to_s) 203 return false 204 end 205 i += 1 206 } 207 208 end 209 210 end 211 212 scan = BScan.new 213