// Web application scanner (ex: phpBB, myCMS, myBlog, mySite etc..) - Only in PHP !
// Find XSS, sql injection, remote file inclusion
1
2
3
4
5
6
7 class BScan
8
9
10
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
60
61
62 def initialize()
63
64
65
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
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
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
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
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
147 next @@scan_buffer
148 end
149 }
150
151 i += 1
152 }
153
154 end
155
156
157
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
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