Compléter la console (sauf pour l’attaquant)

La console est quasiment prête : il ne reste plus qu’à faire le côté de
l’attaquant.
This commit is contained in:
Marc van der Wal 2023-10-25 15:50:30 +02:00
parent 23409b4d6f
commit 662f0668a3
7 changed files with 202 additions and 24 deletions

View File

@ -9,11 +9,13 @@ template: "template_toolkit"
# Specify the addresses of the API endpoints for the other components of the # Specify the addresses of the API endpoints for the other components of the
# system # system
api: api:
dns: "ns.example:3000" dns: "172.31.0.53:3000"
sender: "172.31.10.1:3000"
recipient: "172.31.20.1:3000"
attacker: "172.31.30.1:3000"
# Lists the DNS zones that can be edited by the user # Lists the DNS zones that can be edited by the user
editable_zones: editable_zones:
- example
- expediteur.example - expediteur.example
- destinataire.example - destinataire.example
- attaquant.example - attaquant.example

View File

@ -50,11 +50,8 @@ get '/dns/zone-edit/:zone' => sub {
my $zone_contents; my $zone_contents;
if (defined $zone) { if (defined $zone) {
my $client = REST::Client->new(); my ($response, $status) = call_api(GET => 'dns', "/zone/${zone}/file");
$client->setHost(config->{'api'}{'dns'}); $zone_contents = $response->{contents};
$client->GET("/zone/${zone}/file");
my $response = from_json($client->responseContent());
$zone_contents = $response->{'contents'};
} }
template 'dns/zone-edit' => { template 'dns/zone-edit' => {
@ -71,25 +68,75 @@ post '/dns/zone-edit/:zone' => sub {
} }
my $contents = body_parameters->{'zone-contents'}; my $contents = body_parameters->{'zone-contents'};
my (undef, $status) = call_api(PUT => 'dns', "/zone/${zone}/file", { contents => $contents });
my $client = REST::Client->new(); my $success = ($status eq '200') ? 'success' : 'failure';
$client->setHost(config->{'api'}{'dns'});
$client->PUT("/zone/${zone}/file",
encode_json({ contents => $contents }),
{
"Content-Type" => "application/json",
"Accept" => "application/json"
});
my $success;
if ($client->responseCode() eq '200') {
$success = 'success';
} else {
warn "Got " . $client->responseCode() . " from upstream: " . $client->responseContent();
$success = 'failure'
}
redirect "/dns/zone-edit/$zone?success=$success", 303; redirect "/dns/zone-edit/$zone?success=$success", 303;
};
get '/sender/dkim-keys' => sub {
my ($installed_keys, $status) = call_api(GET => 'sender', '/installed-keys');
($status eq '200') or die "API returned $status";
template 'sender/dkim-keys' => {
active_role => 'sender',
title => 'Gestion des clefs DKIM',
installed_keys => $installed_keys,
};
};
get '/dkim-generator/sender' => sub {
template 'dkim-generator/sender' => {
title => 'Générateur de clefs DKIM'
};
};
post '/dkim-generator/sender' => sub {
my $api_params = {
domain => body_parameters->get('domain'),
selector => body_parameters->get('selector'),
key_size => body_parameters->get('key-size')
};
my ($response, $status) = call_api(POST => 'sender', '/generate-dkim-key', $api_params);
($status eq 200) or die "API returned $status";
template 'dkim-generator/sender' => {
title => 'Générateur de clefs DKIM',
txt_record => $response->{'txt_record'}
};
};
get '/attacker/spoof' => sub {
template 'attacker/spoof' => {
title => 'Usurpateur didentité de courriel'
};
};
get '/sender/send-email' => sub {
my %template_params = (
title => 'Envoi de messages légitimes',
email_data => [
{
what => 'Confirmation de commande',
from => 'support@expediteur.example',
url => 'confirmation_email'
},
{
what => 'Newsletter',
from => 'info@newsletter.expediteur.example',
url => 'newsletter'
}
]
);
my $success = query_parameters->get('success');
if (defined $success) {
$template_params{success} = ($success eq 'success') ? 'success' : 'failure';
}
template 'sender/send-email' => \%template_params;
};
get '/recipient/settings' => sub { get '/recipient/settings' => sub {
my ($system_status, $http_code) = call_api(GET => 'recipient', '/status'); my ($system_status, $http_code) = call_api(GET => 'recipient', '/status');
die if $http_code ne '200'; die if $http_code ne '200';
@ -110,6 +157,13 @@ post '/recipient/settings' => sub {
redirect "/recipient/settings?success=$success", 303; redirect "/recipient/settings?success=$success", 303;
}; };
get '/sender/send-email/:email' => sub {
my $email = route_parameters->get('email');
my (undef, $response) = call_api(POST => 'sender', "/send-email/${email}");
my $success = ($response =~ /^2\d\d$/) ? 'success' : 'failure';
redirect "/sender/send-email?success=$success", 303;
}; };
get '/recipient/webmail' => sub { get '/recipient/webmail' => sub {

View File

@ -1,2 +1,4 @@
<div class="container">
<h1>Erreur 404</h1> <h1>Erreur 404</h1>
<h2>Page non trouvée</h2> <h2>Page non trouvée</h2>
</div>

View File

@ -0,0 +1 @@
TODO

View File

@ -0,0 +1,50 @@
<div class="container">
<div class="row">
<div class="col-12">
<h1>Génération de clef DKIM</h1>
<form method="POST" class="mb-3">
<div class="mb-3">
<label for="domain" class="form-label">Domaine</label>
<input type="text" name="domain" class="form-control" value="expediteur.example" />
</div>
<div class="mb-3">
<label for="selector" class="form-label">Sélecteur</label>
<input type="text" name="selector" class="form-control" value="default" />
</div>
<div class="mb-3">
<label for="key-size" class="form-label">Taille de la clef</label>
<select class="form-select" id="key-size" name="key-size">
<option value="1024">1024 bits</option>
<option value="2048" selected>2048 bits</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Générer</button>
</form>
[% IF txt_record %]
<div class="alert alert-success">
<p>Clef générée.</p>
<p>Publiez ensuite la clef publique dans la <a href="[% request.uri_base %]/dns/zone-edit/expediteur.example">zone DNS</a>:</p>
<div class="card text-bg-success">
<div class="card-header text-end">
<button id="copy-button" class="btn btn-light" onClick="copyTxtRR()">Copier</button>
</div>
<div class="card-body">
<pre class="card-text"><code id="txt-record">[% txt_record | html %]</code></pre>
</div>
</div>
</div>
[% END %]
</div>
</div>
</div>
<script type="text/javascript">
function copyTxtRR() {
navigator.clipboard.writeText($("#txt-record").text());
$("#copy-button").text("Texte copié");
}
</script>

View File

@ -0,0 +1,41 @@
<div class="container">
<div class="row">
<h1>Liste des clefs DKIM installées sur le système</h1>
[% FOR installed_keys %]
<div class="col-sm-12 col-md-6 col-lg-4 col-xl-3">
<div class="card">
<h5 class="card-header">[% domain | html %]</h5>
<ul class="list-group list-group-flush">
<li class="list-group-item">
Sélecteur actuel :
[% IF current_key %][% current_key | html %][% ELSE %](aucun)[% END %]
</li>
<li class="list-group-item">
Sélecteurs disponibles :
<ul>
[% FOR selector IN available_keys -%]
<li>
[%- IF selector == current_key -%]
<strong>[% selector | html %]</strong>
[%- ELSE -%]
[% selector | html %]
[%- END -%]
</li>
[% END %]
</ul>
</li>
</ul>
</div>
</div>
[% END %]
[% UNLESS installed_keys.size %]
<p>
Aucune clef DKIM nest active sur le système. Commencez par <a href="[% request.uri_base %]/dkim-generator/sender">en générer une</a>.
</p>
[% END %]
</div>
</div>

View File

@ -0,0 +1,28 @@
<div class="container">
[% IF success == 'success' %]
<div class="alert alert-success">
<p>Le courriel a bien été envoyé.</p>
<a class="btn btn-outline-success" href="[% request.uri_base %]/recipient/webmail">Relever les courriels du destinataire</a>
</div>
[% ELSIF success == 'failure' %]
<div class="alert alert-danger">
Une erreur est survenue lors de lenvoi du courriel.
</div>
[% END %]
<h1>Système de-mailing</h1>
<div class="row mt-3">
[% FOR email_data %]
<div class="col-sm-12 col-md-12 col-lg-6 col-xl-4 mb-3">
<div class="card">
<h5 class="card-header">[% what | html %]</h5>
<div class="card-body">
<p class="card-text">
Expéditeur: [% from | html %]
</p>
<a href="[% request.uri_base %]/sender/send-email/[% url | html %]" class="btn btn-secondary">Envoyer</a>
</div>
</div>
</div>
[% END %]
</div>
</div>