cgi-dev

Repository that serves as my CGI "scratchpad" to try things out.
git clone git://git.samirparikh.com/cgi-dev
Log | Files | Refs | README

commit 73d50ec8871b9cfbb95b75338ae590d78bd91db7
parent 0327f3d8693661fc15a259ec2995dc75d6714069
Author: Samir Parikh <noreply@samirparikh.com>
Date:   Fri, 25 Feb 2022 21:50:43 +0000

add message authentication check to cookie

Diffstat:
Mhangman3.cgi | 30+++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/hangman3.cgi b/hangman3.cgi @@ -6,12 +6,14 @@ use IO::File(); use CGI qw( :standard ); use CGI::Cookie (); +use MD5 (); use warnings; use strict; use constant WORDS => '/usr/share/dict/hangman_words'; use constant TRIES => 6; -use constant COOKIE_NAME => 'Hangman'; +use constant COOKIE_NAME => 'Hangman3'; +use constant SECRET => 'kiddo'; # retrieve the state #my $state = get_state(); # $state is a hash reference @@ -72,6 +74,7 @@ sub initialize { sub save_state { my $state = shift; + MAC($state, 'generate'); return CGI::Cookie->new ( -name => COOKIE_NAME, -value => $state, @@ -91,6 +94,7 @@ sub save_state { sub get_state { my %cookie = cookie( COOKIE_NAME ); return undef unless %cookie; + authentication_error() unless MAC(\%cookie, 'check'); return \%cookie; } @@ -207,3 +211,27 @@ sub pick_random_word { chomp $word; $word; } + +sub MAC { + my ($state, $action) = @_; + return unless ref( $state ); + my @fields = @{$state}{qw(WORD GUESSES_LEFT GUESSED GAMENO WON TOTAL)}; + my $newmac = MD5->hexhash( + SECRET . MD5->hexhash( join '', SECRET, @fields ) + ); + return $state->{MAC} = $newmac if $action eq 'generate'; + return $newmac eq $state->{MAC} if $action eq 'check'; + return undef; +} + +sub authentication_error { + my $cookie = CGI::Cookie->new(-name => COOKIE_NAME, -value=>'',-expires => '-1d'); + print header(-cookie => $cookie), + start_html(-title => 'Authentication Error'), + h1(font({-color => 'red'}, 'Authentication Error')), + p('This application was unable to confirm the integrity of the', + 'cookie that holds your current score.', + 'Please reload the page to start a fresh session.'), + p('If the problem persists, contact the webmaster.'); + exit 0; +}