Superclass for script challenges, ruby and python2 examples

This commit is contained in:
ts
2018-08-03 13:29:21 +01:00
parent 9ca017d3b2
commit 5e73435337
9 changed files with 287 additions and 5 deletions

View File

@@ -0,0 +1,130 @@
require 'getoptlong'
require_relative '../helpers/constants'
require 'base64'
# Inherited by local script challenge generators
# stdout used to return value
# use Print.local to print status messages (formatted to stdout)
# A nice side-effect is that each of these modules is also an executable script
class ScriptChallengeGenerator
require_relative '../helpers/print.rb'
attr_accessor :module_name
attr_accessor :has_base64_inputs
attr_accessor :outputs
# override this
def initialize
# default values
self.module_name = 'Null generator'
self.has_base64_inputs = false
self.outputs = []
end
# override this
def generate
self.outputs << shebang_line + script_content
end
def read_arguments
# Get command line arguments
opts = get_options
# process option arguments
opts.each do |opt, arg|
# Check if base64 decoding is required and set instance variable
if opt == '--b64'
self.has_base64_inputs = true
end
# Decode if required
argument = self.has_base64_inputs ? Base64.strict_decode64(arg) : arg
process_options(opt, argument)
end
end
# Override this when using read_fact's in your module
def get_options
GetoptLong.new(*get_options_array)
end
def get_options_array
[['--help', '-h', GetoptLong::NO_ARGUMENT],
['--b64', GetoptLong::OPTIONAL_ARGUMENT]]
end
# Override this when using read_fact's in your module. Always call super first
def process_options(opt, arg)
unless option_is_valid(opt)
Print.err "Argument not valid: #{arg}"
usage
exit
end
case opt
when '--help'
usage
when '--b64'
# do nothing
end
end
def usage
Print.err "Usage:
#{$0} [--options]
"
exit
end
def run
Print.local module_name
read_arguments
Print.local_verbose "Generating..."
generate
# print the first 1000 chars to screen
output = self.outputs.to_s
length = output.length
if length < 1000
Print.local_verbose "Generated: #{output}..."
else
Print.local_verbose "Generated: #{output.to_s[0..1000]}..."
Print.local_verbose "(Displaying 1000/#{length} length output)"
end
puts has_base64_inputs ? base64_encode_outputs : self.outputs
end
def base64_encode_outputs
self.outputs.map { |o| Base64.strict_encode64 o }
end
def option_is_valid(opt_to_check)
arg_validity = false
valid_arguments = get_options_array
valid_arguments.each{ |valid_arg_array|
valid_arg_array.each_with_index { |valid_arg|
if valid_arg == opt_to_check
arg_validity = true
end
}
}
arg_validity
end
def script_content
# override me with script content
end
def interpreter_path
# override me with a string containing the interpreter path e.g. "/bin/bash"
end
def shebang_line
"#!/usr/local/bin/suid #{interpreter_path} --\n"
end
end

View File

@@ -0,0 +1,24 @@
#!/usr/bin/ruby
require_relative '../../../../../../../lib/objects/local_script_challenge_generator.rb'
class RubyExampleScriptGenerator < ScriptChallengeGenerator
def initialize
super
self.module_name = 'Python Example Script Generator'
end
def interpreter_path
'/usr/bin/python'
end
def script_content
"from sys import argv
with open('flag') as f:
print f.read()"
end
end
RubyExampleScriptGenerator.new.run

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<generator xmlns="http://www.github/cliffe/SecGen/generator"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/generator">
<name>Ruby Example Challenge Generator</name>
<author>Thomas Shaw</author>
<module_license>MIT</module_license>
<description>TODO</description>
<type>python2_script_challenge</type>
<platform>linux</platform>
<platform>windows</platform>
<output_type>script</output_type>
</generator>

View File

@@ -1,7 +1,7 @@
#!/usr/bin/ruby
require_relative '../../../../../../../lib/objects/local_string_generator.rb'
class RubyExampleScriptGenerator < StringGenerator
require_relative '../../../../../../../lib/objects/local_script_challenge_generator.rb'
class RubyExampleScriptGenerator < ScriptChallengeGenerator
def initialize
super
@@ -9,9 +9,12 @@ class RubyExampleScriptGenerator < StringGenerator
end
def generate
self.outputs << "#!/usr/local/bin/suid /usr/bin/ruby --
puts File.read('flag')"
def interpreter_path
'/usr/bin/ruby'
end
def script_content
"puts File.read('flag')"
end
end

View File

@@ -0,0 +1,45 @@
class python2_challenge_example::install {
$secgen_params = secgen_functions::get_parameters($::base64_inputs_file)
$group = $secgen_params['group']
$script_data = $secgen_params['script_data']
if $secgen_params['account'][0] and $secgen_params['account'][0] != '' {
$account = parsejson($secgen_params['account'][0])
} else {
$account = undef
}
if $secgen_params['storage_directory'] and $secgen_params['storage_directory'][0] {
$storage_dir = $secgen_params['storage_directory'][0]
} else {
$storage_dir = undef
}
if $group {
::secgen_functions::install_setgid_script { 'python2_challenge_example':
source_module_name => $module_name,
challenge_name => $secgen_params['challenge_name'][0],
script_name => 'test.py',
script_data => $script_data[0],
group => $group[0],
account => $account,
flag => $secgen_params['flag'][0],
flag_name => 'flag',
storage_dir => $storage_dir,
strings_to_leak => $secgen_params['strings_to_leak'],
}
} else {
::secgen_functions::install_setuid_root_script { 'python2_challenge_example':
source_module_name => $module_name,
challenge_name => $secgen_params['challenge_name'][0],
script_name => 'test.py',
script_data => $script_data[0],
account => $account,
flag => $secgen_params['flag'][0],
flag_name => 'flag',
storage_dir => $storage_dir,
strings_to_leak => $secgen_params['strings_to_leak'],
}
}
}

View File

@@ -0,0 +1 @@
include python2_challenge_example::install

View File

@@ -0,0 +1,61 @@
<?xml version="1.0"?>
<vulnerability xmlns="http://www.github/cliffe/SecGen/vulnerability"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.github/cliffe/SecGen/vulnerability">
<name>python2 Challenge Example</name>
<author>Thomas Shaw</author>
<module_license>MIT</module_license>
<description>python2 challenge example</description>
<type>ctf_challenge</type>
<type>script_challenge</type>
<privilege>none</privilege>
<access>local</access>
<platform>linux</platform>
<!-- script dropped in account's home directory by default with setuid configuration. -->
<read_fact>challenge_name</read_fact>
<read_fact>script_data</read_fact>
<read_fact>account</read_fact>
<read_fact>flag</read_fact>
<!-- storage_directory: Blank by default. If supplied, store the files here. e.g. NFS or SMB storage location -->
<read_fact>storage_directory</read_fact>
<!-- group: Blank by default. If supplied install script challenge as setgid -->
<read_fact>group</read_fact>
<default_input into="challenge_name">
<value>python2_script_example</value>
</default_input>
<default_input into="script_data">
<generator module_path=".*python_example"/>
</default_input>
<default_input into="account">
<generator type="account">
<input into="username">
<value>challenges</value>
</input>
<input into="password">
<value>password</value>
</input>
</generator>
</default_input>
<default_input into="flag">
<generator type="flag_generator"/>
</default_input>
<default_input into="challenge_name">
<value>python2_script_example</value>
</default_input>
<requires>
<module_path>utilities/unix/system/accounts</module_path>
</requires>
<requires>
<module_path>utilities/unix/system/binary_script_container</module_path>
</requires>
<requires>
<module_path>utilities/unix/languages/python</module_path>
</requires>
</vulnerability>