Cenzic 232 Patent
Paid Advertising
sla.ckers.org is
ha.ckers sla.cking
Sla.ckers.org
Q and A for any cross site scripting information. Feel free to ask away. 
Go to Topic: PreviousNext
Go to: Forum ListMessage ListNew TopicSearchLog In
Protecting against XSS
Posted by: david-king
Date: January 09, 2007 10:25PM

I have seen very few articles on the subject of preventing XSS, but a tonne (like the ha.ckers cheat sheet) that outline the various methods and even more case studies! Anyhow, a disjointed few odds and ends:

Do you guys have any good; tips, links, guides on the topic of input validation and XSS protection?

Is it safe to assume that a regular user will not (or could not) input mad characters (as used in your cheat sheet) with normal use of an html <input> or WYSIWYG javascript editor? And thus mad characters could be blacklisted as a whole?

Tis a ponderous thing.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 10, 2007 04:08AM

I have a few methods placed on my blog, it goes from using character encoding to preventing it with Apache. Instead of posting it here you could take a look.

I'm also planning to write a paper the next month covering the prevention of XSS and SQL injection in a whole, so serversided, web application layer, detection, logging and reporting such acts.

Quote

Is it safe to assume that a regular user will not (or could not) input mad characters (as used in your cheat sheet) with normal use of an html <input> or WYSIWYG javascript editor? And thus mad characters could be blacklisted as a whole?

it depends where they are input it. It's a bad idea to let users use a WYSIWYG editor btw. If they own the site, it's there own problem. But, you could start with these things (not in any order):

1.proper encoding
2.htmlentities
3.filter to match against w/b lists
4.strip
5.escape, and insert into db.

anyway that's my method, some think it's better to do this in the output, but ii use both with htmlenties.



Edited 1 time(s). Last edit at 01/10/2007 04:11AM by jungsonn.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: ckore
Date: January 10, 2007 05:18AM

It even depends on the type of input-forms you have. I have several functions called _POST($str) and _GET($str) which do some checks. I work plenty with regular expressions and never use $_GET[] outside this special functions. If I want to get an id of the adressbar, I only allow 0-9 by regular expression and a strlen of, lets say, 10. I also got get-functions for strings and for strings and numbers together. The same goes for post. Numeric only, string only, numeric and string, array only (and there, each entry is also checked).
The big problem comes along with input-types with no maxlength, a forum-post, userprofile-description, private message, whatever.
I think filtering special words is useless as some attack-vectors in the cheatsheet show. htmlspecialchars, htmlentities (don't forget the parameter ENT_QUOTES) are doing a great job here. I'm not sure if it's possible to bypass these functions with some special charsets or whatever, but I think they are safe (or am I wrong?).

You have to consider all input as evil. Don't forget that every form may be rewritten by a user to exploit your form-evaluating script (the form action). So a dropdown-box could easily be converted to a normal input box and allow the user to insert values you don't expect.

By using my own _POST and _GET-functions, I even think twice what kind of data I will accept.

Maybe a small code example for you:
function is_number($str) {
	return (preg_match("/^([0-9])*$/", $str));
}

function _GETNUM($str, $digits = 12) {
	if (!isset($_GET[$str])) {
		return "";
	}
	if (strlen($_GET[$str]) <= $digits && is_number($_GET[$str]))
		return $_GET[$str];
	return "";
}
Don't forget to disable error-messages at your hosted website. You don't need them and they give hints for attackers.



Edited 2 time(s). Last edit at 01/10/2007 05:24AM by ckore.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 10, 2007 03:09PM

Why not use: int($string) it's alot faster to code.

Think I can re-write the code smaller
Not to show off, but I like simple practical code ^^

if($_GET[$str]) {
   if(strlen($_GET[$str] <= 12)) {
   $str = int($_GET[$str]);
        } else {
   exit();
 }
}

BTW b/w listing can surely help, especially in the SQL injection field. Where it is important to blacklist certain chars. Though, one can write a preg_match to see if they are in the string and throw errors when you have not an integer as string.

A black list function example i wrote a while back,
case insensitive and forced UTF-8:
function StripXSS($input) {

$vectors ='/script|eval|innerHTML|charset|document|string|
create|append|onbefore|onload|onerror|binding|frame|alert|
msgbox|refresh|embed|ilayer|applet|cookie|{|}|[|]|<|>|%3c|
%3e|&lt|&gt|&#60|&#060|&#x3c|&#x03c|javascript|void|href/i';

if(preg_match($vectors, $input)) {
echo "Chars not allowed!";
die();
} else {
$input = htmlentities($input, ENT_QUOTES, 'UTF-8');
}
return $input;
}

But it depends on what you are try to filter yes,
so it requieres mostly a custom function.



Edited 1 time(s). Last edit at 01/10/2007 03:19PM by jungsonn.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Delixe
Date: January 10, 2007 03:19PM

I saw an interesting method of preventing XSS on a server I am hosted.

Any link with <script> inside of it got forwarded to a Not Acceptable page. Obviously this isn't a kill all XSS method but it could stop a few people and methods dead in their tracks.



Edited 1 time(s). Last edit at 01/10/2007 03:20PM by Delixe.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 10, 2007 03:35PM

I wrote a .htaccess piece for that last week, for both XSS and SQL:

XSS:
somesite.com/,;<>'`
somesite.com/file.php?var=">abc<
somesite.com/file.php?var=<script>abc
somesite.com/file.php?var=javascript:abc

SQL:
somesite.com/file.php?var=; sqlfunction abc
somesite.com/file.php?var=' sqlfunction abc
somesite.com/file.php?var=" sqlfunction abc


Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} (\"|%22).*(\>|%3E|<|%3C).* [NC]
RewriteRule ^(.*)$ log.php [NC]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC]
RewriteRule ^(.*)$ log.php [NC]
RewriteCond %{QUERY_STRING} (javascript:).*(\;).* [NC]
RewriteRule ^(.*)$ log.php [NC]
RewriteCond %{QUERY_STRING} (\;|\'|\"|\%22).*(union|select|insert|drop|update|md5|benchmark|or|and|if).* [NC]
RewriteRule ^(.*)$ log.php [NC]
RewriteRule (,|;|<|>|'|`) /log.php [NC]

Works like a charm.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Mephisto
Date: January 10, 2007 09:48PM

I found a site the other day that is only encoding the < sign. Thus rendering it as "&lt;". Anyone discovered and attack vector around this? I believe (thinking back on it) the text is also rendered as a link to another page, so I might be able to URL encode it, but not sure...

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 11, 2007 04:13AM

Apache read it all encoded, and thereby would detect it. so putting < in it, will be in the query string: &lt;

And no, I am not aware of a vector around that, if this exists htmlentities would render useless.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: bubbles
Date: January 11, 2007 08:13AM

I use this RemoveXSS() function on all of my websites:
http://quickwired.com/kallahar/smallprojects/php_xss_filter_function.php

-bubbles
http://webmastertutorials.net

Options: ReplyQuote
Re: Protecting against XSS
Posted by: WhiteAcid
Date: January 11, 2007 08:23AM

Something like this makes more sense to me: http://www.we11er.co.uk/programming/safestring.html

Obiously it's not complete, but the idea is good.

Don't forget our IRC: irc://irc.irchighway.net/#slackers
-WhiteAcid - your friendly, very lazy, web developer

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 11, 2007 11:00AM

@bubbles

I think it's too huge, Though the array function in it with blackwords is good. half of the code can be filtered by one PHP function alone:
escapeshellcmd() which slashes anything which can be used as shell command.


@whiteacid:

mysql_real_escape_string() is better practise then addslases, but still a problem with SQL injection to the CONCAT(CHAR()) vector. cause it only escapes this set:

\x00, \n, \r, \, ', " and \x1a.

So I can still inject SQL quoteless vectors. ^^

But to be on topic: It really requires a custom build one, a combination like from the links and snippets above. At least if you are extremly paranoid.



Edited 1 time(s). Last edit at 01/11/2007 11:08AM by jungsonn.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Delixe
Date: January 11, 2007 11:16AM

I use the following functions to prevent XSS:
function formatOutput($str)
{
	$tmp = nl2br(htmlspecialchars(stripslashes($str)));
	return $tmp;
}

function formatInput($mixed)
{
	if(is_array($mixed))
	{
		reset($mixed);
		while(list($key,$value) = each($mixed))
			$mixed[$key] = htmlspecialchars(stripslashes($value));
	}
	else
		$mixed = htmlspecialchars(stripslashes($mixed));
	return $mixed;
}

Against SQL Injections:
function mqesc($mixed)
{
	if(is_array($buf))
	{
		reset($mixed);
		while(list($key,$value) = each($mixed))
			$mixed[$key] = mysql_real_escape_string($value);
	}
	else
		$mixed = mysql_real_escape_string($mixed);
	return $mixed;
}



Edited 2 time(s). Last edit at 01/11/2007 11:18AM by Delixe.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 11, 2007 11:28AM

@Delixe,

isn't it a little strange to generate <br /> tags _before_ you htmspecialchar'it and then stripslash'it?

I would do it like this:

function formatOutput($str)
{
$tmp = htmlspecialchars(stripslashes(nl2br($str)));
return $tmp;
}

But, maybe i'm to picky right now, so I leave it. :)



Edited 1 time(s). Last edit at 01/11/2007 11:33AM by jungsonn.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 11, 2007 11:31AM

@Delixie

so I can still inject:

SELECT * FROM login WHERE user = CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110),CHAR(39))

But that depends what you put in $buf, what is in there BTW?

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Delixe
Date: January 11, 2007 12:12PM

jungsonn Wrote:
-------------------------------------------------------
> @Delixie
>
> so I can still inject:
>
> SELECT * FROM login WHERE user =
> CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(
> 105),CHAR(110),CHAR(39))
>
> But that depends what you put in $buf, what is in
> there BTW?

For $buf we put the value, such as WHERE USER '{$val}'. mqesc($val) prior to the SQL statement. I don't think CONCAT would work...I haven't tested it.

@Jungsonn: stripslashes doesn't do anything to \n only to \', \\, etc. nl2br must be used last so we have line breaks.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 11, 2007 03:36PM

Well, it really does bypasses mysql_real_escape_string():

a var_dump testcase:

string(107) "SELECT * FROM login WHERE user = CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110),CHAR(39))"

no escaping whatsoever.


Testcase 2 without concat:

string(45) "SELECT * FROM login WHERE user =\\\'admin\\\'"

Anyway, I woud not believed it also, until I tryed it.
It was a blog item last week cause it messes everything up:
http://www.jungsonnstudios.com/blog/?i=57&bin=111001



Edited 2 time(s). Last edit at 01/11/2007 03:46PM by jungsonn.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 11, 2007 03:57PM

Ok now a comparative testcase on the 3 most used functions:

mysql_real_escape_string()
SELECT * FROM login WHERE user = CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110),CHAR(39))

addslashes()
SELECT * FROM login WHERE user = CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110),CHAR(39))

escapeshellcmd()
SELECT \* FROM login WHERE user = CONCAT\(CHAR\(39\),CHAR\(97\),CHAR\(100\),CHAR\(109\),CHAR\(105\),CHAR\(110\),CHAR\(39\)\)


So escapeshellcmd() is the winner here, the one I always use for db input.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Admiral Pi
Date: January 11, 2007 05:10PM

Jungsonn, I think you're missing the point of the above posts. They are imagining a vector that looks like

"SELECT * FROM login WHERE username ='" . $user_input . "'"

whereas the vector you are using is

"SELECT * FROM login WHERE userid =" . $user_input

In the first circumstance, I believe you'll find that mysql_real_escape_string() is satisfactory (at least I know of no way around it). In the second instance, which you are using, it isn't satisfactory, but neither is your solution. If my user input was

-1 union select field1 from othertable

it would come through escapeshellcmd() just fine. Obviously, the only solution in the latter circumstance is to convert to an integer or some other highly-restrictive method; escapeshellcmd() just won't cut it.

Furthermore, if ' or " are paired, escapeshellcmd() won't escape them. Therefore, if you are protecting the first vector (the one with the user input inside quotes) with escapeshellcmd(), you can be successfully attacked with the user input

' union select field1 from othertable -- '

So I would definitely recommend everyone avoid using escapeshellcmd() for sql sanitation and just use what you're supposed to--mysql_real_escape_string() if it's a string (see, it even says so in the function name :D ) and intval() if it's an integer.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: rsnake
Date: January 11, 2007 05:30PM

@bubbles, don't use that function, it is vulnerable to at least this vulnerability in IE6.0 (and maybe more):

<IMG SRC=ja&#&#x78;09;vascrip&#&#x78;09;t:alert(String.fromCharCode(88,83,83));>

I emailed Kallahar over a year ago and it has not yet been fixed. There are likely other vulnerabilities, but this is the one I found a year ago.

- RSnake
Gotta love it. http://ha.ckers.org

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Delixe
Date: January 12, 2007 12:18AM

Admiral Pi is right, we explicitly always use single and double quotes to prevent these kinds of occurrences--it's simply a standard I would always use so your attack vectors would be quite useless.

My functions still stand as secure providing you craft your SQL queries in a correct manner using single and double quotes as needed.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 12, 2007 01:15AM

@Admiral PI

Not quite, try to var_dumping the functions, ofcorse it doesn't escape paired quotes, Pairing quotes is silly argument,
sorry to say because now you made it me more easy:

I just insert: admin and get : 'admin'
instead of the whole CHAR() range.

The char range was invented when quotes are stripped, and not paired.

But do you understand that CHAR(39) is being executed as a single quote in SQL? (') That is just where the danger lies. So I could generated single quotes myself in a paired string :) And please read back, see the first post I said it would be a combination. Alas, I give up. just try it yourself some time.


SQL test case I just made with paired quotes:

mysql_real_escape_string()
SELECT * FROM LOGIN WHERE USER = 'CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110),CHAR(39))'

addslashes()
SELECT * FROM LOGIN WHERE USER = 'CONCAT(CHAR(39),CHAR(97),CHAR(100),CHAR(109),CHAR(105),CHAR(110),CHAR(39))'

escapeshellcmd()
SELECT * FROM LOGIN WHERE USER = 'CONCAT\(CHAR\(39\),CHAR\(97\),CHAR\(100\),CHAR\(109\),CHAR\(105\),CHAR\(110\),CHAR\(39\)\)'

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 12, 2007 02:02AM

Oh and what about my all time favorite bypass vector: /**/

like: SE/**/LECT * F/**/R/**/OM etc. this tough to filter against with blacklisting, unless you whitelist certain allowed chars,

escapeshellcmd() escapes that properly.
mysql_real_escape_string() doesn't ^^

but then again it is also possible to hexencode a whole query. I think the awnser for hexencoding lies in proper analysing the variables before putting it in a escaping function, anyone agree?

I think i'm going to write a class for it soon. If anyone has more suggestions for me, or ideas other then discussed above, encoding methods, bypassing the functions etc. please let me know.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: Admiral Pi
Date: January 12, 2007 07:42AM

Let's move the SQL discussion over to the correct forum. I've created a topic.

Options: ReplyQuote
Re: Protecting against XSS
Posted by: jungsonn
Date: January 12, 2007 12:08PM

consider it done ^^

Options: ReplyQuote
Re: Protecting against XSS
Posted by: lpilorz
Date: January 17, 2007 03:44PM

What protection do you recommend against variable-width encoding XSS? I am currently using mb_convert_encoding($variable, 'UTF-8', 'UTF-8'). What do you think about it?

Options: ReplyQuote
Re: Protecting against XSS
Posted by: rsnake
Date: January 17, 2007 06:25PM

Ambush Commander has suggested using iconv()

- RSnake
Gotta love it. http://ha.ckers.org

Options: ReplyQuote


Sorry, only registered users may post in this forum.