diff --git a/modules/build/puppet/secgen_functions/manifests/install_setgid_binary.pp b/modules/build/puppet/secgen_functions/manifests/install_setgid_binary.pp new file mode 100644 index 000000000..b8dd6797d --- /dev/null +++ b/modules/build/puppet/secgen_functions/manifests/install_setgid_binary.pp @@ -0,0 +1,104 @@ +# Install function for setuid_root binaries +# -- Modules calling this function must provide a Makefile and any .c files within it's /files directory +# +# ** NOTES *** +# Do we really need a user account or can we just pass in the directory path? +# + + + +define secgen_functions::install_setgid_binary ( + $challenge_name, # Challenge name, used for the wrapper-directory + $source_module_name, # Name of the module that calls this function + $group, # Name of group + $account, # User account + $flag, # ctf flag string + $flag_name, # ctf flag name + $storage_dir = '', # Optional: Storage directory (takes precedent if supplied, e.g. nfs / smb share dir) + $strings_to_leak = [''], # Optional: strings to leak (could contain instructions or a message) +) { + + if $account { + $username = $account['username'] + + ::accounts::user { $username: + shell => '/bin/bash', + password => pw_hash($account['password'], 'SHA-512', 'mysalt'), + managehome => true, + home_mode => '0755', + } + + $storage_directory = "/home/$username" + + } elsif $storage_dir { + $storage_directory = $storage_dir + + } else { + err('install: either account or storage_dir is required') + fail + } + + + $compile_directory = "$storage_directory/tmp" + $challenge_directory = "$storage_directory/$challenge_name" + $modules_source = "puppet:///modules/$source_module_name" + + notice("compile_directory: ") + notice($compile_directory) + notice("challenge_directory: ") + notice($challenge_directory) + + group { $group: + ensure => present, + } + + # Create challenge directory + file { "create_$challenge_directory": + path => $challenge_directory, + ensure => directory, + } + + # Move contents of the module's files directory into compile directory + file { "create_$compile_directory": + path => $compile_directory, + ensure => directory, + recurse => true, + source => $modules_source, + } + + # Build the binary with gcc + exec { "gcc_$challenge_name-$compile_directory": + cwd => $compile_directory, + command => "/usr/bin/make", + require => File["create_$challenge_directory", "create_$compile_directory"] + } + + # Move the compiled binary into the challenge directory + file { "$challenge_directory/$challenge_name": + ensure => present, + owner => 'root', + group => $group, + mode => '4771', + source => "$compile_directory/$challenge_name", + require => Exec["gcc_$challenge_name-$compile_directory"], + } + + # Drop the flag file on the box and set permissions + ::secgen_functions::leak_files { "$username-file-leak": + storage_directory => "$challenge_directory", + leaked_filenames => [$flag_name], + strings_to_leak => [$flag], + owner => 'root', + group => $group, + mode => '4440', + leaked_from => "accounts_$username", + require => [Group[$group], Exec["gcc_$challenge_name-$compile_directory"]], + notify => Exec["remove_$compile_directory"], + } + + # Remove compile directory + exec { "remove_$compile_directory": + command => "/bin/rm -rf $compile_directory", + require => [File["$challenge_directory/$challenge_name"]] + } +} diff --git a/modules/build/puppet/secgen_functions/manifests/install_setuid_root_binary.pp b/modules/build/puppet/secgen_functions/manifests/install_setuid_root_binary.pp index a66ecbd6a..42159cbf0 100644 --- a/modules/build/puppet/secgen_functions/manifests/install_setuid_root_binary.pp +++ b/modules/build/puppet/secgen_functions/manifests/install_setuid_root_binary.pp @@ -31,7 +31,7 @@ define secgen_functions::install_setuid_root_binary ( home_mode => '0755', } } else { - err('dc16_amadhj::install: Either storage_directory or account is required') + err('install: Either storage_directory or account is required') fail } diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/dc16_amadhj_group.pp b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/dc16_amadhj_group.pp new file mode 100644 index 000000000..3cac9e788 --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/dc16_amadhj_group.pp @@ -0,0 +1 @@ +include dc16_amadhj_group::install diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/files/Makefile b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/files/Makefile new file mode 100644 index 000000000..c2f5746ad --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/files/Makefile @@ -0,0 +1,3 @@ +all: + gcc amadhj.c -o amadhj --static -s + diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/files/amadhj.c b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/files/amadhj.c new file mode 100644 index 000000000..06f20c902 --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/files/amadhj.c @@ -0,0 +1,445 @@ +#include +#include +#include +#include +#include +#include +#include + +uint64_t exp_l( uint64_t base, uint64_t power) +{ + int i = 0; + uint64_t j = base; + + if ( power == 0 ) { + return 1; + } + + for ( i = 0; i < power-1; i++) { + j *= base; + } + + return j; +} + +uint64_t xor( uint64_t a, uint64_t b) +{ + return a ^ b; +} + +uint64_t shla( uint64_t a, uint64_t dabits) +{ + uint64_t high = 0; + uint64_t low = 0; + + dabits = dabits % 64; + + if ( dabits == 0 ) { + return a; + } + + high = a << dabits; + low = a >> (64-dabits); + + return high | low; +} + +uint64_t shra( uint64_t a, uint64_t dabits) +{ + uint64_t high = 0; + uint64_t low = 0; + + dabits = dabits % 64; + + if ( dabits == 0 ) { + return a; + } + + low = a >> dabits; + high = a << (64-dabits); + + return high | low; +} + +/* + 0 1 2 3 4 5 6 7 + 5 0 4 6 7 3 1 2 +*/ +uint64_t swap_bytes( uint64_t value) +{ + uint64_t final = 0; + + final |= ( (value & 0xff) << 24); + final |= ( (value & 0xff00) << 24); + final |= ( (value & 0xff0000) << 40); + final |= ( (value & 0xff000000) << 16); + final |= ( (value & 0xff00000000) >> 16); + final |= ( (value & 0xff0000000000) >> 40); + final |= ( (value & 0xff000000000000) >> 40); + final |= ( (value & 0xff00000000000000) >> 8); + + return final; +} + +uint64_t swap_two( uint64_t value, uint64_t one, uint64_t two) +{ + uint64_t t_one = 0; + uint64_t t_two = 0; + + uint64_t mask_one = 0xff; + uint64_t mask_two = 0xff; + + mask_one <<= one*8; + mask_two <<= two*8; + + mask_one ^= 0xffffffffffffffff; + mask_two ^= 0xffffffffffffffff; + + t_one = (value >> (one*8)) & 0xff; + t_two = (value >> (two*8)) & 0xff; + + /// Clear the bits + value &= (mask_one & mask_two); + + value |= (t_two << ( one*8)); + value |= (t_one << ( two*8)); + + return value; +} + +uint64_t xor_neighbor( uint64_t value) +{ + int i = 0; + uint64_t t = 0; + + t |= ((value & 0xff00000000000000) >> 8) ^ (value & 0xff000000000000); + t |= ((value & 0xff000000000000) >> 8) ^ (value & 0xff0000000000); + t |= ((value & 0xff0000000000) >> 8) ^ (value & 0xff00000000); + t |= ((value & 0xff00000000) >> 8) ^ (value & 0xff000000); + t |= ((value & 0xff000000) >> 8) ^ (value & 0xff0000); + t |= ((value & 0xff0000) >> 8) ^ (value & 0xff00); + t |= ((value & 0xff00) >> 8) ^ (value & 0xff); + t |= ((value & 0xff) << 56) ^ (value & 0xff00000000000000); + + return t; +} + +uint64_t munge_one( uint64_t value ) +{ + value = xor( value, 0x35966a685c73335a); + value = swap_two( value, 2, 0); + value = xor( value, 0x89fdaf6604952df1); + value = xor( value, 0xe9f30f0ce704876a); + value = swap_two( value, 2, 3); + value = xor( value, 0xbdc5026d3c0b56e6); + value = shla( value, 16); + value = shla( value, 35); + value = shra( value, 19); + value = xor_neighbor( value ); + value = shla( value, 36); + value = shra( value, 40); + value = swap_two( value, 1, 0); + value = xor( value, 0x5de229fb3804db17); + value = swap_bytes( value ); + value = swap_bytes( value ); + value = swap_two( value, 2, 1); + value = xor( value, 0x6aad877366e921f5); + value = swap_two( value, 3, 0); + value = swap_bytes( value ); + value = xor( value, 0x58d83e9d5e6d5083); + value = shra( value, 22); + value = xor_neighbor( value ); + value = xor( value, 0x47b4d980070a9b73); + value = xor_neighbor( value ); + value = xor_neighbor( value ); + value = swap_two( value, 6, 5); + value = shla( value, 59); + value = swap_two( value, 5, 2); + value = swap_two( value, 2, 3); + value = shla( value, 12); + value = xor( value, 0xad25307f8e364b17); + value = xor( value, 0x48a56d5afe0da4c2); + value = shla( value, 6); + value = swap_two( value, 6, 5); + value = shra( value, 11); + value = swap_bytes( value ); + value = xor( value, 0x869365db4c9f3cb6); + value = swap_bytes( value ); + value = shra( value, 2); + value = xor( value, 0x4085aa8c0693425b); + value = shla( value, 35); + value = shla( value, 9); + value = xor_neighbor( value ); + value = shla( value, 7); + value = shla( value, 38); + value = xor_neighbor( value ); + value = xor( value, 0xdef2d72447ef4e1b); + value = swap_bytes( value ); + value = swap_bytes( value ); + value = swap_two( value, 2, 7); + value = shra( value, 51); + value = swap_bytes( value ); + value = shra( value, 19); + value = xor( value, 0x95de49591a44ee21); + value = xor_neighbor( value ); + value = swap_bytes( value ); + value = shra( value, 16); + return value; +} + +uint64_t munge_two( uint64_t value ) +{ + value = shla( value, 22); + value = swap_bytes( value ); + value = swap_two( value, 4, 1); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = shla( value, 35); + value = swap_two( value, 2, 6); + value = xor( value, 0x80a9ea4f90944fea); + value = shla( value, 3); + value = swap_two( value, 0, 1); + value = swap_two( value, 1, 2); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = swap_two( value, 5, 1); + value = shra( value, 24); + value = shla( value, 39); + value = swap_two( value, 2, 4); + value = xor( value, 0x678e70a16230a437); + value = swap_two( value, 4, 3); + value = swap_two( value, 0, 7); + value = shla( value, 62); + value = swap_bytes( value ); + value = swap_two( value, 7, 6); + value = swap_two( value, 2, 6); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = swap_two( value, 5, 2); + value = xor_neighbor( value ); + value = swap_two( value, 1, 7); + value = xor( value, 0x41ea5cf418a918e7); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = swap_two( value, 1, 4); + value = shla( value, 10); + value = swap_bytes( value ); + value = swap_bytes( value ); + value = shra( value, 24); + value = swap_two( value, 0, 4); + value = shra( value, 61); + value = swap_two( value, 3, 4); + value = shra( value, 35); + value = shla( value, 55); + value = shla( value, 34); + value = xor_neighbor( value ); + value = xor_neighbor( value ); + value = shra( value, 23); + value = shla( value, 59); + value = shra( value, 20); + value = shla( value, 28); + value = xor( value, 0xc26499379c0927cd); + value = xor_neighbor( value ); + value = shra( value, 13); + return value; +} + +uint64_t munge_three( uint64_t value ) +{ + value = shla( value, 18); + value = shla( value, 29); + value = swap_two( value, 5, 3); + value = swap_two( value, 0, 7); + value = shla( value, 18); + value = xor( value, 0xc9ab604bb92038ad); + value = shra( value, 33); + value = swap_two( value, 0, 4); + value = xor_neighbor( value ); + value = swap_two( value, 6, 2); + value = shra( value, 13); + value = shra( value, 20); + value = xor( value, 0x58609be21eb37866); + value = xor_neighbor( value ); + value = swap_bytes( value ); + value = shra( value, 46); + value = swap_two( value, 2, 3); + value = shra( value, 44); + value = shra( value, 3); + value = swap_two( value, 4, 3); + value = xor_neighbor( value ); + value = swap_two( value, 7, 6); + value = shra( value, 59); + value = shra( value, 38); + value = swap_bytes( value ); + value = swap_two( value, 1, 5); + value = swap_bytes( value ); + value = shla( value, 27); + value = xor( value, 0xbed577a97eb7966f); + value = shra( value, 14); + value = shla( value, 7); + value = shla( value, 18); + value = shla( value, 57); + value = xor( value, 0xb44427be7889c31b); + value = xor( value, 0xce745c65abecb66); + value = xor( value, 0x94b1608adb7f7221); + value = xor( value, 0x85bef139817ebc4a); + value = swap_two( value, 5, 1); + value = shla( value, 20); + value = shla( value, 24); + value = shra( value, 46); + value = shra( value, 13); + value = xor( value, 0xc95e5c35034b9775); + value = shla( value, 7); + value = xor( value, 0x8e60900383fa5ea); + value = xor( value, 0x59d5bcbf8b0cc9fd); + value = xor_neighbor( value ); + value = swap_two( value, 4, 7); + value = xor_neighbor( value ); + value = shra( value, 22); + value = shra( value, 50); + value = xor_neighbor( value ); + return value; +} + +uint64_t munge_four( uint64_t value ) +{ + value = swap_two( value, 1, 7); + value = shla( value, 6); + value = swap_two( value, 2, 5); + value = shra( value, 57); + value = xor( value, 0xc852fa4047662ce); + value = swap_two( value, 5, 1); + value = shla( value, 1); + value = xor_neighbor( value ); + value = xor( value, 0x5ddfc2422c2a449e); + value = xor_neighbor( value ); + value = shla( value, 6); + value = xor_neighbor( value ); + value = shla( value, 33); + value = shra( value, 25); + value = xor_neighbor( value ); + value = xor( value, 0xa94a4c87a942c60); + value = swap_two( value, 6, 2); + value = xor_neighbor( value ); + value = xor( value, 0xcc508fa31a0da5ab); + value = xor( value, 0x880218b9f910dcbc); + value = xor_neighbor( value ); + value = xor( value, 0x85d7e666ecdba611); + value = shra( value, 8); + value = shra( value, 43); + value = xor( value, 0x633a915bd59ac97b); + value = swap_two( value, 3, 1); + value = swap_two( value, 5, 7); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = shra( value, 59); + value = shra( value, 10); + value = xor_neighbor( value ); + value = swap_two( value, 2, 1); + value = swap_two( value, 7, 2); + value = xor_neighbor( value ); + value = xor( value, 0x648fff323d235735); + value = xor( value, 0xfc9f8d635fd85eb3); + value = xor( value, 0xff651571c16e5cb3); + value = swap_two( value, 2, 4); + value = swap_two( value, 5, 4); + value = shra( value, 11); + value = xor_neighbor( value ); + value = shla( value, 39); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = xor( value, 0xc798d4e5c0e97b1c); + value = swap_bytes( value ); + value = xor_neighbor( value ); + value = shla( value, 35); + value = swap_two( value, 3, 5); + value = xor_neighbor( value ); + value = swap_bytes( value ); + value = xor_neighbor( value ); + return value; +} + +int munge_all( unsigned char *data ) +{ + int i = 0; + uint64_t *base = NULL; + uint64_t one; + uint64_t two; + uint64_t thr; + uint64_t fou; + + read( 0, data, 32); + + for ( i = 0; i < 32; i++ ) { + if ( ((data[i] < 0x41) || ( 0x7a < data[i])) && (data[i] != 0x20) ) { + return 0; + } else if ( data[i] == ']') { + return 0; + } else if ( data[i] == '\\') { + return 0; + } else if ( data[i] == '^') { + return 0; + } else if ( data[i] == '`') { + return 0; + } else if ( data[i] == '[') { + return 0; + } + } + + base = (uint64_t*)data; + + one = munge_one( base[0]); + two = munge_two( base[1]); + thr = munge_three( base[2]); + fou = munge_four( base[3]); + + one = one^two^thr^fou; + + if ( one == 0xb101124831c0110a) { + return 1; + } + + return 0; +} + +void printflag() +{ + int fd; + int len; + unsigned char data[128]; + + fd = open("flag", O_RDONLY); + + if ( fd <= 0 ) { + printf("Failed to open flag.\n"); + return; + } + + len = lseek( fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + + if ( len > 128 ) { + len = 128; + } + + memset(data, 0, 128); + read( fd, data, len); + close(fd); + + printf("%s\n", data); + return; +} + +int main(int argc, char**argv) +{ + int fd; + unsigned char data[32]; + + bzero( data, 32 ); + + if ( munge_all( data ) ) { + printflag(); + } + + return 0; +} diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/manifests/install.pp b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/manifests/install.pp new file mode 100644 index 000000000..9aebbd3d8 --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/manifests/install.pp @@ -0,0 +1,22 @@ +class dc16_amadhj_group::install { + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) + + if $secgen_params['account'][0] != ''{ + $account = parsejson($secgen_params['account'][0]) + } else { + $account = undef + } + notice("account: ") + notice($account) + + ::secgen_functions::install_setgid_binary { 'defcon16_amadhj_group': + source_module_name => 'dc16_amadhj_group', + challenge_name => $secgen_params['challenge_name'][0], + group => $secgen_params['group'][0], + account => $account, + flag => $secgen_params['flag'][0], + flag_name => 'flag', + storage_dir => $secgen_params['storage_directory'][0], + strings_to_leak => $secgen_params['strings_to_leak'], + } +} diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/secgen_metadata.xml b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/secgen_metadata.xml new file mode 100644 index 000000000..55b0e5ccf --- /dev/null +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj_group/secgen_metadata.xml @@ -0,0 +1,50 @@ + + + + DefCon Quals 2016 - amadhj + Thomas Shaw + MIT + Binary Reverse Engineering CTF Challenge from the Defcon 2016 CTF Qualifier. + + ctf_challenge + reverse_engineering + none + local + linux + + + challenge_name + group + account + flag + strings_to_leak + + storage_directory + + + amadhj + + + test + + + + + challenges + + + password + + + + + + + + + utilities/unix/system/accounts + + + diff --git a/modules/vulnerabilities/unix/system/binary_script_container/binary_script_container.pp b/modules/vulnerabilities/unix/system/binary_script_container/binary_script_container.pp new file mode 100644 index 000000000..78e4d5c9b --- /dev/null +++ b/modules/vulnerabilities/unix/system/binary_script_container/binary_script_container.pp @@ -0,0 +1 @@ +require ruby_script_container::init \ No newline at end of file diff --git a/modules/vulnerabilities/unix/system/binary_script_container/manifests/account.pp b/modules/vulnerabilities/unix/system/binary_script_container/manifests/account.pp new file mode 100644 index 000000000..31387405e --- /dev/null +++ b/modules/vulnerabilities/unix/system/binary_script_container/manifests/account.pp @@ -0,0 +1,42 @@ +define ruby_script_container::account($username, $group, $password, $strings_to_leak, $leaked_filenames) { + + group { $group: + ensure => present, + } + + ::accounts::user { $username: + shell => '/bin/bash', + password => pw_hash($password, 'SHA-512', 'mysalt'), + managehome => true, + home_mode => '0755', + groups => [$group], + require => Group[$group], + } + + # strings_to_leak[0]: flag in /home//flag.txt + ::secgen_functions::leak_files { "$username-file-leak": + storage_directory => "/home/$username/", + leaked_filenames => $leaked_filenames, + strings_to_leak => [$strings_to_leak[0]], + owner => $username, + group => $group, + mode => '2440', + leaked_from => "accounts_$username", + require => Group[$group], + } + + file { "/home/$username/test.rb": + owner => $username, + group => $group, + mode => '2777', + ensure => file, + content => template('ruby_script_container/template.rb.erb'), + require => Group[$group], + } + + # exec { "$username-compileandsetup1": + # cwd => "/home/$username/", + # command => "sudo chown $username:shadow prompt && sudo chmod 2755 prompt", + # path => [ '/bin/', '/sbin/' , '/usr/bin/', '/usr/sbin/' ], + # } +} \ No newline at end of file diff --git a/modules/vulnerabilities/unix/system/binary_script_container/manifests/init.pp b/modules/vulnerabilities/unix/system/binary_script_container/manifests/init.pp new file mode 100644 index 000000000..b49a828e0 --- /dev/null +++ b/modules/vulnerabilities/unix/system/binary_script_container/manifests/init.pp @@ -0,0 +1,25 @@ +class ruby_script_container::init { + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) + $group = $secgen_parameters['group'][0] + + ::accounts::user { 'temp': + shell => '/bin/bash', + password => pw_hash('temp', 'SHA-512', 'mysalt'), + managehome => true, + home_mode => '0755', + groups => [$group], + } + + $accounts = $secgen_parameters['accounts'] + $accounts.each |$raw_account| { + $account = parsejson($raw_account) + $username = $account['username'] + ruby_script_container::account { "script_container_$username": + username => $username, + password => $account['password'], + group => $group, + strings_to_leak => $account['strings_to_leak'], + leaked_filenames => $account['leaked_filenames'] + } + } +} \ No newline at end of file diff --git a/modules/vulnerabilities/unix/system/binary_script_container/secgen_metadata.xml b/modules/vulnerabilities/unix/system/binary_script_container/secgen_metadata.xml new file mode 100644 index 000000000..ba573f519 --- /dev/null +++ b/modules/vulnerabilities/unix/system/binary_script_container/secgen_metadata.xml @@ -0,0 +1,49 @@ + + + + Binary script container + Thomas Shaw + MIT + Binary container module for script based challenges. + + system + script_challenge_container + none + local + linux + + accounts + + + + + test + + + + + flag.txt + + + + + + + + + utilities/unix/system/accounts + + + + utilities/.*ruby.* + + + + + + + + + \ No newline at end of file diff --git a/modules/vulnerabilities/unix/system/binary_script_container/templates/template.rb.erb b/modules/vulnerabilities/unix/system/binary_script_container/templates/template.rb.erb new file mode 100644 index 000000000..b760bd8c7 --- /dev/null +++ b/modules/vulnerabilities/unix/system/binary_script_container/templates/template.rb.erb @@ -0,0 +1,3 @@ +puts "hallo worlden!" + +File.read('/home/test/flag.txt') \ No newline at end of file diff --git a/scenarios/examples/ctf_challenge_examples/setgid_pwnable_binary_example.xml b/scenarios/examples/ctf_challenge_examples/setgid_pwnable_binary_example.xml new file mode 100644 index 000000000..1f3e71b24 --- /dev/null +++ b/scenarios/examples/ctf_challenge_examples/setgid_pwnable_binary_example.xml @@ -0,0 +1,31 @@ + + + + + + + reverse_me + + + + + + + + + + + + + + + + + + + + +