Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bestpractical/rt.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsunnavy <sunnavy@bestpractical.com>2022-07-15 00:09:52 +0300
committersunnavy <sunnavy@bestpractical.com>2022-07-15 06:48:11 +0300
commit920c4f5286851358fd9b4ada24d3ddae8a6a0215 (patch)
treed76dccdd305d4f4b527002c3a9cc9c60c0d9ef4f
parentcca8fb65629b9104b72bd32399a01201af7fe1c7 (diff)
Add security tests for vulnerabilities released between 2014 and 20214.4/security-tests-2021
This includes tests for: CVE-2014-9472: mailgate dos CVE-2021-38562: side channel attack
-rw-r--r--t/security/CVE-2014-9472-decode-dos.t45
-rw-r--r--t/security/CVE-2021-38562-timing-side-channel.t56
2 files changed, 101 insertions, 0 deletions
diff --git a/t/security/CVE-2014-9472-decode-dos.t b/t/security/CVE-2014-9472-decode-dos.t
new file mode 100644
index 0000000000..8bdce7d8bb
--- /dev/null
+++ b/t/security/CVE-2014-9472-decode-dos.t
@@ -0,0 +1,45 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+plan skip_all => "Requires perl >= 5.14.0 to generate the warnings"
+ if $] lt '5.014';
+
+my $mail = <<'EOF';
+From: root@localhost
+To: rt@localhost
+Subject: Testing
+Content-Type: text/plain; charset="utf-32LE"
+Content-Transfer-Encoding: base64
+
+EOF
+$mail .= (("F" x 76)."\r\n") x 100;
+
+# We do this via callback on the logger because it is otherwise hard to
+# know what got skipped by our $SIG{__WARN__}
+my @warnings;
+
+# Stop warnings from going to STDERR; even when passing, we expect this
+# to generate warnings.
+ok $RT::Logger->remove( 'rttest' );
+
+$RT::Logger->add_callback(
+ sub {
+ my (%args) = @_;
+ push @warnings, $args{message} if $args{level} eq "warning";
+ return $args{message};
+ }
+);
+
+my ($status, $id) = RT::Test->send_via_mailgate(
+ $mail,
+ queue => "general"
+);
+
+ok @warnings < 20, "There are up to a small number or warnings; got @{[@warnings+0]}";
+
+# Clear our the warnings to make Test::NoWarnings happy. We know we
+# generated some.
+Test::NoWarnings->clear_warnings;
+
+done_testing;
diff --git a/t/security/CVE-2021-38562-timing-side-channel.t b/t/security/CVE-2021-38562-timing-side-channel.t
new file mode 100644
index 0000000000..d0c63a81ec
--- /dev/null
+++ b/t/security/CVE-2021-38562-timing-side-channel.t
@@ -0,0 +1,56 @@
+use strict;
+use warnings;
+
+use RT::Test;
+use Time::HiRes qw(tv_interval gettimeofday);
+
+my ( $baseurl, $m ) = RT::Test->started_ok;
+
+my $existing_user = 'root';
+my $nonexistent_user = 'quux-cabbage';
+my $disabled_user = 'disabled';
+
+my $d = RT::Test->load_or_create_user(Name => 'disabled');
+$d->SetDisabled(1);
+$d->SetPassword('testing123ok');
+sub login
+{
+ my ($user) = @_;
+ my $t0 = [gettimeofday()];
+
+ $m->get($baseurl);
+ $m->submit_form(
+ form_id => 'login',
+ fields => {
+ user => $user,
+ pass => 'testing123ok',
+ }
+ );
+ $m->warning_like(qr/FAILED LOGIN for $user from/, 'Got expected warning');
+ return tv_interval($t0);
+}
+
+my $t_existing = 0.0;
+my $t_nonexisting = 0.0;
+my $t_disabled = 0.0;
+
+for (my $i=0; $i<20; $i++) {
+ $t_existing += login($existing_user);
+}
+for (my $i=0; $i<20; $i++) {
+ $t_nonexisting += login($nonexistent_user);
+}
+for (my $i=0; $i<20; $i++) {
+ $t_disabled += login($disabled_user);
+}
+
+# The difference is usually within 5%, but github actions are so slow that it
+# could even be 15%, here checking 20% instead to make github actions happy.
+ok ($t_existing >= 0.8 * $t_nonexisting && $t_nonexisting >= 0.8 * $t_existing,
+ "Login timings for existing and nonexisting users are within 20%($t_existing and $t_nonexisting)");
+ok ($t_existing >= 0.8 * $t_disabled && $t_disabled >= 0.8 * $t_existing,
+ "Login timings for existing and disabled users are within 20%($t_existing and $t_disabled)");
+ok ($t_nonexisting >= 0.8 * $t_disabled && $t_disabled >= 0.8 * $t_nonexisting,
+ "Login timings for nonexisting and disabled users are within 20%($t_nonexisting and $t_disabled)");
+
+done_testing();