WebApp Sec mailing list archives

Re: XSS, SQL injection etc - permutations of input strings


From: "James Barkley" <James.Barkley () noaa gov>
Date: Tue, 28 Sep 2004 01:05:45 -0400

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


Turning off GET requests may not buy you as much as you think.  Any
dedicated hacker who is going to be attempting xss or sql injection,
etc. probably knows how to save a page and tamper the post form vars.
Also, if you do regular log checks variable tampering through GET
requests is typically much easier to spot as the entire URL is logged
and you can see hacking attempts as part of the URL request.

Best thing to do is turn off register_globals and then sanitize all
input based on what type you expect.  IF you expect an integer, an
alpha_numeric, a string containing typeable characters, etc.  All are
easy to sanitize with preg_match.  IF you are really concerned about
the source, check that as well.

Here's a prototype of a sanitizing function and some examples of how
to use:
<snip>
function appeal ($name, $type=__MY_UNKNOWN, $source=__MY_UNKNOWN,
$min=__MY_UNKNOWN, $max=__MY_UNKNOWN,$types=-1);
<snip>

<snip>
$uid = appeal ("uid", __MY_INTEGER, __MY_GET);
$summary = appeal("summary", __MY_ASCII_TYPEABLE, __MY_POST);
$ftypes[0] = 'add';
$ftypes[1] = 'delete';
$ftypes[2] = 'search';
$action = appeal ("action", __MY_CUSTOM, __CN_POST_OR_GET, 20, $ftypes);
<snip>

My two cents.


focus () karsites net wrote:

|Thankyou for your comments Devdas.
|
|On Wed, 22 Sep 2004, Devdas Bhagat wrote:
|
|>To: webappsec () securityfocus com
|>From: Devdas Bhagat <devdas () dvb homelinux org>
|>Subject: Re: XSS, SQL injection etc - permutations of input strings
|>
|>Actually, there are two types of user input, untrusted and untrusted.
|>You are assuming that the only input possible is via the browser
|>interface.
|>What happens if that is bypassed?
|
|
|No - if an attacker creates some custom attack forms on
|their machine , and POST's them to the appropriate pages on
|my server, all the checking functions are still waiting to
|check user I/P at the server end (see examples further
|down)- So I don't do hacking checks in J/S at the Browser
|end, as you rightly point out - that can be by-passed!
|
|>>I use php on my server, and do not allow passing of values
|>>in the URL query string - probably a bit to restrictive for
|>>most sites that like to pass the session ID in the URL.
|>
|>So you block http get?
|
|
|Yes - if you take a look at www.karsites.net - I use the
|following function (in php on the server) to block any GET's
|that try to pass values in the URL. GET's without URL
|variables are accepted.
|
|At the start of each script you will need to put:
|
|// get the URL query string and put into global scope!
|$v_url_string = $_SERVER["QUERY_STRING"];
|
|/*-------------------------------------------------------------*/
|
|/* Call this function at the start of each script to detect
|   and stop unexpected variables from being passed
|   with the 'GET' URL query string. */
|
|function url_check($v_url_string)
|{
| if ('' != $v_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 -> ' . $v_url_string . '<BR>';
|  exit();
| }
|}
|/*-------------------------------------------------------------*/
|
|I suppose the above fuction may be adapted to do alot less
|restrictive URL checking, and just allow a SID to be passed;
|anything else - terminate the script.
|
|Or - even call other checking functions as per examples
|below, to check URL variable names and content. I found it
|alot easier to scrap passing of variables in the GET
|method, and just focus on the POST vars instead.
|
|(I also use POST to force a reload of the pages, as GET
|sometimes comes from a cache, which would mean old
|dynamic pages being served up to the user).
|
|
|>>  string_check($v_ref_number, 'v_ref_number');
|>>  property_check($v_wants_property, 'v_wants_property');
|>>  area_check($v_wants_area, 'v_wants_area');
|>>  Y_N_check($v_wants_careline, 'v_wants_careline');
|>>  Y_N_check($v_wants_pics, 'v_wants_pics');
|>>
|>>Once all the inputs have been checked at the start of the
|>>script, then I only refer to the checked and validated
|>>values in the php variables. I do not refer to the values in
|>>$_POST["v_name"] , as these contain the unchecked values.
|>
|>A good way of doing things. Personally, I would prefer an interface like
|>$untainted_variable = check(type, variable)
|>where the check method knows about the appropriate bounds for 'type'.
|
|
|Yes - that is another way of doing the checking - or maybe
|something similar to:
|
| $untainted_var1 = input_type_check($_POST["var1"], 'var1_name');
|
| $v_wants_area = area_check($_POST["v_wants_area"], 'v_wants_area');
|
|
|Here are a few of the custom php checking functions I use to
|check certain types of user I/P - they are a bit verbose and
|in need of optimisation (The error message part could be
|made into a seperate function, to reduce code size).
|
|// Called via string_check() at the start of each script, to identify
the string
|// find_txt (in lowercase, uppercase, or any combination of case) (or
single
|// character) hidden inside form variables posted to the server, and
terminate
|// this script if found.
|
|// $v_var is variable to check
|// $v_varname is text string name of variable
|// $v_find_txt is the string to look for in $v_var
|
|function string_hacking_check($v_var, $v_varname, $v_find_txt)
|{
| $v_str1 = strtolower($v_var);
| $v_str2 = strtolower($v_find_txt);
|
| $v_found = strchr($v_str1, "$v_str2");
|
| if ('' <> $v_found)
| {
|  echo "<P> The character or word <FONT COLOR='red'> $v_find_txt
</FONT>".
|       "was found in your <FONT COLOR='blue'> $v_varname </FONT>
variable <BR>".
|       "This is NOT valid input -> <FONT COLOR='red'> $v_var </FONT>
<BR>".
|       "Program terminating now - Please try again";
|  exit();
| }
|} // end of function string_hacking_check($v_var)
|/*-------------------------------------------------------------*/
|
|// function to remove any invalid characters from form input
|// variables without terminating the script being checked
|
|// $v_var is variable to check for invalid characters
|
|function strip_invalid_chars($v_var)
|{
| $v_new_txt = strtolower($v_var);
|
| /////////////////////////////////
| // strip escaped characters
| $v_new_txt = str_replace("\'", "", $v_new_txt);
| $v_new_txt = str_replace("\"", "", $v_new_txt);
| $v_new_txt = str_replace("\\", "", $v_new_txt);
|
| /////////////////////////////////
| // strip unwanted ordinary characters
|
| $v_new_txt = str_replace("/", "", $v_new_txt);
| $v_new_txt = str_replace(";", "", $v_new_txt);
| // test data
| $v_new_txt = str_replace("***", "", $v_new_txt);
| $v_new_txt = str_replace("aBc", "", $v_new_txt);
|
| return $v_new_txt;
|
|} // end of function strip_invalid_chars($v_var)
|/*-------------------------------------------------------------*/
|
|// function to strip a string from a form variable WITHOUT
terminating the
|// script. String may be in lowercase, uppercase, or any combination.
|// this function is called from string_check(...) below
|//
|// $v_var is variable to check
|// $v_varname is the text-string-name of the variable
|// $v_txt_str is the string to strip from $v_var
|
|function strip_invalid_string($v_var, $v_varname, $v_txt_str)
|{
| $v_new_txt = trim($v_var);
|
| $v_str1 = strtolower($v_new_txt);
| $v_str2 = strtolower($v_txt_str);
|
| $v_new_txt = str_replace($v_str2, "", $v_str1);
|
| if ('v_name' == $v_varname)
|  $v_new_txt = ucwords($v_new_txt);
|
| if ('v_address' == $v_varname)
|  $v_new_txt = ucwords($v_new_txt);
|
| if ('v_post_code' == $v_varname)
|  $v_new_txt = strtoupper($v_new_txt);
|
| if ('v_phone_number' == $v_varname)
|  $v_new_txt = strtoupper($v_new_txt);
|
| if ('v_extra_info' == $v_varname)
|  $v_new_txt = ucwords($v_new_txt);
|
| if ('****' == $v_varname)
|  $v_new_txt = $v_var;
|
| return $v_new_txt;
|
|} // end of function strip_invalid_string($v_var)
|/*-------------------------------------------------------------*/
|
|/* check for unknown input from form variables  */
|
|// $v_var is variable to check
|// $v_txt is text-string-name of variable
|
|function string_check($v_var, $v_txt)
|{
| // strip out any php or html tags first
| $v_var = strip_tags($v_var);
|
| // check for other known hacking strings and STOP script if found
| // add as many more checks here as needed
|
| // string_hacking_check($v_var, $v_txt, 'here');
| // string_hacking_check($v_var, $v_txt, 'there');
| // string_hacking_check($v_var, $v_txt, 'and everywhere');
|
| // strip characters or strings from form variables
| // WITHOUT stopping the script - extend this part as required
|
| // strip out invalid control characters first
| $v_new_str = strip_invalid_chars($v_var);
|
| // strip invalid strings from form variables
| $v_new_str = strip_invalid_string($v_new_str, $v_txt, '');
| // $v_new_str = strip_invalid_string($v_new_str, $v_txt, 'ZZZ');
|
| return $v_new_str;
|
|} // end of function string_check($v_var)
|/*-------------------------------------------------------------*/
|
|// the following checking functions should be self-explanatory!
|
|// $v_var is variable to check
|// $v_txt is text-string-name of variable
|
|function property_check($v_var, $v_txt)
|{
| // initialise checked_OK variable
| $v_checked_OK = 'NO';
|
| if ('' == $v_var
|     OR 'House' == $v_var
|     OR 'Bungalow' == $v_var
|     OR 'Bedsit' == $v_var
|     OR 'Downstairs Flat' == $v_var
|     OR 'Downstairs Maisonette' == $v_var
|     OR 'Upstairs Flat' == $v_var
|     OR 'Upstairs Maisonette' == $v_var
|     OR 'Y' == $v_var
|     OR 'N' == $v_var)
|
|     $v_checked_OK = 'YES';
|
| if ( 'NO' == $v_checked_OK)
| {
|  echo "<P> There is bad input in your <FONT COLOR='blue'> $v_txt
</FONT> variable <BR>" .
|       "This is NOT valid input  -> <FONT COLOR='red'> $v_var </FONT>
<BR>".
|       "Program terminating now - Please try again";
|  exit();
| }
|} // end of function property_check($v_var, $v_txt)
|/*-------------------------------------------------------------*/
|
|// $v_var is variable to check
|// $v_txt is text-string-name of variable
|
|function area_check($v_var, $v_txt)
|{
| // initialise checked_OK variable
| $v_checked_OK = 'NO';
|
| if ('' == $v_var
|     OR 'South Lynn' == $v_var
|     OR 'North Lynn' == $v_var
|     OR 'Central' == $v_var
|     OR 'Marsh Lane' == $v_var
|     OR 'Gaywood' == $v_var
|     OR 'Fairstead' == $v_var
|     OR 'South Wotton' == $v_var
|     OR 'North Wotton' == $v_var
|     OR 'Villages' == $v_var
|     OR 'Y' == $v_var
|     OR 'N' == $v_var)
|
|     $v_checked_OK = 'YES';
|
| if ( 'NO' == $v_checked_OK)
| {
|  echo "<P> There is bad input in your <FONT COLOR='blue'> $v_txt
</FONT> variable <BR>" .
|       "This is NOT valid input  -> <FONT COLOR='red'> $v_var </FONT>
<BR>".
|       "Program terminating now - Please try again";
|  exit();
| }
|} // end of function area_check($v_var, $v_txt)
|/*-------------------------------------------------------------*/
|
|You may use these checking functions ENTIRELY AT YOUR OWN RISK!
|
|Kind Regards - Keith Roberts
|
|
|

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFBWPEmBtvwQGcl/zERAr6+AJ0c3jY5Lrsm7ZMhh2pRlhNf2kMdcwCfRVfH
2LTsTig0xCtH/jH40JJdyfM=
=c5VO
-----END PGP SIGNATURE-----


Current thread: