mirror of
https://github.com/cliffe/SecGen.git
synced 2026-02-21 11:18:06 +00:00
WiP: Script container and script generator tracer code - need to build the shebang into the module and finish implementing setuid script function
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# Install function for setgid binaries
|
||||
# -- Modules calling this function must provide a Makefile and any .c files within it's <module_name>/files directory
|
||||
|
||||
define secgen_functions::install_setgid_script (
|
||||
$challenge_name, # Challenge name, used for the wrapper-directory
|
||||
$script_name, # Script filename
|
||||
$script_data, # Script data
|
||||
$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"
|
||||
|
||||
group { $group:
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
# Create challenge directory
|
||||
::secgen_functions::create_directory { "create_$challenge_directory":
|
||||
path => $challenge_directory,
|
||||
notify => File["$challenge_directory/$script_name"],
|
||||
}
|
||||
|
||||
# Move the compiled binary into the challenge directory
|
||||
file { "$challenge_directory/$script_name":
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
group => $group,
|
||||
mode => '4775',
|
||||
content => $script_data,
|
||||
require => Group[$group],
|
||||
}
|
||||
|
||||
# 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 => '0440',
|
||||
leaked_from => "accounts_$username",
|
||||
require => Group[$group],
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
# Install function for setuid_root binaries
|
||||
# -- Modules calling this function must provide a Makefile and any .c files within it's <module_name>/files directory
|
||||
|
||||
define secgen_functions::install_setuid_root_binary (
|
||||
$challenge_name, # Challenge name, used for the wrapper-directory
|
||||
$source_module_name, # Name of the module that calls this function
|
||||
$account, # User account (leak here if $storage_directory is not supplied)
|
||||
$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"
|
||||
|
||||
# Create challenge directory
|
||||
::secgen_functions::create_directory { "create_$challenge_directory":
|
||||
path => $challenge_directory,
|
||||
notify => File["create_$compile_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_$compile_directory"]
|
||||
}
|
||||
|
||||
# Move the compiled binary into the challenge directory
|
||||
file { "$challenge_directory/$challenge_name":
|
||||
ensure => present,
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
mode => '4755',
|
||||
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',
|
||||
mode => '0400',
|
||||
leaked_from => "accounts_$username",
|
||||
require => 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"]]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
require_relative '../../../../../../../lib/objects/local_string_generator.rb'
|
||||
class RubyExampleScriptGenerator < StringGenerator
|
||||
|
||||
def initialize
|
||||
super
|
||||
self.module_name = 'Ruby Example Script Generator'
|
||||
end
|
||||
|
||||
|
||||
def generate
|
||||
self.outputs << "#!/usr/local/bin/suid /usr/bin/ruby --
|
||||
puts File.read('flag')"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
RubyExampleScriptGenerator.new.run
|
||||
@@ -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>ruby_script_challenge</type>
|
||||
|
||||
<platform>linux</platform>
|
||||
<platform>windows</platform>
|
||||
|
||||
<output_type>script</output_type>
|
||||
|
||||
</generator>
|
||||
@@ -0,0 +1 @@
|
||||
require binary_script_container::install
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/local/bin/suid /bin/bash -o privileged --
|
||||
set -eu
|
||||
echo uid=$(id -run) euid=$(id -un)
|
||||
echo gid=$(id -rgn) egid=$(id -gn)
|
||||
@@ -0,0 +1,206 @@
|
||||
/* Generic setuid/setgid wrapper for scripts.
|
||||
*
|
||||
* Copyright (c) 2016 Likai Liu <liulk@likai.org>
|
||||
*
|
||||
* Usage of the works is permitted provided that this instrument is
|
||||
* retained with the works, so that any entity that uses the works is
|
||||
* notified of this instrument.
|
||||
* DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Usage: use the following shebang line in the script.
|
||||
* #!/usr/local/bin/suid /path/to/interpreter [options] --
|
||||
*
|
||||
* Mac OS X ignores the setuid of the first interpreter, so we reexec
|
||||
* ourselves to get it back. Linux will pass /path/to/interpreter and
|
||||
* all the options to us as one argument, but we will split them by
|
||||
* whitespaces only (no quotes).
|
||||
*
|
||||
* Interpreter options must be given before the "--" marker which is
|
||||
* mandatory. The implicit last argument is the script itself, which
|
||||
* must also have the executable bit set as well as setuid or setgid.
|
||||
*
|
||||
* For shell scripts, it is necessary to pass -p or -o privileged to
|
||||
* /bin/bash in the shebang line, or it will reset the effective uid
|
||||
* and gid to the real ones. Other options are strongly recommended
|
||||
* to be set explicitly in the script, e.g. "set -eu".
|
||||
*
|
||||
* A setuid binary has getuid() set to the invoking user, and
|
||||
* geteuid() set to the owner of the binary. This wrapper will keep
|
||||
* the same getuid() and getgid() but further modify geteuid() and
|
||||
* geteguid() to the owner of the script, according to the setuid and
|
||||
* setgid bits of the script itself. In order for this to work, the
|
||||
* wrapper binary itself must be setuid root or the script owner.
|
||||
*
|
||||
* Here are the safety measures we take:
|
||||
*
|
||||
* - All LD_* and DYLD_* environment variables are cleared.
|
||||
* - The script name is replaced with /dev/fd/NN.
|
||||
*
|
||||
* The script is responsible for ensuring sane IFS and PATH. Note
|
||||
* that on bash, IFS changes the way variables are expanded when it
|
||||
* appears on a command line, but hard-coded text remains unaffected.
|
||||
*
|
||||
* Further reading:
|
||||
* http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/avoid-setuid.html
|
||||
* http://profesores.elo.utfsm.cl/~agv/elo330/programs/shell/NotUseSetuidScripts.html
|
||||
* http://burrows.svbtle.com/bash-privileged-mode-quirk
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char usage[] =
|
||||
"Usage: use the following shebang line in the script.\n"
|
||||
" #!/path/to/suid /path/to/interpreter [options] --\n";
|
||||
|
||||
extern char **environ;
|
||||
|
||||
static void sanitize_environ(char **environ) {
|
||||
int in, out;
|
||||
for (in = 0, out = 0; environ[in] != NULL; ++in) {
|
||||
if (strncmp(environ[in], "LD_", 3) == 0 ||
|
||||
strncmp(environ[in], "DYLD_", 5) == 0)
|
||||
continue; /* skip */
|
||||
environ[out++] = environ[in]; /* keep */
|
||||
}
|
||||
environ[out] = NULL; /* terminate list */
|
||||
}
|
||||
|
||||
/* always returns the true next powers of 2; e.g. next_pow2(8) returns 16 */
|
||||
static int next_pow2(int n) {
|
||||
int i = 0;
|
||||
while (n)
|
||||
++i, n >>= 1;
|
||||
return 1 << i;
|
||||
}
|
||||
|
||||
typedef struct arg_s {
|
||||
int c /* count */, n /* capacity */;
|
||||
char **v /* malloc */;
|
||||
} arg_t;
|
||||
|
||||
static char *nextspace(const char *s) {
|
||||
while (*s && !isspace(*s))
|
||||
++s;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
static char *skipspace(const char *s) {
|
||||
while (isspace(*s))
|
||||
++s;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
static arg_t split_argv(int argc, char **old_argv) {
|
||||
/* argc does not count the trailing NULL pointer in argv */
|
||||
size_t argn = next_pow2(argc + 1);
|
||||
char **argv = (char **) malloc(sizeof(char *) * argn);
|
||||
|
||||
int in = 0, out = 0;
|
||||
argv[out++] = strdup(old_argv[in++]);
|
||||
|
||||
if (in >= argc)
|
||||
goto done;
|
||||
|
||||
/* split old_argv[1] */
|
||||
char *stop, *start;
|
||||
for (start = old_argv[in++]; *start; start = stop) {
|
||||
start = skipspace(start), stop = nextspace(start);
|
||||
if (start == stop) break; /* trailing space */
|
||||
argv[out++] = strndup(start, stop - start);
|
||||
if (argn <= out)
|
||||
argn <<= 1, argv = (char **) realloc(argv, sizeof(char *) * argn);
|
||||
/* if realloc() fails, just segmentation fault on NULL access */
|
||||
}
|
||||
|
||||
/* copy the remaining arguments */
|
||||
while (in < argc) {
|
||||
argv[out++] = strdup(old_argv[in++]);
|
||||
if (argn <= out)
|
||||
argn <<= 1, argv = (char **) realloc(argv, sizeof(char *) * argn);
|
||||
/* if realloc() fails, just segmentation fault on NULL access */
|
||||
}
|
||||
|
||||
done:
|
||||
argv[out] = NULL;
|
||||
|
||||
struct arg_s r = { out, argn, argv };
|
||||
return r;
|
||||
}
|
||||
|
||||
static int find_dashdash(int argc, char **argv, int i) {
|
||||
while (i < argc) {
|
||||
if (strcmp("--", argv[i]) == 0)
|
||||
return i;
|
||||
++i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
sanitize_environ(environ);
|
||||
|
||||
const char *self = argv[0];
|
||||
struct stat statself;
|
||||
if (stat(self, &statself) < 0)
|
||||
return perror(self), EX_IOERR;
|
||||
|
||||
if (statself.st_mode & S_ISUID) {
|
||||
if (geteuid() != statself.st_uid) { /* OS ignored our setuid bit, */
|
||||
execv(argv[0], argv); /* rerun self to get setuid back. */
|
||||
return perror(argv[0]), EX_OSERR;
|
||||
}
|
||||
}
|
||||
|
||||
arg_t arg = split_argv(argc, argv);
|
||||
|
||||
int dashdash = find_dashdash(arg.c, arg.v, 2);
|
||||
if (dashdash < 0 || dashdash + 1 >= arg.c)
|
||||
return fputs(usage, stderr), EX_USAGE;
|
||||
|
||||
const char *interp = arg.v[1], *script = arg.v[dashdash + 1];
|
||||
|
||||
/* access() checks permission using real uid and gid (set to the
|
||||
* invoking user) as opposed to the effective uid and gid (set to
|
||||
* the binary).
|
||||
*/
|
||||
if (access(interp, X_OK) < 0)
|
||||
return perror(interp), EX_NOPERM;
|
||||
if (access(script, X_OK | R_OK) < 0)
|
||||
return perror(script), EX_NOPERM;
|
||||
|
||||
int fd = open(script, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return perror(script), EX_NOPERM;
|
||||
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "/dev/fd/%d", fd);
|
||||
|
||||
struct stat statbuf;
|
||||
if (fstat(fd, &statbuf) < 0)
|
||||
return perror(script), EX_IOERR;
|
||||
|
||||
#define SETEXID(xid, S_ISXID) \
|
||||
if (sete##xid(statbuf.st_mode & S_ISXID ? \
|
||||
statbuf.st_##xid : get##xid()) < 0) \
|
||||
return perror("sete" #xid), EX_NOPERM;
|
||||
|
||||
/* set effective gid first, or we might not be able to do that after
|
||||
* setting effective uid away from root.
|
||||
*/
|
||||
SETEXID(gid, S_ISGID);
|
||||
SETEXID(uid, S_ISUID);
|
||||
#undef SETEXID
|
||||
|
||||
arg.v[dashdash + 1] = buf; /* override script to fd */
|
||||
execv(arg.v[1], arg.v + 1); /* normally should not return. */
|
||||
return perror(arg.v[1]), EX_OSERR;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
class binary_script_container::install {
|
||||
|
||||
# Create temp install directory
|
||||
file { '/root/tmp':
|
||||
ensure => directory,
|
||||
}
|
||||
|
||||
# Move wrapper.c onto box
|
||||
file { "/root/tmp/suid.c":
|
||||
ensure => file,
|
||||
source => 'puppet:///modules/binary_script_container/wrapper.c',
|
||||
}
|
||||
|
||||
# Make and install
|
||||
exec { "wrapper make install":
|
||||
command => 'make suid; install -m a+rx,u+ws -s ./suid /usr/local/bin/suid',
|
||||
cwd => '/root/tmp',
|
||||
path => '/bin:/sbin:/usr/bin:/usr/sbin',
|
||||
}
|
||||
|
||||
# Create group for test TODO: remove me
|
||||
group { 'test':
|
||||
ensure => present
|
||||
}
|
||||
|
||||
file { '/home/tmp':
|
||||
ensure => directory,
|
||||
}
|
||||
|
||||
# Move test file onto box TODO: remove me
|
||||
file { "/home/tmp/test.sh":
|
||||
ensure => file,
|
||||
source => 'puppet:///modules/binary_script_container/test.sh',
|
||||
group => 'test',
|
||||
mode => '2775',
|
||||
require => [Group['test'],File['/home/tmp']],
|
||||
}
|
||||
|
||||
|
||||
# Test: add a flag file with a group TODO: remove me
|
||||
::secgen_functions::leak_files { "flag-file-leak":
|
||||
storage_directory => "/home/tmp/",
|
||||
leaked_filenames => ['flag'],
|
||||
strings_to_leak => ['flag{wayy!!!}'],
|
||||
owner => 'root',
|
||||
group => 'test',
|
||||
mode => '0440',
|
||||
leaked_from => "binary_script_container_flag",
|
||||
require => [Group['test'], File["/home/tmp/test.sh"]],
|
||||
}
|
||||
|
||||
|
||||
# Remove temp install directory
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<utility xmlns="http://www.github/cliffe/SecGen/utility"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/utility">
|
||||
<name>Binary script container</name>
|
||||
<author>Likai Liu</author>
|
||||
<author>Thomas Shaw</author>
|
||||
<module_license>MIT</module_license>
|
||||
<description>Binary container module for script based challenges.</description>
|
||||
|
||||
<type>system</type>
|
||||
<type>script_challenge_container</type>
|
||||
|
||||
<platform>linux</platform>
|
||||
|
||||
<reference>https://lifecs.likai.org/p/suid.html</reference>
|
||||
|
||||
</utility>
|
||||
@@ -0,0 +1,43 @@
|
||||
class ruby_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 { 'ruby_challenge_example':
|
||||
source_module_name => $module_name,
|
||||
challenge_name => $secgen_params['challenge_name'][0],
|
||||
script_name => 'test.rb',
|
||||
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_binary { 'ruby_challenge_example':
|
||||
# source_module_name => $module_name,
|
||||
# challenge_name => $secgen_params['challenge_name'][0],
|
||||
# account => $account,
|
||||
# flag => $secgen_params['flag'][0],
|
||||
# flag_name => 'flag',
|
||||
# storage_dir => $storage_dir,
|
||||
# strings_to_leak => $secgen_params['strings_to_leak'],
|
||||
# }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
include ruby_challenge_example::install
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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>Ruby Challenge Example</name>
|
||||
<author>Thomas Shaw</author>
|
||||
<module_license>MIT</module_license>
|
||||
<description>Ruby challenge example</description>
|
||||
|
||||
<type>ctf_challenge</type>
|
||||
<type>script_challenge</type>
|
||||
<privilege>none</privilege>
|
||||
<access>local</access>
|
||||
<platform>linux</platform>
|
||||
|
||||
<!-- binary dropped in account's home directory by default. -->
|
||||
<read_fact>challenge_name</read_fact>
|
||||
<read_fact>script_data</read_fact>
|
||||
<read_fact>group</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>
|
||||
|
||||
<default_input into="challenge_name">
|
||||
<value>ruby_script_example</value>
|
||||
</default_input>
|
||||
<default_input into="script_data">
|
||||
<generator module_path=".*ruby_example"/>
|
||||
</default_input>
|
||||
<default_input into="group">
|
||||
<value>test1</value>
|
||||
</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>ruby_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/ruby</module_path>
|
||||
</requires>
|
||||
|
||||
</vulnerability>
|
||||
@@ -0,0 +1,29 @@
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Crackme
|
||||
{
|
||||
public Crackme()
|
||||
{
|
||||
}
|
||||
|
||||
public static void main(String args[])
|
||||
{
|
||||
System.out.println("Please enter the password:");
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
String s = scanner.next();
|
||||
if(s.equals("<%= @password %>"))
|
||||
{
|
||||
System.out.println("Correct");
|
||||
System.out.print("Your key is: ");
|
||||
<% @flag.split('').each do |char|-%>
|
||||
System.out.print("<%= char %>");
|
||||
<% end %>
|
||||
System.out.print("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Wrong");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
require ruby_script_container::init
|
||||
@@ -1,42 +0,0 @@
|
||||
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/<username>/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/' ],
|
||||
# }
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
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']
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?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>Binary script container</name>
|
||||
<author>Thomas Shaw</author>
|
||||
<module_license>MIT</module_license>
|
||||
<description>Binary container module for script based challenges.</description>
|
||||
|
||||
<type>system</type>
|
||||
<type>script_challenge_container</type>
|
||||
<privilege>none</privilege>
|
||||
<access>local</access>
|
||||
<platform>linux</platform>
|
||||
|
||||
<read_fact>accounts</read_fact>
|
||||
|
||||
<default_input into="accounts">
|
||||
<generator type="account">
|
||||
<input into="username">
|
||||
<value>test</value>
|
||||
</input>
|
||||
<input into="password">
|
||||
</input>
|
||||
<input into="leaked_filenames">
|
||||
<value>flag.txt</value>
|
||||
</input>
|
||||
<input into="strings_to_leak">
|
||||
<generator type="flag_generator"/> <!-- flag in /home/<username>/flag.txt -->
|
||||
</input>
|
||||
</generator>
|
||||
</default_input>
|
||||
|
||||
<requires>
|
||||
<module_path>utilities/unix/system/accounts</module_path>
|
||||
</requires>
|
||||
|
||||
<requires>
|
||||
<module_path>utilities/.*ruby.*</module_path>
|
||||
</requires>
|
||||
|
||||
|
||||
<!-- Need a way on to the box. -->
|
||||
<!--<requires>-->
|
||||
<!--<privilege>user_rwx</privilege>-->
|
||||
<!--</requires>-->
|
||||
|
||||
</vulnerability>
|
||||
@@ -1,3 +0,0 @@
|
||||
puts "hallo worlden!"
|
||||
|
||||
File.read('/home/test/flag.txt')
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<scenario xmlns="http://www.github/cliffe/SecGen/scenario"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario">
|
||||
|
||||
<!-- TODO: Should container be a utility? -->
|
||||
|
||||
<system>
|
||||
<system_name>challenge_server</system_name>
|
||||
<base platform="linux" type="server"/>
|
||||
|
||||
<utility module_path=".*binary_script_container"/>
|
||||
|
||||
<network type="private_network" range="dhcp" />
|
||||
</system>
|
||||
|
||||
</scenario>
|
||||
@@ -10,25 +10,25 @@
|
||||
<base platform="linux" type="server"/>
|
||||
|
||||
<!-- 1) Default uses an account and drops the binary in the users home directory -->
|
||||
<vulnerability type="pwnable_binary">
|
||||
<input into="group">
|
||||
<value>task1</value>
|
||||
</input>
|
||||
</vulnerability>
|
||||
|
||||
<!-- 2) Using a custom storage directory -->
|
||||
<!--<vulnerability type="pwnable_binary">-->
|
||||
<!--<input into="group">-->
|
||||
<!--<value>task2</value>-->
|
||||
<!--</input>-->
|
||||
<!--<input into="account">-->
|
||||
<!--<value/>-->
|
||||
<!--</input>-->
|
||||
<!--<input into="storage_directory">-->
|
||||
<!--<value>/test/hidden/challenges</value>-->
|
||||
<!--<value>task1</value>-->
|
||||
<!--</input>-->
|
||||
<!--</vulnerability>-->
|
||||
|
||||
<!-- 2) Using a custom storage directory -->
|
||||
<vulnerability type="pwnable_binary">
|
||||
<input into="group">
|
||||
<value>task2</value>
|
||||
</input>
|
||||
<input into="account">
|
||||
<value/>
|
||||
</input>
|
||||
<input into="storage_directory">
|
||||
<value>/test/hidden/challenges</value>
|
||||
</input>
|
||||
</vulnerability>
|
||||
|
||||
<network type="private_network" range="dhcp"/>
|
||||
</system>
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<scenario xmlns="http://www.github/cliffe/SecGen/scenario"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.github/cliffe/SecGen/scenario">
|
||||
|
||||
<!-- an example system with a setgid binary. -->
|
||||
<system>
|
||||
<system_name>group_challenges</system_name>
|
||||
<base platform="linux" type="server"/>
|
||||
|
||||
<!-- 1) Default uses an account and drops the binary in the users home directory -->
|
||||
<vulnerability type="script_challenge">
|
||||
<input into="group">
|
||||
<value>task1</value>
|
||||
</input>
|
||||
</vulnerability>
|
||||
|
||||
<!-- 2) Using a custom storage directory -->
|
||||
<!--<vulnerability type="pwnable_binary">-->
|
||||
<!--<input into="group">-->
|
||||
<!--<value>task2</value>-->
|
||||
<!--</input>-->
|
||||
<!--<input into="account">-->
|
||||
<!--<value/>-->
|
||||
<!--</input>-->
|
||||
<!--<input into="storage_directory">-->
|
||||
<!--<value>/test/hidden/challenges</value>-->
|
||||
<!--</input>-->
|
||||
<!--</vulnerability>-->
|
||||
|
||||
<network type="private_network" range="dhcp"/>
|
||||
</system>
|
||||
|
||||
</scenario>
|
||||
Reference in New Issue
Block a user