diff --git a/lib/objects/local_script_challenge_generator.rb b/lib/objects/local_script_challenge_generator.rb new file mode 100644 index 000000000..692116b7e --- /dev/null +++ b/lib/objects/local_script_challenge_generator.rb @@ -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 + diff --git a/modules/generators/challenges/misc/programming/python_example/manifests/.no_puppet b/modules/generators/challenges/misc/programming/python_example/manifests/.no_puppet new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/challenges/misc/programming/python_example/python_example.pp b/modules/generators/challenges/misc/programming/python_example/python_example.pp new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/challenges/misc/programming/python_example/secgen_local/local.rb b/modules/generators/challenges/misc/programming/python_example/secgen_local/local.rb new file mode 100644 index 000000000..c63a7ae0e --- /dev/null +++ b/modules/generators/challenges/misc/programming/python_example/secgen_local/local.rb @@ -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 \ No newline at end of file diff --git a/modules/generators/challenges/misc/programming/python_example/secgen_metadata.xml b/modules/generators/challenges/misc/programming/python_example/secgen_metadata.xml new file mode 100644 index 000000000..7b143d8fd --- /dev/null +++ b/modules/generators/challenges/misc/programming/python_example/secgen_metadata.xml @@ -0,0 +1,18 @@ + + + + Ruby Example Challenge Generator + Thomas Shaw + MIT + TODO + + python2_script_challenge + + linux + windows + + script + + \ No newline at end of file diff --git a/modules/generators/challenges/misc/programming/ruby_example/secgen_local/local.rb b/modules/generators/challenges/misc/programming/ruby_example/secgen_local/local.rb index 2d7435e89..5dba077ea 100644 --- a/modules/generators/challenges/misc/programming/ruby_example/secgen_local/local.rb +++ b/modules/generators/challenges/misc/programming/ruby_example/secgen_local/local.rb @@ -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 diff --git a/modules/vulnerabilities/unix/ctf/python2_challenge_example/manifests/install.pp b/modules/vulnerabilities/unix/ctf/python2_challenge_example/manifests/install.pp new file mode 100644 index 000000000..747a9f5a8 --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/python2_challenge_example/manifests/install.pp @@ -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'], + } + } + +} diff --git a/modules/vulnerabilities/unix/ctf/python2_challenge_example/python2_challenge_example.pp b/modules/vulnerabilities/unix/ctf/python2_challenge_example/python2_challenge_example.pp new file mode 100644 index 000000000..99d16c5df --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/python2_challenge_example/python2_challenge_example.pp @@ -0,0 +1 @@ +include python2_challenge_example::install diff --git a/modules/vulnerabilities/unix/ctf/python2_challenge_example/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/python2_challenge_example/secgen_metadata.xml new file mode 100644 index 000000000..3fc6c29f8 --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/python2_challenge_example/secgen_metadata.xml @@ -0,0 +1,61 @@ + + + + python2 Challenge Example + Thomas Shaw + MIT + python2 challenge example + + ctf_challenge + script_challenge + none + local + linux + + + challenge_name + script_data + account + flag + + storage_directory + + group + + python2_script_example + + + + + + + + challenges + + + password + + + + + + + + python2_script_example + + + + utilities/unix/system/accounts + + + + utilities/unix/system/binary_script_container + + + + utilities/unix/languages/python + + +