From c910ad8f8db9ff5b42795e2aec86216d4e6f4151 Mon Sep 17 00:00:00 2001 From: Marc van der Wal Date: Wed, 25 Oct 2023 15:50:24 +0200 Subject: [PATCH] =?UTF-8?q?API=20REST=20pour=20l=E2=80=99attaquant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- attacker/Dockerfile | 57 ++++++++++++++++++- attacker/web-api/.dancer | 0 attacker/web-api/MANIFEST | 24 ++++++++ attacker/web-api/MANIFEST.SKIP | 17 ++++++ attacker/web-api/Makefile.PL | 26 +++++++++ attacker/web-api/bin/app.psgi | 9 +++ attacker/web-api/config.yml | 4 ++ attacker/web-api/cpanfile | 11 ++++ attacker/web-api/environments/development.yml | 15 +++++ attacker/web-api/environments/production.yml | 16 ++++++ .../lib/Email/SpoofingDemo/API/Attacker.pm | 56 ++++++++++++++++++ attacker/web-api/public/dispatch.cgi | 16 ++++++ attacker/web-api/public/dispatch.fcgi | 18 ++++++ 13 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 attacker/web-api/.dancer create mode 100644 attacker/web-api/MANIFEST create mode 100644 attacker/web-api/MANIFEST.SKIP create mode 100644 attacker/web-api/Makefile.PL create mode 100644 attacker/web-api/bin/app.psgi create mode 100644 attacker/web-api/config.yml create mode 100644 attacker/web-api/cpanfile create mode 100644 attacker/web-api/environments/development.yml create mode 100644 attacker/web-api/environments/production.yml create mode 100644 attacker/web-api/lib/Email/SpoofingDemo/API/Attacker.pm create mode 100644 attacker/web-api/public/dispatch.cgi create mode 100644 attacker/web-api/public/dispatch.fcgi diff --git a/attacker/Dockerfile b/attacker/Dockerfile index 3ba1fbd..3d3fc49 100644 --- a/attacker/Dockerfile +++ b/attacker/Dockerfile @@ -19,10 +19,61 @@ RUN apk add \ RUN pip install dkimpy +# Dependencies for REST API +RUN apk add \ + gcc \ + libc-dev \ + make \ + perl-app-cpanminus \ + perl-clone \ + perl-config-any \ + perl-data-optlist \ + perl-dev \ + perl-exporter-tiny \ + perl-extutils-config \ + perl-extutils-helpers \ + perl-extutils-installpaths \ + perl-file-sharedir \ + perl-file-sharedir-install \ + perl-file-slurp \ + perl-file-which \ + perl-hash-merge-simple \ + perl-hash-multivalue \ + perl-http-date \ + perl-http-headers-fast \ + perl-import-into \ + perl-json-maybexs \ + perl-module-build \ + perl-module-build-tiny \ + perl-module-implementation \ + perl-module-runtime \ + perl-moo \ + perl-params-util \ + perl-params-validate \ + perl-path-tiny \ + perl-plack \ + perl-readonly \ + perl-ref-util \ + perl-role-tiny \ + perl-safe-isa \ + perl-sub-exporter \ + perl-sub-install \ + perl-sub-quote \ + perl-template-toolkit \ + perl-type-tiny \ + perl-yaml + +RUN cpanm -n -v \ + Dancer2 \ + Module::Pluggable::Object + # TODO mettre un bashrc qui positionne un prompt qui montre bien qu’on est # en train d’être méchant -USER attaquant -ENTRYPOINT ["/bin/bash"] - COPY --chown=attaquant scripts /home/attaquant/scripts + +COPY web-api /src/api +RUN chmod +x /src/api/bin/app.psgi + +USER attaquant +ENTRYPOINT ["/src/api/bin/app.psgi"] diff --git a/attacker/web-api/.dancer b/attacker/web-api/.dancer new file mode 100644 index 0000000..e69de29 diff --git a/attacker/web-api/MANIFEST b/attacker/web-api/MANIFEST new file mode 100644 index 0000000..aada075 --- /dev/null +++ b/attacker/web-api/MANIFEST @@ -0,0 +1,24 @@ +MANIFEST +MANIFEST.SKIP +.dancer +Makefile.PL +config.yml +cpanfile +views/index.tt +views/layouts/main.tt +lib/Email/SpoofingDemo/API/DNS.pm +t/002_index_route.t +t/001_base.t +environments/production.yml +environments/development.yml +bin/app.psgi +public/500.html +public/dispatch.cgi +public/dispatch.fcgi +public/favicon.ico +public/404.html +public/javascripts/jquery.js +public/css/error.css +public/css/style.css +public/images/perldancer-bg.jpg +public/images/perldancer.jpg diff --git a/attacker/web-api/MANIFEST.SKIP b/attacker/web-api/MANIFEST.SKIP new file mode 100644 index 0000000..bbfb365 --- /dev/null +++ b/attacker/web-api/MANIFEST.SKIP @@ -0,0 +1,17 @@ +^\.git\/ +maint +^tags$ +.last_cover_stats +Makefile$ +^blib +^pm_to_blib +^.*.bak +^.*.old +^t.*sessions +^cover_db +^.*\.log +^.*\.swp$ +MYMETA.* +^.gitignore +^.svn\/ +^Email-SpoofingDemo-API-DNS- diff --git a/attacker/web-api/Makefile.PL b/attacker/web-api/Makefile.PL new file mode 100644 index 0000000..ba7d937 --- /dev/null +++ b/attacker/web-api/Makefile.PL @@ -0,0 +1,26 @@ +use strict; +use warnings; +use ExtUtils::MakeMaker; + +# Normalize version strings like 6.30_02 to 6.3002, +# so that we can do numerical comparisons on it. +my $eumm_version = $ExtUtils::MakeMaker::VERSION; +$eumm_version =~ s/_//; + +WriteMakefile( + NAME => 'Email::SpoofingDemo::API::DNS', + AUTHOR => q{Marc van der Wal }, + VERSION_FROM => 'lib/Email/SpoofingDemo/API/DNS.pm', + ABSTRACT => 'Email spoofing demo: REST API for DNS', + ($eumm_version >= 6.3001 + ? ('LICENSE'=> 'all-rights-reserved') + : ()), + PL_FILES => {}, + PREREQ_PM => { + 'Test::More' => 0, + 'YAML' => 0, + 'Dancer2' => 0.300000, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Email-SpoofingDemo-API-DNS-*' }, +); diff --git a/attacker/web-api/bin/app.psgi b/attacker/web-api/bin/app.psgi new file mode 100644 index 0000000..01987bd --- /dev/null +++ b/attacker/web-api/bin/app.psgi @@ -0,0 +1,9 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use FindBin; +use lib "$FindBin::Bin/../lib"; + +use Email::SpoofingDemo::API::Attacker; +Email::SpoofingDemo::API::Attacker->to_app; diff --git a/attacker/web-api/config.yml b/attacker/web-api/config.yml new file mode 100644 index 0000000..9401f00 --- /dev/null +++ b/attacker/web-api/config.yml @@ -0,0 +1,4 @@ + +appname: "Email::SpoofingDemo::API::Attacker" +charset: "UTF-8" +serializer: JSON diff --git a/attacker/web-api/cpanfile b/attacker/web-api/cpanfile new file mode 100644 index 0000000..28436b4 --- /dev/null +++ b/attacker/web-api/cpanfile @@ -0,0 +1,11 @@ +requires "Dancer2" => "0.300000"; + +recommends "YAML" => "0"; +recommends "URL::Encode::XS" => "0"; +recommends "CGI::Deurl::XS" => "0"; +recommends "HTTP::Parser::XS" => "0"; + +on "test" => sub { + requires "Test::More" => "0"; + requires "HTTP::Request::Common" => "0"; +}; diff --git a/attacker/web-api/environments/development.yml b/attacker/web-api/environments/development.yml new file mode 100644 index 0000000..fe8dc03 --- /dev/null +++ b/attacker/web-api/environments/development.yml @@ -0,0 +1,15 @@ +# configuration file for development environment + +logger: "console" +log: "core" + +# should Dancer2 consider warnings as critical errors? +warnings: 1 + +# should Dancer2 show a stacktrace when an 5xx error is caught? +# if set to yes, public/500.html will be ignored and either +# views/500.tt, 'error_template' template, or a default error template will be used. +show_errors: 1 + +# print the banner +startup_info: 1 diff --git a/attacker/web-api/environments/production.yml b/attacker/web-api/environments/production.yml new file mode 100644 index 0000000..41b436f --- /dev/null +++ b/attacker/web-api/environments/production.yml @@ -0,0 +1,16 @@ +# configuration file for production environment + +# only log warning and error messsages +log: "warning" + +# log message to a file in logs/ +logger: "file" + +# don't consider warnings critical +warnings: 0 + +# hide errors +show_errors: 0 + +# disable server tokens in production environments +no_server_tokens: 1 diff --git a/attacker/web-api/lib/Email/SpoofingDemo/API/Attacker.pm b/attacker/web-api/lib/Email/SpoofingDemo/API/Attacker.pm new file mode 100644 index 0000000..c89e02c --- /dev/null +++ b/attacker/web-api/lib/Email/SpoofingDemo/API/Attacker.pm @@ -0,0 +1,56 @@ +package Email::SpoofingDemo::API::Attacker; +use Dancer2; + +our $VERSION = '0.1'; + +my $SCRIPT = '/home/attaquant/scripts/send_email.py'; + +sub run_script { + open(my $fh, '-|', $SCRIPT, '--non-interactive', @_) + or die "$SCRIPT: $!"; + + my $json; + { + local $/ = undef; + $json = <$fh>; + } + + close($fh); + + if (($? >> 8) != 0) { + die $json; + } + return from_json($json); +} + +get '/' => sub { return "Welcome"; }; + +get '/config' => sub { + return run_script('--get-config'); +}; + +post '/spoof' => sub { + my $helo = body_parameters->{'helo'}; + my $scenario = body_parameters->{'scenario'}; + + if (not defined $scenario) { + status 400; + return "Need a scenario name"; + } + + my @args = ('--template', $scenario); + if (defined $helo) { + push @args, ('--helo', $helo); + } + if (body_parameters->{'replace_mail_from'}) { + push @args, ('--replace-rfc5321-mail-from'); + } + + return run_script(@args); +}; + +any qr{.*} => sub { status 'not_found'; return "Invalid route" }; + +dance; + +true; diff --git a/attacker/web-api/public/dispatch.cgi b/attacker/web-api/public/dispatch.cgi new file mode 100644 index 0000000..706ba0c --- /dev/null +++ b/attacker/web-api/public/dispatch.cgi @@ -0,0 +1,16 @@ +#!/usr/bin/env perl +BEGIN { $ENV{DANCER_APPHANDLER} = 'PSGI';} +use Dancer2; +use FindBin '$RealBin'; +use Plack::Runner; + +# For some reason Apache SetEnv directives don't propagate +# correctly to the dispatchers, so forcing PSGI and env here +# is safer. +set apphandler => 'PSGI'; +set environment => 'production'; + +my $psgi = path($RealBin, '..', 'bin', 'app.psgi'); +die "Unable to read startup script: $psgi" unless -r $psgi; + +Plack::Runner->run($psgi); diff --git a/attacker/web-api/public/dispatch.fcgi b/attacker/web-api/public/dispatch.fcgi new file mode 100644 index 0000000..ad42deb --- /dev/null +++ b/attacker/web-api/public/dispatch.fcgi @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +BEGIN { $ENV{DANCER_APPHANDLER} = 'PSGI';} +use Dancer2; +use FindBin '$RealBin'; +use Plack::Handler::FCGI; + +# For some reason Apache SetEnv directives don't propagate +# correctly to the dispatchers, so forcing PSGI and env here +# is safer. +set apphandler => 'PSGI'; +set environment => 'production'; + +my $psgi = path($RealBin, '..', 'bin', 'app.psgi'); +my $app = do($psgi); +die "Unable to read startup script: $@" if $@; +my $server = Plack::Handler::FCGI->new(nproc => 5, detach => 1); + +$server->run($app);