Question on use of ternary operator

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
akimm
Forum Contributor
Posts: 460
Joined: Thu Apr 27, 2006 10:50 am
Location: Ypsilanti Michigan, formally Clipsburgh

Question on use of ternary operator

Post by akimm »

To use ternary operator do I need to use GET. I'm just trying to incomperate ternary into my next program so I can learn how to utilize it. I don't need anything at this point except an answer if possible.
LiveFree
Forum Contributor
Posts: 258
Joined: Tue Dec 06, 2005 5:34 pm
Location: W-Town

Post by LiveFree »

You can use the tenerary in any condition

Code: Select all

$var = ( isset($var1) ) ? "ya" : "non";
User avatar
akimm
Forum Contributor
Posts: 460
Joined: Thu Apr 27, 2006 10:50 am
Location: Ypsilanti Michigan, formally Clipsburgh

Ok

Post by akimm »

If I wanted to use it to append a specific link I would then use GET yes?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Not normally, instead you'd modify the string that contains the link that would have been displayed.
User avatar
akimm
Forum Contributor
Posts: 460
Joined: Thu Apr 27, 2006 10:50 am
Location: Ypsilanti Michigan, formally Clipsburgh

something like this?

Post by akimm »

Code: Select all

echo "<h2><a href=\"".$_SERVER['PHP_SELF']; 
        if ($part != $char) echo "?part=".$char; 
        echo "\">- ".$char." -</a></h2>\n"
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

I wouldn't get into a habit of using $_SERVER['PHP_SELF'] as it contains user input. This can lead to cross site scripting attacks.

$_SERVER contains several other elements that can be used to build effectively the same information that isn't dictated by user input.
User avatar
akimm
Forum Contributor
Posts: 460
Joined: Thu Apr 27, 2006 10:50 am
Location: Ypsilanti Michigan, formally Clipsburgh

ok

Post by akimm »

I'll check that superglobal on php.net. See if I can figure out how to do this. Thanks.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

I wouldn't get into a habit of using $_SERVER['PHP_SELF'] as it contains user input.
sure?
http://www.php.net/manual/en/reserved.variables.php wrote:'PHP_SELF'

The filename of the currently executing script, relative to the document root. For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar would be /test.php/foo.bar. The __FILE__ constant contains the full path and filename of the current (i.e. included) file.
User avatar
JayBird
Admin
Posts: 4524
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK
Contact:

Post by JayBird »

taken from elsewhere

A predominant PHP developer (whose name I didn't get permission to drop, so I won't, but many of you know who I mean) has been doing a bunch of research related to Cross Site Scripting (XSS), lately. It's really opened opened my eyes to how much I take user input for granted.

Don't get me wrong. I write by the "never trust users" mantra. The issue, in this case, is something abusable that completely slipped under my radar.

Most developers worth their paycheque, I'm sure, know the common rules of "never trust the user", such as "escape all user-supplied data on output," "always validate user input," and "don't rely on something not in your control to do so (ie. Javascript cannot be trusted)." "Don't output unescaped input" goes without saying, in most cases. Only a fool would "echo $_GET['param'];" (and we're all foolish sometimes, aren't we?).

The problem that was demonstrated to me exploited something I considered to be safe. The filename portion of request URI. Now I know just how wrong I was.

Consider this: you build a simple script; let's call it simple.php but that doesn't really matter. simple.php looks something like this:

Code: Select all

<html>
<body>
  <?php
  if (isset($_REQUEST['submitted']) && $_REQUEST['submitted'] == '1') {
    echo "Form submitted!";
  }
  ?>
  <form action="<?php echo $_SERVER['PHP_SELF']; ?>">
   <input type="hidden" name="submitted" value="1" />
   <input type="submit" value="Submit!" />
  </form>
</body>
</html>


Alright. Let's put this script at: http://example.com/tests/simple.php. On a properly-configured web server, you would expect the script to always render to this, on request:

Code: Select all

<html>
<body>
  <form action="/tests/simple.php">
   <input type="hidden" name="submitted" value="1" />
   <input type="submit" value="Submit!" />
  </form>
</body>
</html>
Right? No.

What I forgot about, as I suspect some of you have, too (or maybe I'm the only loser who didn't think of this (-; ), is that $_SERVER['PHP_SELF'] can be manipulated by the user.

How's that? If I put a script at /simple/test.php, $_SERVER['PHP_SELF'] should always be "/simple/test.php", right?

Wrong, again.

See, there's a feature of Apache (I think it's Apache, anyway) that you may have used for things like short URLs, or to optimize your query-string-heavy website to make it search-engine friendly. $_SERVER['PATH_INFO']-based URLs.

Quickly, this is when scripts are able to receive data in the GET string, but before the question mark that separates the file name from the parameters. In a URL like http://www.example.com/download.php/path/to/file, download.php would be

executed, and /path/to/file would (usually, depending on config) be available to the script via $_SERVER['PATH_INFO'].

The quirk is that $_SERVER['PHP_SELF'] contains this extra data, opening up the door to potential attack. Even something as simple the code above is vulnerable to such exploits.

Let's look at our simple.php script, again, but requested in a slightly different manner:
http://example.com/tests/simple.php/extra_data_here

It would still "work"--the output, in this case, would be:

Code: Select all

<html>
<body>
  <form action="/tests/simple.php/extra_data_here">
   <input type="hidden" name="submitted" value="1" />
   <input type="submit" value="Submit!" />
  </form>
</body>
</html>

I hope that the problem is now obvious. Consider:
http://example.com/tests/simple.php/%22 ... t%3E%3Cfoo

The output suddenly becomes very alarming:

Code: Select all

<html>
<body>
  <form action="/tests/simple.php/"><script>alert('xss')</script><foo">
   <input type="hidden" name="submitted" value="1" />
   <input type="submit" value="Submit!" />
  </form>
</body>
</html>

If you ignore the obviously-incorrect <foo"> tag, you'll see what's happening. The would-be attacker has successfully exploited a critical (if you consider XSS critical) flaw in your logic, and, by getting a user to click the link (even through a redirect script), he has executed the Javascript of his choice on your user's client (obviously, this requires the user to have Javascript enabled). My alert() example is non-malicious, but it's trivial to write similarly-invoked Javascript that changes the action of a form, or usurps cookies (and submits them in a hidden iframe, or through an image tag's URL, to a server that records this personal data).

The solution should also be obvious. Convert the user-supplied data to entities. The code becomes:

Code: Select all

<html>
<body>
  <?php
  if (isset($_REQUEST['submitted']) && $_REQUEST['submitted'] == '1') {
    echo "Form submitted!";
  }
  ?>
  <form action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
   <input type="hidden" name="submitted" value="1" />
   <input type="submit" value="Submit!" />
  </form>
</body>
</html>


And an attack, as above, would be rendered:

Code: Select all

<html>
<body>
  <form action="/tests/simple.php/"><script>alert('xss')</script><foo">
   <input type="hidden" name="submitted" value="1" />
   <input type="submit" value="Submit!" />
  </form>
</body>
</html>


This still violates the assumption that the script name and path are the only data in $_SERVER['PHP_SELF'], but the payload has been neutralized.

Needless to say, I felt silly for not thinking of such a simple exploit, earlier. As the aforementioned PHP developer said, at the time (to paraphrase): if guys who consider themselves experts in PHP development don't notice these things, there's little hope for the unwashed masses who have just written their first 'echo "hello world!\n";'. He's working on a generic user-input filtering mechanism that can be applied globally to all user input. Hopefully we'll see it in PECL, soon. Don't forget about the other data in $_SERVER, either..

... ...

Upon experimenting with this exploit on my own server (and watching the raw data in my _SUPERGLOBALS, conveniently, via phpinfo()), I noticed something very interesting that reminded me that even though trusting this data was a stupid mistake on my part, I'm not the only one to do so. A fun (and by fun, I mean nauseating) little game to play: create a file called "info.php" (or whatever name you like). In it, place only "<php phpinfo(); ?>". Now request it like this:
http://your-server/path/to/info.php/%22 ... %3E%3Cblah

Nice huh? A little less nauseating: it's fixed in CVS.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

oh boy 8O
am i happy i don't do web development anymore :)
mikesmith76
Forum Commoner
Posts: 34
Joined: Fri Aug 25, 2006 7:10 am
Location: Manchester, UK

Post by mikesmith76 »

well this thread has been an eye opener. So what data from $_SERVER can be trusted to provide the name of the currently executing script?

thanks
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

I prefer to set my action to # and avoid using SERVER variables at all costs, typically.
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

I had written a little function (before feyd taught me basename() ) that took the page based on $_SERVER['PHP_SELF'] and stripped everything out of it except the name of the page. If I can find it, I will post it for review/appreciation/condemnation. I never use $_SERVER['PHP_SELF'] by itself.

EDIT | Found it. I haven't tested this against XSS (nor have I tested basename() against XSS).

Code: Select all

<?php
function get_page_name($page_name = '')
{
	if ($page_name == '')
	{
		$page_name = $_SERVER['PHP_SELF'];
	}

	//This is added to handle page names with query strings
	if ( strpos($page_name, '?') )
	{
		$page_name = substr($page_name,0,(strlen($page_name)-strpos($page_name, '?')));
	}

	$page = substr($page_name,0,strlen($page_name)-4);
	$page_array = explode("/",$page);
	$page_array_index = count($page_array)-1;
	$page = $page_array[$page_array_index];

	return $page;
}
?>
Last edited by RobertGonzalez on Fri Sep 15, 2006 11:50 am, edited 1 time in total.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

Jcart wrote:I prefer to set my action to # and avoid using SERVER variables at all costs, typically.
that's what I do too
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

Does anyone have the link that timvw posted a ways back with all the various XSS strings to pass to a page? I was looking for that the other day and I cannot find it.
Post Reply