[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[suse-security] Stopping XSS attacks



Hi all!

I have found a way to limit the effects of Cross Site
Scripting attacks - possibly stopping them completely.

The idea is to write a 'closed site' that will not allow
passing of variables on the URL line.

This has been tested with apache 1.3.26, php4 etc under SuSE
8.1 pro on my box. (site is still under development - though
I may put it on line for testing purposes if you want to
contact me first)

I've used special FORM POST buttons written for passing
values between php4 scripts in a closed environment.
(please see below)

The only way into the website is via a URL WITHOUT anything
passed after the ? of the URL.

Once a user is on the homepage, they have to use the special
FORM POST buttons to navigate this site.

This is what I use on my website, which is STILL under
construction, due to security issues, such as XSS.

Any attempt to pass variables with the URL will be
identified and the script will terminate!

Would this be of use in stopping/limiting cross site
scripting exploits, ref: CA-2000-02 ?


Here it is:


 // this line needs to be called at the begining of each php4
 // script, to put the URL query string into the global scope.
 // register_globals in php.ini must be set to OFF
 // or this method will not work!

 $url_string = $_SERVER["QUERY_STRING"];

/*-------------------------------------------------------------*/

/* Call this function (from an included file) at the start
   of each php4 script to detect and stop variables from being passed
   in the URL query string. */

function url_check($url_string)
{
 if (DEBUG_CODE)
 {
  echo "common.url string: '$url_string' <BR>";
 }

 if ('' <> $url_string)
 {
  echo '<P> Passing of variables by URL query string is not
            supported! <BR>'.
       'Program terminating now - Please try again';

  echo '<P> Found in URL -> ' . $url_string . '<BR>';
  exit();
 }
}
/*-------------------------------------------------------------*/

So, if an attacker tries to pass anything on the URL line,
it will not be accepted!

Then, instead of using an HREF link, I use a custom php4
function like the one below, for each script to be called.

All these 'buttons' live in an include file, that is
included at the start of each executable script.

Other advantages are that the button is declared only once,
but available to ALL pages that include it!

This makes updating variables passed to other pages very
easy to, as they ONLY need to be modified once, in the
included file!

As register_globals is OFF, the hidden variables passed from
the calling script, have to be made available to the called
script with:

/*--------------------------------------------------*/

// get form button POST variables from array

$host_name     = $HTTP_POST_VARS["host_name"];
$debug_value   = $HTTP_POST_VARS["debug_value"];
$table_output  = $HTTP_POST_VARS["table_output"];
$advcd_search  = $HTTP_POST_VARS["advcd_search"];

// $xyz_var_name  = $HTTP_POST_VARS["xyz_var_name"];

/*--------------------------------------------------*/

At the start of each script, before they are accessed.

This puts them back into the global scope, as if
register_globals was set to ON.

As you can see from below, this is just a simple HTML form,
with no INPUT controls, so all the user sees is the submit
button, with a descriptive name telling them what pressing
the button will do.

/*---------------------------------------------------------*/
/*  (simple) Search for a mutual property exchange button  */
/*---------------------------------------------------------*/

function simple_SEARCH_button($text)
{
 // declare the following variables as global to access them
 global $debug_value;
 global $table_output;

 ?> <!-- back into HTML mode -->

 <FORM ACTION="./search.hml" METHOD="POST">

 <P ALIGN=CENTER>
 <INPUT TYPE="SUBMIT" VALUE="<?php echo $text; ?>"> </P>

 <!-- ========================================================== -->

 <!-- pass the following hidden variables with the form -->

 <INPUT TYPE="HIDDEN" NAME="debug_value"
         VALUE="<?php echo $debug_value; ?>">

 <INPUT TYPE="HIDDEN" NAME="table_output"
         VALUE="<?php echo $table_output; ?>">

 <INPUT TYPE="HIDDEN" NAME="advcd_search" VALUE="OFF">

 <!-- ========================================================== -->

 </FORM>

 <?php // back into php mode

} // end of function simple_SEARCH_button($text)
/*-------------------------------------------------------------*/


/*--------------------------------------------------*/
/*  Advanced search for a property exchange button  */
/*--------------------------------------------------*/

function ADVCD_SEARCH_button($text)
{
 // declare the following variables as global to access them
 global $debug_value;
 global $table_output;

 ?> <!-- back into HTML mode -->

 <FORM ACTION="./search.hml" METHOD="POST">

 <P ALIGN=CENTER>
 <INPUT TYPE="SUBMIT" VALUE="<?php echo $text; ?>"> </P>

 <!-- ========================================================== -->

 <!-- pass the following hidden variables with the form -->

 <INPUT TYPE="HIDDEN" NAME="debug_value"
         VALUE="<?php echo $debug_value; ?>">

 <INPUT TYPE="HIDDEN" NAME="table_output"
         VALUE="<?php echo $table_output; ?>">

 <INPUT TYPE="HIDDEN" NAME="advcd_search" VALUE="ON">

 <!-- ========================================================== -->

 </FORM>

 <?php // back into php mode

} // end of function ADVCD_SEARCH_button($text)
/*-------------------------------------------------------------*/


Then, to call for example, the script search.hml from another page I use:

<TR>
  <TD COLSPAN="100%">
    <?php // back into php mode
    simple_SEARCH_button('Search for a mutual property exchange');
    ?> <!-- back into HTML mode -->

<TR>
  <TD COLSPAN="100%">
    <?php // back into php mode
    ADVCD_SEARCH_button('Advanced search for a property exchange');
    ?> <!-- back into HTML mode -->

<TR>
  <TD COLSPAN="100%">
    <?php // back into php mode
    ADD_REC_button('Add your exchange details to the database');
    ?> <!-- back into HTML mode -->

<TR>
  <TD COLSPAN="100%">
    <?php // back into php mode
    EDIT_REC_button('Update your details in the database');
    ?> <!-- back into HTML mode -->

So, variables are passed between the php4 scripts, as HIDDEN
HTML FORM variables, and not on the URL line.

AFAIK, this makes altering values passed between scripts
very difficult for attackers, which is what is intended.

If you have any comments or questions please contact me,

Kind Regards - Keith Roberts




-- 
Check the headers for your unsubscription address
For additional commands, e-mail: suse-security-help@xxxxxxxx
Security-related bug reports go to security@xxxxxxx, not here