Changeset 2755 in subversion


Ignore:
Timestamp:
Jul 15, 2009 5:49:35 AM (4 years ago)
Author:
thomasb
Message:

Use request tokens to protect POST requests from CSFR

Location:
trunk/roundcubemail/program
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/roundcubemail/program/include/rcmail.php

    r2747 r2755  
    853853   
    854854  /** 
     855   * Generate a unique token to be used in a form request 
     856   * 
     857   * @param string Request identifier 
     858   * @return string The request token 
     859   */ 
     860  public function get_request_token($key) 
     861  { 
     862    if (!$this->request_tokens[$key]) 
     863      $_SESSION['request_tokens'][$key] = $this->request_tokens[$key] = md5(uniqid($key . rand(), true)); 
     864     
     865    return $this->request_tokens[$key]; 
     866  } 
     867   
     868   
     869  /** 
     870   * Check if the current request contains a valid token 
     871   * 
     872   * @param string Request identifier 
     873   * @return boolean True if request token is valid false if not 
     874   */ 
     875  public function check_request($key, $mode = RCUBE_INPUT_POST) 
     876  { 
     877    $token = get_input_value('_token', $mode); 
     878    $valid = !(empty($token) || $_SESSION['request_tokens'][$key] != $token); 
     879     
     880    if ($valid) 
     881      unset($_SESSION['request_tokens'][$key]); 
     882     
     883    return $valid; 
     884  } 
     885   
     886   
     887  /** 
    855888   * Create unique authorization hash 
    856889   * 
  • trunk/roundcubemail/program/include/rcube_template.php

    r2743 r2755  
    926926    public function form_tag($attrib, $content = null) 
    927927    { 
    928       if ($this->framed) { 
     928      if ($this->framed || !empty($_REQUEST['_framed'])) { 
    929929        $hiddenfield = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); 
    930930        $hidden = $hiddenfield->show(); 
     
    936936      return html::tag('form', 
    937937        $attrib + array('action' => "./", 'method' => "get"), 
    938         $hidden . $content); 
     938        $hidden . $content, 
     939        array('id','class','style','name','method','action','enctype','onsubmit')); 
     940    } 
     941     
     942     
     943    /** 
     944     * Build a form tag with a unique request token 
     945     * 
     946     * @param array Named tag parameters including 'action' and 'task' values which will be put into hidden fields 
     947     * @param string Form content 
     948     * @return string HTML code for the form 
     949     */ 
     950    public function request_form($attrib, $content) 
     951    { 
     952        $hidden = new html_hiddenfield(); 
     953        if ($attrib['task']) { 
     954            $hidden->add(array('name' => '_task', 'value' => $attrib['task'])); 
     955        } 
     956        if ($attrib['action']) { 
     957            $hidden->add(array('name' => '_action', 'value' => $attrib['action'])); 
     958        } 
     959       
     960        // generate request token 
     961        $request_key = $attrib['request'] ? $attrib['request'] : $attrib['action']; 
     962        $hidden->add(array('name' => '_token', 'value' => $this->app->get_request_token($request_key))); 
     963       
     964        unset($attrib['task'], $attrib['request']); 
     965        $attrib['action'] = './'; 
     966       
     967        // we already have a <form> tag 
     968        if ($attrib['form']) 
     969            return $hidden->show() . $content; 
     970        else 
     971            return $this->form_tag($attrib, $hidden->show() . $content); 
    939972    } 
    940973 
  • trunk/roundcubemail/program/localization/de_CH/messages.inc

    r2716 r2755  
    2323$messages['sessionerror'] = 'Ihre Session ist ungÃŒltig oder abgelaufen'; 
    2424$messages['imaperror'] = 'Keine Verbindung zum IMAP Server'; 
     25$messages['servererror'] = 'Serverfehler!'; 
     26$messages['invalidrequest'] = 'UngÃŒltige Anfrage! Es wurden keine Daten gespeichert.'; 
    2527$messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner'; 
    2628$messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!'; 
     
    4648$messages['errormoving'] = 'Nachricht konnte nicht verschoben werden'; 
    4749$messages['errordeleting'] = 'Nachricht konnte nicht gelöscht werden'; 
     50$messages['errormarking'] = 'Nachricht konnte nicht markiert werden'; 
    4851$messages['deletecontactconfirm'] = 'Wollen Sie die ausgewÀhlten Kontakte wirklich löschen'; 
    4952$messages['deletemessagesconfirm'] = 'Wollen Sie die ausgewÀhlten Nachrichten wirklich löschen?'; 
  • trunk/roundcubemail/program/localization/de_DE/messages.inc

    r2716 r2755  
    2424$messages['imaperror'] = 'Keine Verbindung zum IMAP-Server'; 
    2525$messages['servererror'] = 'Serverfehler!'; 
     26$messages['invalidrequest'] = 'UngÃŒltige Anfrage! Es wurden keine Daten gespeichert.'; 
    2627$messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner'; 
    2728$messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!'; 
  • trunk/roundcubemail/program/localization/en_US/messages.inc

    r2713 r2755  
    2424$messages['imaperror'] = 'Connection to IMAP server failed'; 
    2525$messages['servererror'] = 'Server Error!'; 
     26$messages['invalidrequest'] = 'Invalid request! No data was saved.'; 
    2627$messages['nomessagesfound'] = 'No messages found in this mailbox'; 
    2728$messages['loggedout'] = 'You have successfully terminated the session. Good bye!'; 
  • trunk/roundcubemail/program/steps/addressbook/edit.inc

    r1939 r2755  
    8282// similar function as in /steps/settings/edit_identity.inc 
    8383function get_form_tags($attrib) 
    84   { 
     84{ 
    8585  global $CONTACTS, $EDIT_FORM, $RCMAIL; 
    8686 
    87   $result = $CONTACTS->get_result(); 
    88   $form_start = ''; 
    89   if (!strlen($EDIT_FORM)) 
    90     { 
    91     $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); 
    92     $hiddenfields->add(array('name' => '_action', 'value' => 'save')); 
    93     $hiddenfields->add(array('name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); 
    94     $hiddenfields->add(array('name' => '_framed', 'value' => (empty($_REQUEST['_framed']) ? 0 : 1))); 
     87  $form_start = $form_end = ''; 
     88   
     89  if (empty($EDIT_FORM)) { 
     90    $hiddenfields = new html_hiddenfield(array('name' => '_source', 'value' => get_input_value('_source', RCUBE_INPUT_GPC))); 
    9591     
    9692    if (($result = $CONTACTS->get_result()) && ($record = $result->first())) 
    9793      $hiddenfields->add(array('name' => '_cid', 'value' => $record['ID'])); 
    9894     
    99     $form_start = !strlen($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; 
    100     $form_start .= $hiddenfields->show(); 
    101     } 
    102      
    103   $form_end = (strlen($EDIT_FORM) && !strlen($attrib['form'])) ? '</form>' : ''; 
    104   $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; 
    105    
    106   if (!strlen($EDIT_FORM)) 
    107     $RCMAIL->output->add_gui_object('editform', $form_name); 
    108    
    109   $EDIT_FORM = $form_name; 
     95    $form_start = $RCMAIL->output->request_form(array('name' => "form", 'method' => "post", 'task' => $RCMAIL->task, 'action' => 'save', 'request' => 'save.'.intval($record['ID']), 'noclose' => true) + $attrib, $hiddenfields->show()); 
     96    $form_end = !strlen($attrib['form']) ? '</form>' : ''; 
     97 
     98    $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; 
     99    $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); 
     100  } 
    110101 
    111102  return array($form_start, $form_end);  
    112   } 
     103} 
    113104 
    114105 
  • trunk/roundcubemail/program/steps/addressbook/save.inc

    r2441 r2755  
    2020*/ 
    2121 
     22$cid = get_input_value('_cid', RCUBE_INPUT_POST); 
     23$return_action = empty($cid) ? 'add' : 'show'; 
     24 
     25// check request token and exit if invalid 
     26if (!$RCMAIL->check_request('save.'.intval($cid), RCUBE_INPUT_POST)) 
     27{ 
     28  $OUTPUT->show_message('invalidrequest', 'error'); 
     29  rcmail_overwrite_action($return_action); 
     30  return; 
     31} 
     32 
    2233// cannot edit record 
    2334if ($CONTACTS->readonly) 
    2435{ 
    2536  $OUTPUT->show_message('contactreadonly', 'error'); 
    26   rcmail_overwrite_action(empty($_POST['_cid']) ? 'add' : 'show'); 
     37  rcmail_overwrite_action($return_action); 
    2738  return; 
    2839} 
     
    3243{ 
    3344  $OUTPUT->show_message('formincomplete', 'warning'); 
    34   rcmail_overwrite_action(empty($_POST['_cid']) ? 'add' : 'show'); 
     45  rcmail_overwrite_action($return_action); 
    3546  return; 
    3647} 
     
    4051$a_save_cols = array('name', 'firstname', 'surname', 'email'); 
    4152$a_record = array(); 
    42 $cid = get_input_value('_cid', RCUBE_INPUT_POST); 
    4353 
    4454// read POST values into hash array 
  • trunk/roundcubemail/program/steps/settings/edit_identity.inc

    r2383 r2755  
    6161  $t_cols = !empty($attrib['textareacols']) ? $attrib['textareacols'] : 40; 
    6262 
    63   list($form_start, $form_end) = get_form_tags($attrib, 'save-identity', array('name' => '_iid', 'value' => $IDENTITY_RECORD['identity_id'])); 
     63  list($form_start, $form_end) = get_form_tags($attrib, 'save-identity', intval($IDENTITY_RECORD['identity_id']), array('name' => '_iid', 'value' => $IDENTITY_RECORD['identity_id'])); 
    6464  unset($attrib['form']); 
    6565 
  • trunk/roundcubemail/program/steps/settings/func.inc

    r2702 r2755  
    432432 
    433433// similar function as in /steps/addressbook/edit.inc 
    434 function get_form_tags($attrib, $action, $add_hidden=array()) 
     434function get_form_tags($attrib, $action, $id = null, $hidden = null) 
    435435  { 
    436436  global $EDIT_FORM, $RCMAIL; 
    437437 
    438   $form_start = ''; 
    439   if (!strlen($EDIT_FORM)) 
    440     { 
    441     $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); 
    442     $hiddenfields->add(array('name' => '_action', 'value' => $action)); 
     438  $form_start = $form_end = ''; 
     439   
     440  if (empty($EDIT_FORM)) { 
     441    $request_key = $action . (isset($id) ? '.'.$id : ''); 
     442    $form_start = $RCMAIL->output->request_form(array('name' => "form", 'method' => "post", 'task' => $RCMAIL->task, 'action' => $action, 'request' => $request_key, 'noclose' => true) + $attrib); 
    443443     
    444     if ($add_hidden) 
    445       $hiddenfields->add($add_hidden); 
     444    if (is_array($hidden)) { 
     445      $hiddenfields = new html_hiddenfield($hidden); 
     446      $form_start .= $hiddenfields->show(); 
     447    } 
    446448     
    447     $form_start = !strlen($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; 
    448     $form_start .= $hiddenfields->show(); 
    449     } 
    450      
    451   $form_end = (!strlen($EDIT_FORM) && !strlen($attrib['form'])) ? '</form>' : ''; 
    452   $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; 
    453  
    454   if (!strlen($EDIT_FORM)) 
    455     $RCMAIL->output->add_gui_object('editform', $form_name); 
    456    
    457   $EDIT_FORM = $form_name; 
     449    $form_end = !strlen($attrib['form']) ? '</form>' : ''; 
     450 
     451    $EDIT_FORM = !empty($attrib['form']) ? $attrib['form'] : 'form'; 
     452    $RCMAIL->output->add_gui_object('editform', $EDIT_FORM); 
     453  } 
    458454 
    459455  return array($form_start, $form_end); 
  • trunk/roundcubemail/program/steps/settings/save_identity.inc

    r2481 r2755  
    2727$updated = $default_id = false; 
    2828 
     29// check request token 
     30if (!$RCMAIL->check_request('save-identity.'.intval(get_input_value('_iid', RCUBE_INPUT_POST)), RCUBE_INPUT_POST)) { 
     31  $OUTPUT->show_message('invalidrequest', 'error'); 
     32  rcmail_overwrite_action('identities'); 
     33  return; 
     34} 
    2935// check input 
    3036if (empty($_POST['_name']) || (empty($_POST['_email']) && IDENTITIES_LEVEL != 1 && IDENTITIES_LEVEL != 3)) 
  • trunk/roundcubemail/program/steps/settings/save_prefs.inc

    r2401 r2755  
    1919 
    2020*/ 
     21 
     22// check request token and exit if invalid 
     23if (!$RCMAIL->check_request('save-prefs', RCUBE_INPUT_POST)) { 
     24  $OUTPUT->show_message('invalidrequest', 'error'); 
     25  rcmail_overwrite_action('preferences'); 
     26  return; 
     27} 
    2128 
    2229$a_user_prefs = array( 
Note: See TracChangeset for help on using the changeset viewer.