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.   function drupalPostModified($html, $form_id, $edit, $submit) {
  33.     $submit_matches = FALSE;
  34.     if ($this->parse()) {
  35.       $edit_save = $edit;
  36.       // Let's iterate over all the forms.
  37.       $forms = $this->elements->xpath("//input[@id='".$form_id."']/parent::*");
  38.       $form = $forms[0];
  39.       $edit = $edit_save;
  40.       $post = array();
  41.       $upload = array();
  42.       $submit_matches = $this->handleFormModified($post, $edit, $upload, $submit, $form);
  43.       $action = isset($form['action']) ? $this->getAbsoluteUrl($form['action']) : $this->getUrl();
  44.       // This part is not pretty. There is very little I can do.
  45.       if ($upload) {
  46.         foreach ($post as &$value) {
  47.           if (strlen($value) > 0 && $value[0] == '@') {
  48.             $this->fail(t("Can't upload and post a value starting with @"));
  49.             return FALSE;
  50.           }
  51.         }
  52.         foreach ($upload as $key => $file) {
  53.           $post[$key] = '@' . realpath($file);
  54.         }
  55.       }
  56.       else {
  57.         $post_array = $post;
  58.         $post = array();
  59.         echo "<pre>".print_r($post_array,1)."</pre>";
  60.         foreach ($post_array as $key => $value) {
  61.           // Whether this needs to be urlencode or rawurlencode, is not
  62.           // quite clear, but this seems to be the better choice.
  63.           $post[] = urlencode($key) . '=' . urlencode($value);
  64.         }
  65.         $post = implode('&', $post);
  66.       }
  67.       die;
  68.       $out = $this->curlExec(array(CURLOPT_URL => $action, CURLOPT_POSTFIELDS => $post, CURLOPT_POST => TRUE));
  69.       // Ensure that any changes to variables in the other thread are picked up.
  70.       $this->refreshVariables();
  71.       return $out;
  72.     }
  73.   }
  74.  
  75.  
  76.     /**
  77.    * Handle form Modified
  78.    */
  79.   protected function handleFormModified(&$post, &$edit, &$upload, $submit, $form) {
  80.     // Retrieve the form elements.
  81.     $elements = $form->xpath("//input[@type='text']|//textarea");
  82.     $submit_matches = FALSE;
  83.     foreach ($elements as $element) {
  84.       // SimpleXML objects need string casting all the time.
  85.       $name = (string)$element['name'];
  86.       // This can either be the type of <input> or the name of the tag itself
  87.       // for <select> or <textarea>.
  88.       $type = isset($element['type']) ? (string)$element['type'] : $element->getName();
  89.       $value = isset($element['value']) ? (string)$element['value'] : '';
  90.       $done = FALSE;
  91.       if (isset($edit[$name])) {
  92.         switch ($type) {
  93.           case 'text':
  94.           case 'textarea':
  95.             $post[$name] = $edit[$name];
  96.             unset($edit[$name]);
  97.             break;
  98.         }
  99.       }
  100.       if (!isset($post[$name]) && !$done) {
  101.         switch ($type) {
  102.           case 'textarea':
  103.             $post[$name] = (string)$element;
  104.             break;
  105.           case 'submit':
  106.             if ($submit == $value) {
  107.               $post[$name] = $value;
  108.               $submit_matches = TRUE;
  109.             }
  110.             break;
  111.           default:
  112.             $post[$name] = $value;
  113.         }
  114.       }
  115.     }
  116.     return $submit_matches;
  117.   }