Fix for Xss injector

  1. function page_xss_injector() {
  2.     for($i=0;$i<2;$i++) {
  3.       // Extract the forms url and id
  4.       $form_details = db_fetch_array(db_query("SELECT f.id,l.path FROM {crawler_forms} f INNER JOIN {crawler_links} l ON f.page_id = l.id WHERE status = 2 LIMIT 1"));
  5.       // Visit that url
  6.       $obj = new drupal_security_scanner_test();
  7.       $session_cookie = variable_get('security_scanner_cookie','');
  8.       $obj->curl_options = array(
  9.         CURLOPT_COOKIE => $session_cookie,
  10.       );
  11.       //$obj->drupalGet($form_details['path']);
  12.       $html = $obj->drupalGet('http://localhost/soc2008/?q=node/add/page');
  13.       $obj->parse();
  14.       // Selecting only textareas and input type = 'text' before seeding
  15.       // (already included inside handleFormModified, but repeated to build the array of the value to seed)
  16.       $all_inputs = $obj->elements->xpath("//input[@type='text']|//textarea");
  17.       //echo "<pre>".print_r($all_inputs,1)."</pre>";
  18.       foreach ($all_inputs as $input) {
  19.         $name = (string)$input->attributes()->name;
  20.         $edit[$name] = "<\script\>alert('xss');</\script\>";
  21.       }
  22.       echo "<pre>".print_r($edit,1)."</pre>";
  23.       // $obj->drupalPostModified($html, $form_details['id'], $form_state, TRUE);
  24.       $obj->drupalPostModified($html, 'edit-page-node-form', $edit, TRUE);
  25.       die;
  26.     }
  27.  
  28.  
  29.  
  30. // Function drupalPostModified and handleFormModified (I have to change its name)
  31.  
  32.   /**
  33.    * Execute a POST request on a Drupal page. (modified function)
  34.    * It will be done as usual POST request with SimpleBrowser.
  35.    *
  36.    * @param string  $path
  37.    *   Location of the post form. Either a Drupal path or an absolute path or
  38.    *   NULL to post to the current page.
  39.    * @param array $edit
  40.    *   Field data in an assocative array. Changes the current input fields
  41.    *   (where possible) to the values indicated. A checkbox can be set to
  42.    *   TRUE to be checked and FALSE to be unchecked.
  43.    * @param string $submit
  44.    *   Value of the submit button.
  45.    * @param $tamper
  46.    *   If this is set to TRUE then you can post anything, otherwise hidden and
  47.    *   nonexistent fields are not posted.
  48.    */
  49.   function drupalPostModified($html, $form_id, $edit, $submit) {
  50.     $submit_matches = FALSE;
  51.     if ($this->parse()) {
  52.       $edit_save = $edit;
  53.       // Let's iterate over all the forms.
  54.       $forms = $this->elements->xpath("//input[@id='".$form_id."']/parent::*");
  55.       foreach ($forms as $form) {
  56.         // We try to set the fields of this form as specified in $edit.
  57.         $edit = $edit_save;
  58.         $post = array();
  59.         $upload = array();
  60.         $submit_matches = $this->handleFormModified($post, $edit, $upload, $submit, $form);
  61.         $action = isset($form['action']) ? $this->getAbsoluteUrl($form['action']) : $this->getUrl();
  62.         // This part is not pretty. There is very little I can do.
  63.         if ($upload) {
  64.           foreach ($post as &$value) {
  65.             if (strlen($value) > 0 && $value[0] == '@') {
  66.               $this->fail(t("Can't upload and post a value starting with @"));
  67.               return FALSE;
  68.             }
  69.           }
  70.           foreach ($upload as $key => $file) {
  71.             $post[$key] = '@' . realpath($file);
  72.           }
  73.         }
  74.         else {
  75.           $post_array = $post;
  76.           $post = array();
  77.           foreach ($post_array as $key => $value) {
  78.             // Whether this needs to be urlencode or rawurlencode, is not
  79.             // quite clear, but this seems to be the better choice.
  80.             $post[] = urlencode($key) . '=' . urlencode($value);
  81.           }
  82.           $post = implode('&', $post);
  83.         }
  84.         $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POSTFIELDS => $post, CURLOPT_POST => TRUE));
  85.         // Ensure that any changes to variables in the other thread are picked up.
  86.         $this->refreshVariables();
  87.         return $out;
  88.       }
  89.       // We have not found a form which contained all fields of $edit.
  90.       foreach ($edit as $name => $value) {
  91.         $this->fail(t('Failed to set field @name to @value', array('@name' => $name, '@value' => $value)));
  92.       }
  93.     }
  94.   }
  95.  
  96.  
  97.     /**
  98.    * Handle form Modified
  99.    */
  100.   protected function handleFormModified(&$post, &$edit, &$upload, $submit, $form) {
  101.     // Retrieve the form elements.
  102.     $elements = $form->xpath("//input[@type='text']|//textarea");
  103.     $submit_matches = FALSE;
  104.     foreach ($elements as $element) {
  105.       // SimpleXML objects need string casting all the time.
  106.       $name = (string)$element['name'];
  107.       // This can either be the type of <input> or the name of the tag itself
  108.       // for <select> or <textarea>.
  109.       $type = isset($element['type']) ? (string)$element['type'] : $element->getName();
  110.       $value = isset($element['value']) ? (string)$element['value'] : '';
  111.       $done = FALSE;
  112.       if (isset($edit[$name])) {
  113.         switch ($type) {
  114.           case 'text':
  115.           case 'textarea':
  116.             $post[$name] = $edit[$name];
  117.             unset($edit[$name]);
  118.             break;
  119.         }
  120.       }
  121.       if (!isset($post[$name]) && !$done) {
  122.         switch ($type) {
  123.           case 'textarea':
  124.             $post[$name] = (string)$element;
  125.             break;
  126.           case 'submit':
  127.             if ($submit == $value) {
  128.               $post[$name] = $value;
  129.               $submit_matches = TRUE;
  130.             }
  131.             break;
  132.           default:
  133.             $post[$name] = $value;
  134.         }
  135.       }
  136.     }
  137.     return $submit_matches;
  138.   }