PHP_SELF and XSS - php

I've found an article claiming that $_SERVER['PHP_SELF'] is vulnerable to XSS.
I'm not sure if I have understood it correctly, but I'm almost sure that it's wrong.
How can this be vulnerable to XSS attacks!?
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<!-- form contents -->
</form>

To make it safe to use you need to use htmlspecialchars().
<?php echo htmlspecialchars($_SERVER["PHP_SELF"], ENT_QUOTES, "utf-8"); ?>
See A XSS Vulnerability in Almost Every PHP Form I’ve Ever Written for how $_SERVER["PHP_SELF"] can be attacked.

It is indeed a XSS vulnerability. I do understand that you believe it may not harm your website, but this doesn't mean it is not real.
If you do not believe it, try the following:
We assume you have a page such as "registration.php".
We assume you have a form where action is:
<?php echo $_SERVER['PHP_SELF']; ?>
as you put it down indeed:
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<!-- form contents -->
</form>
Now simply append the string below
%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E
It is not actually hard to understand, because PHP_SELF is a reflection of the URL, your application will read whatever you put in the URL and echo it. It is simple as that.
htmlspecialchars should take care of the matter, no reason to dispute the evidence.
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
<!-- form contents -->
</form>
However, even this is a first step in stealing a cookie, it's not that it take place automatically. Even if it's quite easy to craft the attack (as the attacker will register on your site and will see how the cookie looks...etc.), a series of other factors must be true to get to the point of having a cookie stealing situation. For instance, the cookie must not be expired. Than it depends of how complex the cookie is. Than maybe you have other precautions in placed on server, it doesn't have to be all authentication based on the presence of cookie!
While I do believe it is rather difficult and really bad programming for all conditions to met (even if yahoo.mail for example had such a vulnerability and if you look on internet you will find even the exploit and the cookie decoder), the XSS is real and who knows what a crafty attacker may do if your site suffer of it. The cure is simple...

The very article you linked gives you:
http://www.example.com/form.php/%22%3E%3Cscript%3Ealert(‘xss attack’)%3C/script%3E%3Cbr%20class=%22irrelevant
what's not clear?
Edit: this is an XSS attack because I can hide a link from my site to yours with some JS added to the URL which sends me your cookies so the moment you click that link, you are pwnd.

You should be using filter_input() to access superglobals in PHP. If you set the filter to FILTER_SANITIZE_FULL_SPECIAL_CHARS it will strip the unsafe characters typically used in XSS. Given your example:
<form method="post"
action="<?php filter_input(INPUT_SERVER, 'PHP_SELF', FILTER_SANITIZE_FULL_SPECIAL_CHARS); ?>">
<!-- form contents -->
</form>

The vulnerability is that a user can enter malicious JavaScript codes in the form. To prevent this, htmlspecialchars function is used.
Predefined characters (like >, <, ", ') are converted into entities(> < etc)
htmlspecialchars($_SERVER["PHP_SELF"]) ensures that all submitted form variables are converted into entities.
To read more about this vulnerability, visit: https://www.w3schools.com/php/php_form_validation.asp
Another link that can help you: https://www.google.com/amp/s/www.bitdegree.org/learn/php-form-validation/amp

I am studying this issue about the PHP_SELF variable and the XSS attack. There is something that I still can't understand: PHP_SELF variable is suposed to reference the name of the script file (the script that is running). Then, why does it take its value from the URL? (allowing the XSS problem).

Related

Sending token query string parameter from webpage url in POST request

I'm trying to send a POST request with part of the webpage URL as the parameter. For instance, in this url:
http://testsite.com/confirmEmail/?token=abcdefg
I want to be able to send the input token with the value abcdefg. I want to make this responsive to different token values. Any ideas?
Thanks
This answer is assuming they will do some action on this page, otherwise you would want a redirect.
<?php
$token=$_GET['token'];
?>
<form method="POST">
<input type="hidden" name="token" value="<?php echo htmlentities($token, ENT_QUOTES);?>" />
<!--other form fields and submit button here-->
</form>
UPDATE:
This was a simple answer, to be easily understood, but of course echoing out a get variable straight from the url opens you up to xss. Someone edited my answer to strip quotes from that variable but htmlentities() is also vulnerable to xss. I believe the appropriate function nowadays is htmlspecialchars($token, ENT_QUOTES, "UTF-8"). If you go this route, you need to be careful about which encoding & characters you put in your tokens now, so they aren't stripped, which would probably break your verification process. Looks like it's numeric in the example, so you should be ok. Also remember someone could still post a modified form, so you need to sanitize this token field to prevent injections, but hopefully that's not relevant to this question.

$_SERVER['REQUEST_URI'] - Preventing XSS and other attacks

I'm building a form where users can upload files to my server. The upload script is in PHP and is secure but I'm unsure how secure my form action is.
At the moment I do the following on submit:
<form id="apply" method="post" enctype="multipart/form-data" action="<?php echo htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES, "utf-8"); ?>">
I've read about XSS and the $_SERVER array and how to use htmlspecialchars to secure it.
Is this enough? Should I be doing something else?
Just use action="", it will POST to the current page.
It's not secure to directly use $_SERVER['REQUEST_URI'] value, even if you use htmlspecialchars

Header Location - return url in post - is it safe?

I have something like this (short version):
index.php:
<?PHP
echo "<form action='process_form.php?action=do_something' method='post'>";
echo "<input type='hidden' name='return_url' value='index.php?".$_SERVER['QUERY_STRING']."'>";
?>
and now in process_form.php I have processed that form and at the end of it I put this:
<?PHP
$return_url = $_POST['return_url'];
header ("location: $return_url");
die();
?>
My question is - am I doing it right? Is it right way of processing POST forms data and redirecting back? Thing is that my return url can be anything, but I want users be redirected exactly to where they submitted that form.
Is there some security concern I should pay special attention to?
Thanks
I would use this:
index.php
<form action="process_form.php" method="post">
<input type="hidden" name="action" value="do_something" />
<input type="submit" value="Submit" />
</form>
process_form.php
<?php
header('Location: ' . $_SERVER['HTTP_REFERER']);
?>
I don't see any problem. A hacker would gain nothing by tinkering with the POST variable. He's just messing with the HTTP response he himself is going to get. Since the request is a POST, a caching server would not save the response. Response splitting is not a potential attack vector here.
What you're doing is correct. If instead of $_POST, you were to redirect off a $_SESSION variable, then there would be multiple vulnerabilities.
Using $_POST anywhere in your code without filtering has a potential to cause unwanted behaviour; in your case, you should be aware of response splitting attacks.
The good news is that since PHP 5.1.2 it's no longer possible to unknowingly set multiple headers in a single header() call.
That said, you could still check out the various input filters that typically ship with PHP - e.g. FILTER_VALIDATE_URL.

How to make $_POST more secured?

This is a sample code that i got from Facebook Engineering page.
<?php
if ($_POST['name']) {
?>
<span>Hello, <?=$_POST['name']?>.</span>
<?php
} else {
?>
<form method="post">
What is your name?<br>
<input type="text" name="name">
<input type="submit">
</form>
<?php
}
It says that the above code is not secured because it is open to cross site scripting. the correct way is to pass the $_POST['name'] via htmlspecialchars(). However, they stated that it is poor programming practice.
Is always passing $_POST variable via a htmlspecialchars() inefficient?
I can't thought of any way to make it secure. They introduce XHP which i am reluctant to use.
Reference: https://www.facebook.com/notes/facebook-engineering/xhp-a-new-way-to-write-php/294003943919
the correct way is to pass the $_POST['name'] via htmlspecialchars(). However, they stated that it is poor programming practice.
It's not poor practice in itself. The problem is that when you have to type htmlspecialchars every single time you drop text content into HTML, you are quite likely to forget one, leaving a vulnerability.
What that page is saying, correctly, is that it's better to have a templating language that HTML-escapes by default, so that you don't have to think about it. This is a lesson most web frameworks have learned by now, but raw PHP still doesn't have a convenient way to do that.

What is the benefit of using the super global `$_SERVER['PHP_SELF']` in PHP?

What is the benefit of using the super global $_SERVER['PHP_SELF']?
$_SERVER['PHP_SELF'] doesn't (or shouldn't) include the domain name. It includes the path component of the url that the script was called from.
Its use is primarily to introduce cross site scripting vulnerabilities.
you can use it to fill in the action attribute of a form tag:
<form method="post" action="<?=$_SERVER['PHP_SELF']?>"></form>
If I then call your page with:
your-file-that-uses-php-self.php/("><script>eval-javascript-here</script>)
where everything in parens is urlencoded then I can inject the code into your page. If I send that link to somebody else, then I'm executing that code in their browser from your site.
Edit:
To make it safe against XSS attacks, use htmlspecialchars:
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">...</form>
Edit 2: As this $_SERVER variable has been misused so often out there in examples across the internets, don't miss reading your HTML reference: As that URI is the shortest possible relative URI, you can just leave the action attribute empty:
<form action="" method="post" >...</form>

Categories