Rectangle 27 17

str_replace(".php", "", basename($_SERVER["SCRIPT_NAME"]));
hey.php-i-am-a-weird-filename.php

I already thought of that but I figured they were using it for the single page mentioned in the question. You could also check to see if the ".php" is at the end of the string. Not saying your question is wrong but regular espressions can be kind of a pain in the ass and are usually used in scenarios where a much simpler and less resource intensive method could be used.

Shofner I ran some benchmarks and your way runs about twice as quick, but still over 1000 iterations the difference is 0.003231 microseconds.

php - Get the current script file name - Stack Overflow

php file
Rectangle 27 72

Recommended using HTTP_HOST, and falling back on SERVER_NAME only if HTTP_HOST was not set. He said that SERVER_NAME could be unreliable on the server for a variety of reasons, including:

Great answer. Thanks for adding the highlights from the article here.

HTTP_HOST seems right to me. SERVER_NAME worked fine until we started using Docker, then just gave us "localhost". Just note that HTTP_HOST will give you the sub-domain too.

PHP get domain name - Stack Overflow

php domain-name
Rectangle 27 70

Recommended using HTTP_HOST, and falling back on SERVER_NAME only if HTTP_HOST was not set. He said that SERVER_NAME could be unreliable on the server for a variety of reasons, including:

Great answer. Thanks for adding the highlights from the article here.

HTTP_HOST seems right to me. SERVER_NAME worked fine until we started using Docker, then just gave us "localhost". Just note that HTTP_HOST will give you the sub-domain too.

PHP get domain name - Stack Overflow

php domain-name
Rectangle 27 14

I just recently encountered the same problem because some code I had that was masking the same problem had gotten in the way.

My diagnosis of the problem is as follows: This is a quirk of a change made in Apache 2.0. The Port directive is no longer part of the httpd.conf directives, essentially split up between the ServerName and Listen directives.

ServerName myservername.com
Listen: 5150

Yet PHP $_SERVER['SERVER_PORT'] was returning 80 to all requests being made on port 5150.

So poring over the Apache docs, I found a tidbit about Port being a deprecated directive and ServerName subsuming it.

ServerName myservername.com:5150
UseCanonicalName On
Listen 5150

and suddenly the php script was doing the right thing, reporting _SERVER['SERVER_PORT'] as 5150.

ServerName myservername.com
UseCanonicalName Off
Listen 5150

So then I dug into the php (5.3.20) source code and the apache source code until I found the source of the behavior.

dirOfApacheSource/server/core.c
AP_DECLARE(apr_port_t) ap_get_server_port(const request_rec *r)

Here you will see that if your httpd UseCanonicalName directive is set to "On" then port gets parsed out of the ServerName directive. When the ServerName directive is not of the form ServerName myserver.com:myport number, the case code will fetch an ap_default_port of the request object (which is kindly set to default to 80 by the apache folks).

If it bothers you that you need to add the port explicitly to the ServerName directive in httpd.conf, your other choice is to set the UseCanonicalName to "Off", this forces the code in server/core.c to parse the URI request to extract the servername and port.

Six of one, half a dozen of the other, tweak your apache httpd.conf file and you will soon see the expected results.

UseCanonicalName On
UseCanonicalPhysicalPort On

I'm working with Apache configured for Plain & TLS on default ports and the Symfony2 PHP framework. I had Apache telling me its http port was 443 (which, of course, was wrong: that was it's https Port). UseCanonicalPhysicalPort On solved my problem, so big fat +1!! :)

php - Incorrect port number returned by $_SERVER['server_port'] - Stac...

php ssl
Rectangle 27 8

function getClientIP() {

    if (isset($_SERVER)) {

        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
            return $_SERVER["HTTP_X_FORWARDED_FOR"];

        if (isset($_SERVER["HTTP_CLIENT_IP"]))
            return $_SERVER["HTTP_CLIENT_IP"];

        return $_SERVER["REMOTE_ADDR"];
    }

    if (getenv('HTTP_X_FORWARDED_FOR'))
        return getenv('HTTP_X_FORWARDED_FOR');

    if (getenv('HTTP_CLIENT_IP'))
        return getenv('HTTP_CLIENT_IP');

    return getenv('REMOTE_ADDR');
}

i mean what's the point.. doesn't getenv give you the same thing as $_SERVER ?

@Paceriermy guess would be older versions of PHP where $_SERVER was not yet available ;)

@Johan Why not just return an array with all three?

@nueverest Because a user doesn't access your site from 3 different IPs (usually). You want to return the one that applies to him.

environment variables - How to get the client IP address in PHP? - Sta...

php environment-variables ip-address
Rectangle 27 2

$_SERVER['SCRIPT_FILENAME']
header.php
<?php
if($_SERVER['SCRIPT_FILENAME'] == 'header.php') {
    exit();
}

html - How to make page blank when user access php file directly? - St...

php html
Rectangle 27 24

1. Check the ORIGIN header

As specified by OWASP, this is not enough but recommended :

Although it is trivial to spoof any header from your own browser, it is generally impossible to do so in a CSRF attack, except via an XSS vulnerability. That's why checking headers is a reasonable first step in your CSRF defense, but since they aren't always present, its generally not considered a sufficient defense on its own.

The Origin header is considered helpful against JSON data theft and CSRF attacks. The information provided by Origin--a bit of contextual request-creation information--should provide hints to web servers about trustworthiness of requests [...]

Checking the HTTP_ORIGIN header could be written as :

header('Content-Type: application/json');

if (isset($_SERVER['HTTP_ORIGIN'])) {
    $address = 'http://' . $_SERVER['SERVER_NAME'];
    if (strpos($address, $_SERVER['HTTP_ORIGIN']) !== 0) {
        exit(json_encode([
            'error' => 'Invalid Origin header: ' . $_SERVER['HTTP_ORIGIN']
        ]));
    }
} else {
    exit(json_encode(['error' => 'No Origin header']));
}

1. (bis) Check the REFERER header

If the Origin header is not present, verify the hostname in the Referer header matches the site's origin. Checking the referer is a commonly used method of preventing CSRF on embedded network devices because it does not require a per-user state.. This method of CSRF mitigation is also commonly used with unauthenticated requests [...]

Checking the HTTP_REFERER is also quite simple in PHP with $_SERVER['HTTP_REFERER'], you can just update the above code with it.

BE CAREFUL with the checking which always need to be really specific : do no check just example.com or api.example.com but the full https://example.com. Why ? Because you could spoof this check with an origin like api.example.com.hacker.com.

  • Generate the token : session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); }

Add it in your generated views via a meta (like Github) :

<meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?>">
  • Setup jQuery ajax calls to include this token : $.ajaxSetup({ headers : { 'CsrfToken': $('meta[name="csrf-token"]').attr('content') } });
  • Server-side check your AJAX requests : session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } header('Content-Type: application/json'); $headers = apache_request_headers(); if (isset($headers['CsrfToken'])) { if ($headers['CsrfToken'] !== $_SESSION['csrf_token']) { exit(json_encode(['error' => 'Wrong CSRF token.'])); } } else { exit(json_encode(['error' => 'No CSRF token.'])); }

Most PHP frameworks have their own CSRF implementation, which more or less lay upon the same principle.

As @blue112 said, it is one of the most elementary security principles.

X-Requested-With is a non-standard header which never tells you what URL initiated the request. That's Origin, which is easily forged if the attacker isn't doing a CSRF attack.

I had to change the session array key to "Csrf-Token", otherwise it got renamed on my server to "Csrftoken" in the apache headers.

openssl_random_pseudo_bytes()

@wpcoder I'm not an expert in cryptographic security. However the PHP official documentation and some googling tells me that "pseudo-random" is less random than "cryptographic random". Moreover, Symfony and Laravel (based on Foundation) are also both using random_bytes.

javascript - How to send secure AJAX requests with PHP and jQuery - St...

javascript php jquery ajax security
Rectangle 27 23

Nothing will be perfect. If you just want something to stop non-programmers then here's a little script I wrote you can use:

<?php
$infile=$_SERVER['argv'][1];
$outfile=$_SERVER['argv'][2];
if (!$infile || !$outfile) {
    die("Usage: php {$_SERVER['argv'][0]} <input file> <output file>\n");
}
echo "Processing $infile to $outfile\n";
$data="ob_end_clean();?>";
$data.=php_strip_whitespace($infile);
// compress data
$data=gzcompress($data,9);
// encode in base64
$data=base64_encode($data);
// generate output text
$out='<?ob_start();$a=\''.$data.'\';eval(gzuncompress(base64_decode($a)));$v=ob_get_contents();ob_end_clean();?>';
// write output text
file_put_contents($outfile,$out);

Awesome? Every page comes with the complete solution to getting the source: run "gzuncompress(base64_decode($a))". Yes, this will stop non-programmers. But then the original source code will stop non-programmers, who needs encoding for that? The only person who is going to look at this intending to reverse engineer it is a PHP programmer.

Most of the time non-programmers try by search some strings in source code that they want to change, i am also looking for such a solution that only stop non programmers from change in source code e.g. domain name, database name, users etc.

This is a very helpful answer for me. I'm only interested in preventing the user from easily opening my "database.php" in notepad and seeing my database username and password.

obfuscation - Is there a code obfuscator for PHP? - Stack Overflow

php obfuscation
Rectangle 27 22

1. Check the ORIGIN header

As specified by OWASP, this is not enough but recommended :

Although it is trivial to spoof any header from your own browser, it is generally impossible to do so in a CSRF attack, except via an XSS vulnerability. That's why checking headers is a reasonable first step in your CSRF defense, but since they aren't always present, its generally not considered a sufficient defense on its own.

The Origin header is considered helpful against JSON data theft and CSRF attacks. The information provided by Origin--a bit of contextual request-creation information--should provide hints to web servers about trustworthiness of requests [...]

Checking the HTTP_ORIGIN header could be written as :

header('Content-Type: application/json');

if (isset($_SERVER['HTTP_ORIGIN'])) {
    $address = 'http://' . $_SERVER['SERVER_NAME'];
    if (strpos($address, $_SERVER['HTTP_ORIGIN']) !== 0) {
        exit(json_encode([
            'error' => 'Invalid Origin header: ' . $_SERVER['HTTP_ORIGIN']
        ]));
    }
} else {
    exit(json_encode(['error' => 'No Origin header']));
}

1. (bis) Check the REFERER header

If the Origin header is not present, verify the hostname in the Referer header matches the site's origin. Checking the referer is a commonly used method of preventing CSRF on embedded network devices because it does not require a per-user state.. This method of CSRF mitigation is also commonly used with unauthenticated requests [...]

Checking the HTTP_REFERER is also quite simple in PHP with $_SERVER['HTTP_REFERER'], you can just update the above code with it.

BE CAREFUL with the checking which always need to be really specific : do no check just example.com or api.example.com but the full https://example.com. Why ? Because you could spoof this check with an origin like api.example.com.hacker.com.

  • Generate the token : session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); }

Add it in your generated views via a meta (like Github) :

<meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?>">
  • Setup jQuery ajax calls to include this token : $.ajaxSetup({ headers : { 'CsrfToken': $('meta[name="csrf-token"]').attr('content') } });
  • Server-side check your AJAX requests : session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } header('Content-Type: application/json'); $headers = apache_request_headers(); if (isset($headers['CsrfToken'])) { if ($headers['CsrfToken'] !== $_SESSION['csrf_token']) { exit(json_encode(['error' => 'Wrong CSRF token.'])); } } else { exit(json_encode(['error' => 'No CSRF token.'])); }

Most PHP frameworks have their own CSRF implementation, which more or less lay upon the same principle.

As @blue112 said, it is one of the most elementary security principles.

X-Requested-With is a non-standard header which never tells you what URL initiated the request. That's Origin, which is easily forged if the attacker isn't doing a CSRF attack.

I had to change the session array key to "Csrf-Token", otherwise it got renamed on my server to "Csrftoken" in the apache headers.

openssl_random_pseudo_bytes()

@wpcoder I'm not an expert in cryptographic security. However the PHP official documentation and some googling tells me that "pseudo-random" is less random than "cryptographic random". Moreover, Symfony and Laravel (based on Foundation) are also both using random_bytes.

javascript - How to send secure AJAX requests with PHP and jQuery - St...

javascript php jquery ajax security
Rectangle 27 3

http://localhost/%3C?php%20echo%20$_SERVER['PHP_SELF'];%20?%3E

Then your PHP is not getting parsed. Your HTML form contains the raw PHP code as its destination, so of course you're getting access failure a few factors may be contributing to your getting 403, not 404.

php - Weird 403 Forbidden: You don't have permission to access /< on t...

php html wamp
Rectangle 27 1

I found a great solution to this in the related apache bug report: Simply add the following line to your apache configuration inside the VirtualDocumentRoot vhost definition:

php_admin_value auto_prepend_file /path/setdocroot.php

Then, create the referenced PHP file, and put set this as its contents:

<?php
$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

Now, every page load has this file executed, which properly sets DOCUMENT_ROOT.

php - VirtualDocumentRoot works well but does not make any change to $...

php apache config
Rectangle 27 187

REST in PHP can be done pretty simple. Create http://example.com/test.php (outlined below). Use this for REST calls, e.g. http://example.com/test.php/testing/123/hello. This works with Apache and Lighttpd out of the box, and no rewrite rules are needed.

<?php
$method = $_SERVER['REQUEST_METHOD'];
$request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    do_something_with_put($request);  
    break;
  case 'POST':
    do_something_with_post($request);  
    break;
  case 'GET':
    do_something_with_get($request);  
    break;
  case 'HEAD':
    do_something_with_head($request);  
    break;
  case 'DELETE':
    do_something_with_delete($request);  
    break;
  case 'OPTIONS':
    do_something_with_options($request);    
    break;
  default:
    handle_error($request);  
    break;
}

If you want to have your API available, without quoting what interpreting engine you're using, add a .htaccess file containing RewriteEngine on RewriteRule ^api/(.*)$ api.php/$1 This assumes your API file is called api.php. Also, since the above code block was written, the PHP developers have depreciated the split function. it works fine if you replace split with explode.

$_SERVER['PATH_INFO']

@Svish, what a great detail you noticed! It gets rid of PHP Notice: Undefined index: PATH_INFO in case PATH_INFO is not in $_SERVER. I'm adding this to my bag of tricks right away! It's a way of saying "I know there might not be an entry named that way in this array, and I'm ready for that, so just shut up and do what I tell you to". :) Thanks guys, both for posting this answer and for bringing my attention to that particular character in it.

I usually use a !empty instead of @. Better practice?

<?php     $request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));     $rest = 'rest_'.strtolower($_SERVER['REQUEST_METHOD']);     if (function_exists($rest))      call_user_func($rest, $request);     ?>

Detecting request type in PHP (GET, POST, PUT or DELETE) - Stack Overf...

php request
Rectangle 27 10

In PHP every $_SERVER variable starting with HTTP_ can be influenced by the user. For example the variable $_SERVER['HTTP_REINERS'] can be tainted by setting the HTTP header REINERS to an arbitrary value in the HTTP request.

php - Which $_SERVER variables are safe? - Stack Overflow

php security
Rectangle 27 10

In PHP every $_SERVER variable starting with HTTP_ can be influenced by the user. For example the variable $_SERVER['HTTP_REINERS'] can be tainted by setting the HTTP header REINERS to an arbitrary value in the HTTP request.

php - Which $_SERVER variables are safe? - Stack Overflow

php security
Rectangle 27 11

You can identify which button was used provided you structure your HTML correctly

<input type="submit" name="action" value="Edit">
<input type="submit" name="action" value="Preview">
<input type="submit" name="action" value="Post">

The $_POST array (or $_GET/$_REQUEST) will contain the key "action" with the value of the enacted button (whether clicked or not).

Now, "clicking" is explicitly a client-side behavior - if you want to differentiate between a click and a keypress, you'll need to add some scripting to your form to aid in that determination.

Alternatively, you can be "sneaky" and use a hidden submit that should correctly identify a key-pressed for submission, but this probably has some significant impact on accessibility.

<?php

if ( 'POST' == $_SERVER['REQUEST_METHOD'] )
{
    echo '<pre>';
    print_r( $_POST );
    echo '</pre>';
}

?>
<form method="post">

    <input type="text" name="test" value="Hello World">

    <input type="submit" name="action" value="None" style="display: none">
    <input type="submit" name="action" value="Edit">
    <input type="submit" name="action" value="Preview">
    <input type="submit" name="action" value="Post">

</form>

This only works when you click on the button. It doesn't work when you press Enter in one of the text inputs.

Um... yes it does. The first one by source-order will be "chosen" by the browser as the submit actor.

Yes chosen by the browser, not the user.

Roberto, the first submit-button in the source is chosen when enter is pressed. Thus the user chooses it by pressing enter whether they know it or not.

Well, first of all, if you don't have accessibility as part of your current requirements, don't worry about it. It's silly to address it with a single feature of your site but ignore it everywhere else in your structure. And secondly - I'm not sure. I'm not an accessibility expert - I'm just very cautious of "clever" solutions to web problems because they very often cause troubles for those types of audiences.

forms - How can PHP determine if user pressed Enter key or Submit butt...

php forms submit form-submit
Rectangle 27 6

You could just let Apache think SSL is on by setting the environment variable (in PHP logic $_SERVER['HTTPS'])

SetEnvIf X-Forwarded-Proto https HTTPS=On

This works great when you need to support a bunch of different legacy apps and don't want to break upgradability by changing the way they check for HTTPS. +1

apache - Redirect Loop in PHP behind a Load Balancer with SSL - Stack ...

php apache redirect header
Rectangle 27 4

you have used an absolute path in your code, so PHP acts right.

write a simple code and take a look at $_SERVER variable:

<?php
echo '<xmp>';
print_r($_SERVER);
echo '</xmp>';
?>

you'll find appropriate key to use in your code. before the log.log

in my case that would be like this:

<?php

$sRoot = $_SERVER['DOCUMENT_ROOT'];

$fp = fopen($sRoot . '/log.log', 'w');

?>

path relative to document root in PHP - Stack Overflow

php relative-path fopen
Rectangle 27 187

REST in PHP can be done pretty simple. Create http://example.com/test.php (outlined below). Use this for REST calls, e.g. http://example.com/test.php/testing/123/hello. This works with Apache and Lighttpd out of the box, and no rewrite rules are needed.

<?php
$method = $_SERVER['REQUEST_METHOD'];
$request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    do_something_with_put($request);  
    break;
  case 'POST':
    do_something_with_post($request);  
    break;
  case 'GET':
    do_something_with_get($request);  
    break;
  case 'HEAD':
    do_something_with_head($request);  
    break;
  case 'DELETE':
    do_something_with_delete($request);  
    break;
  case 'OPTIONS':
    do_something_with_options($request);    
    break;
  default:
    handle_error($request);  
    break;
}

If you want to have your API available, without quoting what interpreting engine you're using, add a .htaccess file containing RewriteEngine on RewriteRule ^api/(.*)$ api.php/$1 This assumes your API file is called api.php. Also, since the above code block was written, the PHP developers have depreciated the split function. it works fine if you replace split with explode.

$_SERVER['PATH_INFO']

@Svish, what a great detail you noticed! It gets rid of PHP Notice: Undefined index: PATH_INFO in case PATH_INFO is not in $_SERVER. I'm adding this to my bag of tricks right away! It's a way of saying "I know there might not be an entry named that way in this array, and I'm ready for that, so just shut up and do what I tell you to". :) Thanks guys, both for posting this answer and for bringing my attention to that particular character in it.

I usually use a !empty instead of @. Better practice?

<?php     $request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));     $rest = 'rest_'.strtolower($_SERVER['REQUEST_METHOD']);     if (function_exists($rest))      call_user_func($rest, $request);     ?>

Detecting request type in PHP (GET, POST, PUT or DELETE) - Stack Overf...

php request
Rectangle 27 187

REST in PHP can be done pretty simple. Create http://example.com/test.php (outlined below). Use this for REST calls, e.g. http://example.com/test.php/testing/123/hello. This works with Apache and Lighttpd out of the box, and no rewrite rules are needed.

<?php
$method = $_SERVER['REQUEST_METHOD'];
$request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    do_something_with_put($request);  
    break;
  case 'POST':
    do_something_with_post($request);  
    break;
  case 'GET':
    do_something_with_get($request);  
    break;
  case 'HEAD':
    do_something_with_head($request);  
    break;
  case 'DELETE':
    do_something_with_delete($request);  
    break;
  case 'OPTIONS':
    do_something_with_options($request);    
    break;
  default:
    handle_error($request);  
    break;
}

If you want to have your API available, without quoting what interpreting engine you're using, add a .htaccess file containing RewriteEngine on RewriteRule ^api/(.*)$ api.php/$1 This assumes your API file is called api.php. Also, since the above code block was written, the PHP developers have depreciated the split function. it works fine if you replace split with explode.

$_SERVER['PATH_INFO']

@Svish, what a great detail you noticed! It gets rid of PHP Notice: Undefined index: PATH_INFO in case PATH_INFO is not in $_SERVER. I'm adding this to my bag of tricks right away! It's a way of saying "I know there might not be an entry named that way in this array, and I'm ready for that, so just shut up and do what I tell you to". :) Thanks guys, both for posting this answer and for bringing my attention to that particular character in it.

I usually use a !empty instead of @. Better practice?

<?php     $request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));     $rest = 'rest_'.strtolower($_SERVER['REQUEST_METHOD']);     if (function_exists($rest))      call_user_func($rest, $request);     ?>

Detecting request type in PHP (GET, POST, PUT or DELETE) - Stack Overf...

php request
Rectangle 27 187

REST in PHP can be done pretty simple. Create http://example.com/test.php (outlined below). Use this for REST calls, e.g. http://example.com/test.php/testing/123/hello. This works with Apache and Lighttpd out of the box, and no rewrite rules are needed.

<?php
$method = $_SERVER['REQUEST_METHOD'];
$request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    do_something_with_put($request);  
    break;
  case 'POST':
    do_something_with_post($request);  
    break;
  case 'GET':
    do_something_with_get($request);  
    break;
  case 'HEAD':
    do_something_with_head($request);  
    break;
  case 'DELETE':
    do_something_with_delete($request);  
    break;
  case 'OPTIONS':
    do_something_with_options($request);    
    break;
  default:
    handle_error($request);  
    break;
}

If you want to have your API available, without quoting what interpreting engine you're using, add a .htaccess file containing RewriteEngine on RewriteRule ^api/(.*)$ api.php/$1 This assumes your API file is called api.php. Also, since the above code block was written, the PHP developers have depreciated the split function. it works fine if you replace split with explode.

$_SERVER['PATH_INFO']

@Svish, what a great detail you noticed! It gets rid of PHP Notice: Undefined index: PATH_INFO in case PATH_INFO is not in $_SERVER. I'm adding this to my bag of tricks right away! It's a way of saying "I know there might not be an entry named that way in this array, and I'm ready for that, so just shut up and do what I tell you to". :) Thanks guys, both for posting this answer and for bringing my attention to that particular character in it.

I usually use a !empty instead of @. Better practice?

<?php     $request = explode("/", substr(@$_SERVER['PATH_INFO'], 1));     $rest = 'rest_'.strtolower($_SERVER['REQUEST_METHOD']);     if (function_exists($rest))      call_user_func($rest, $request);     ?>

Detecting request type in PHP (GET, POST, PUT or DELETE) - Stack Overf...

php request