From 1e8d26baecad6ca1088ea7815fe2615fb520a10e Mon Sep 17 00:00:00 2001 From: zach Date: Mon, 10 Nov 2008 21:23:30 -0500 Subject: [PATCH] CSRF Protection for login and new notice. Ticket #503 darcs-hash:20081111022330-462f3-810b2a86e6e209330ade628fc0e97df96151d496.gz --- actions/login.php | 10 +++++++++- actions/newnotice.php | 25 ++++++++++++++++--------- actions/noticesearch.php | 2 ++ lib/util.php | 3 ++- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/actions/login.php b/actions/login.php index f183c1cd45..ccec9cf8a7 100644 --- a/actions/login.php +++ b/actions/login.php @@ -37,8 +37,15 @@ class LoginAction extends Action { } function check_login() { - # XXX: form token in $_SESSION to prevent XSS # XXX: login throttle + + # CSRF protection - token set in common_notice_form() + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->client_error(_('There was a problem with your session token. Try again, please.')); + return; + } + $nickname = common_canonical_nickname($this->trimmed('nickname')); $password = $this->arg('password'); if (common_check_user($nickname, $password)) { @@ -104,6 +111,7 @@ class LoginAction extends Action { _('Automatically login in the future; ' . 'not for shared computers!')); common_submit('submit', _('Login')); + common_hidden('token', common_session_token()); common_element_end('form'); common_element_start('p'); common_element('a', array('href' => common_local_url('recoverpassword')), diff --git a/actions/newnotice.php b/actions/newnotice.php index b5fc98c37c..37cca982d6 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -20,7 +20,7 @@ if (!defined('LACONICA')) { exit(1); } class NewnoticeAction extends Action { - + function handle($args) { parent::handle($args); # XXX: Ajax! @@ -36,10 +36,17 @@ class NewnoticeAction extends Action { function save_new_notice() { + # CSRF protection - token set in common_notice_form() + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->client_error(_('There was a problem with your session token. Try again, please.')); + return; + } + $user = common_current_user(); assert($user); # XXX: maybe an error instead... $content = $this->trimmed('status_textarea'); - + if (!$content) { $this->show_form(_('No content!')); return; @@ -51,9 +58,9 @@ class NewnoticeAction extends Action { } $inter = new CommandInterpreter(); - + $cmd = $inter->handle_command($user, $content); - + if ($cmd) { $cmd->execute(new WebChannel()); return; @@ -62,18 +69,18 @@ class NewnoticeAction extends Action { $replyto = $this->trimmed('inreplyto'); common_debug("Replyto = $replyto\n"); - + $notice = Notice::saveNew($user->id, $content, 'web', 1, ($replyto == 'false') ? NULL : $replyto); - + if (is_string($notice)) { $this->show_form($notice); return; } - + common_broadcast_notice($notice); - + $returnto = $this->trimmed('returnto'); - + if ($returnto) { $url = common_local_url($returnto, array('nickname' => $user->nickname)); diff --git a/actions/noticesearch.php b/actions/noticesearch.php index e6de21ae06..bc052d512f 100644 --- a/actions/noticesearch.php +++ b/actions/noticesearch.php @@ -142,6 +142,8 @@ class NoticesearchAction extends SearchAction { 'onclick' => 'doreply("'.$profile->nickname.'"); return false', 'title' => _('reply'), 'class' => 'replybutton')); + common_hidden('posttoken', common_session_token()); + common_raw('→'); common_element_end('a'); common_element_end('p'); diff --git a/lib/util.php b/lib/util.php index 6ec557b2f9..a5eeab0566 100644 --- a/lib/util.php +++ b/lib/util.php @@ -1353,12 +1353,13 @@ function common_notice_form($action=NULL, $content=NULL) { common_element('label', array('for' => 'status_textarea', 'id' => 'status_label'), sprintf(_('What\'s up, %s?'), $user->nickname)); - common_element('span', array('id' => 'counter', 'class' => 'counter'), '140'); + common_element('span', array('id' => 'counter', 'class' => 'counter'), '140'); common_element('textarea', array('id' => 'status_textarea', 'cols' => 60, 'rows' => 3, 'name' => 'status_textarea'), ($content) ? $content : ''); + common_hidden('token', common_session_token()); if ($action) { common_hidden('returnto', $action); }