diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm index 470677088..65136a269 100644 --- a/IkiWiki/CGI.pm +++ b/IkiWiki/CGI.pm @@ -161,8 +161,18 @@ sub cgi_prefs ($$) { #{{{ my $session=shift; needsignin($q, $session); - decode_cgi_utf8($q); + + # The session id is stored on the form and checked to + # guard against CSRF. + my $sid=$q->param('sid'); + if (! defined $sid) { + $q->delete_all; + } + elsif ($sid ne $session->id) { + error(gettext("Your login session has expired.")); + } + eval q{use CGI::FormBuilder}; error($@) if $@; my $form = CGI::FormBuilder->new( @@ -193,7 +203,10 @@ sub cgi_prefs ($$) { #{{{ buttons => $buttons); }); - $form->field(name => "do", type => "hidden"); + $form->field(name => "do", type => "hidden", value => "prefs", + force => 1); + $form->field(name => "sid", type => "hidden", value => $session->id, + force => 1); $form->field(name => "email", size => 50, fieldset => "preferences"); $form->field(name => "banned_users", size => 50, fieldset => "admin"); @@ -241,11 +254,11 @@ sub cgi_prefs ($$) { #{{{ sub cgi_editpage ($$) { #{{{ my $q=shift; my $session=shift; - - my @fields=qw(do rcsinfo subpage from page type editcontent comments); - my @buttons=("Save Page", "Preview", "Cancel"); decode_cgi_utf8($q); + + my @fields=qw(do rcsinfo subpage from page type editcontent comments); + my @buttons=("Save Page", "Preview", "Cancel"); eval q{use CGI::FormBuilder}; error($@) if $@; my $form = CGI::FormBuilder->new( @@ -316,6 +329,8 @@ sub cgi_editpage ($$) { #{{{ } $form->field(name => "do", type => 'hidden'); + $form->field(name => "sid", type => "hidden", value => $session->id, + force => 1); $form->field(name => "from", type => 'hidden'); $form->field(name => "rcsinfo", type => 'hidden'); $form->field(name => "subpage", type => 'hidden'); @@ -474,6 +489,16 @@ sub cgi_editpage ($$) { #{{{ else { # save page check_canedit($page, $q, $session); + + # The session id is stored on the form and checked to + # guard against CSRF. But only if the user is logged in, + # as anonok can allow anonymous edits. + if (defined $session->param("name")) { + my $sid=$q->param('sid'); + if (! defined $sid || $sid ne $session->id) { + error(gettext("Your login session has expired.")); + } + } my $exists=-e "$config{srcdir}/$file"; diff --git a/debian/changelog b/debian/changelog index 613640f60..9085d97cb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,9 @@ ikiwiki (2.42) UNRELEASED; urgency=low * aggregate: Correct a mistake in the code that dummy up a guid for feeds lacking one. * inline: Correct handling of urls relative to baseurl in feeds. + * Fix CSRF attacks against the preferences and edit forms. The fix involved + embedding the session id in the forms, and not allowing the forms to be + submitted if the embedded id does not match the session id. Closes: #475445 -- Joey Hess Thu, 03 Apr 2008 02:35:39 -0400 diff --git a/doc/security.mdwn b/doc/security.mdwn index 373f64557..29ae7d4b3 100644 --- a/doc/security.mdwn +++ b/doc/security.mdwn @@ -366,3 +366,14 @@ with the release of ikiwiki 2.31.1. (And a few subsequent versions..) A fix was also backported to Debian etch, as version 1.33.4. I recommend upgrading to one of these versions if your wiki can be edited by third parties. + +## Cross Site Request Forging + +Cross Site Request Forging could be used to constuct a link that would +change a logged-in user's password or other preferences if they clicked on +the link. It could also be used to construct a link that would cause a wiki +page to be modified by a logged-in user. + +These holes were discovered on 10 April 2008 and fixed the same day with +the release of ikiwiki 2.42. A fix was also backported to Debian etch, as +version 1.33.4. I recommend upgrading to one of these versions. diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index a3f7cafcb..5e7e4b4d4 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-03-29 21:01-0400\n" +"POT-Creation-Date: 2008-04-10 16:18-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -24,46 +24,50 @@ msgstr "" msgid "login failed, perhaps you need to turn on cookies?" msgstr "" -#: ../IkiWiki/CGI.pm:184 +#: ../IkiWiki/CGI.pm:173 ../IkiWiki/CGI.pm:499 +msgid "Your login session has expired." +msgstr "" + +#: ../IkiWiki/CGI.pm:194 msgid "Login" msgstr "" -#: ../IkiWiki/CGI.pm:185 +#: ../IkiWiki/CGI.pm:195 msgid "Preferences" msgstr "" -#: ../IkiWiki/CGI.pm:186 +#: ../IkiWiki/CGI.pm:196 msgid "Admin" msgstr "" -#: ../IkiWiki/CGI.pm:235 +#: ../IkiWiki/CGI.pm:248 msgid "Preferences saved." msgstr "" -#: ../IkiWiki/CGI.pm:293 +#: ../IkiWiki/CGI.pm:306 #, perl-format msgid "%s is not an editable page" msgstr "" -#: ../IkiWiki/CGI.pm:395 ../IkiWiki/Plugin/brokenlinks.pm:24 +#: ../IkiWiki/CGI.pm:410 ../IkiWiki/Plugin/brokenlinks.pm:24 #: ../IkiWiki/Plugin/inline.pm:265 ../IkiWiki/Plugin/opendiscussion.pm:17 #: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95 #: ../IkiWiki/Render.pm:172 msgid "discussion" msgstr "" -#: ../IkiWiki/CGI.pm:451 +#: ../IkiWiki/CGI.pm:466 #, perl-format msgid "creating %s" msgstr "" -#: ../IkiWiki/CGI.pm:469 ../IkiWiki/CGI.pm:487 ../IkiWiki/CGI.pm:497 -#: ../IkiWiki/CGI.pm:531 ../IkiWiki/CGI.pm:576 +#: ../IkiWiki/CGI.pm:484 ../IkiWiki/CGI.pm:512 ../IkiWiki/CGI.pm:522 +#: ../IkiWiki/CGI.pm:556 ../IkiWiki/CGI.pm:601 #, perl-format msgid "editing %s" msgstr "" -#: ../IkiWiki/CGI.pm:666 +#: ../IkiWiki/CGI.pm:691 msgid "You are banned." msgstr "" @@ -222,7 +226,7 @@ msgstr "" msgid "Discussion" msgstr "" -#: ../IkiWiki/Plugin/inline.pm:491 +#: ../IkiWiki/Plugin/inline.pm:500 msgid "RPC::XML::Client not found, not pinging" msgstr "" diff --git a/templates/editpage.tmpl b/templates/editpage.tmpl index cf4950ead..b0bb0ecb9 100644 --- a/templates/editpage.tmpl +++ b/templates/editpage.tmpl @@ -41,6 +41,7 @@ together before saving. +