I've seen cookies set by web pages with the "." character in them. I'm trying to maximize the dynamic use of a $_GET['url'] to set my cookies, and then include it in a next page as a conditional where it checks to make sure the cookie was set before it allows users to perform an action. Basically I'm using cookies and IP addresses in an anonymous voting action to make sure anyone who votes only gets one per day. IPs are reset through a cron job once a day, and the cookies are set to expire after 17 hours. I have no issues setting a cookie named with the .php extension, however after many hours of trial and error, I can't get it to accept it in an if(isset). No matter what I try, it will not recognize that the cookie is set. Without the extension everything works fine. I've tried a dozen configurations, but here's basically what I have trying to debug.
<?php
$cookie = "test.php";
setcookie("$cookie", "workdamnyou");
if (isset($_COOKIE[$cookie])) {
echo "is set";
}
else {
echo "not set";
}
?>
I've tried isset($_COOKIE["$cookie"]) and isset($COOKIE['$cookie']) as well. That said, I really wish you could run PHP without uploading it each time to your server.. --
setcookie doesn't change $_COOKIE immediately. It sets the headers to change the cookie in the browser, so the script won't see the test value until you refresh the page.
You CAN run PHP without uploading to a server; the easiest option is to install a xAMP stack (LAMP/MAMP/WAMP depending on if you're developing on Linux/Mac/Windows).
Well, I found the solution I guess... PHP doesn't like dots in variable names (http://www.php.net/manual/en/language.variables.basics.php). Now, since Register Globals could be on, it might be possible that a $_COOKIE["name.ext"] could turn into a $name.ext which would be invalid. Thus, "Dots and spaces in variable names are converted to underscores. For example becomes $_REQUEST["a_b"]." (http://www.php.net/manual/en/language.variables.external.php). Does a check for isset("name_php") work?
You cannot set and access a cookie in the same instance! You have to do a redirect, refresh or something, but you cannot both set and access at the same time. Also make sure your other parameters are set like hostname, expiry time. . e.t.c
Eg.
setcookie("TestCookie", $value, time()+3600, "/", "/", 1);
For debugging, just do a var_dump($_COOKIE)
Note that cookies only become available on the next pageload (when they have traversed from server to client and back).
Try setting the cookie directly with $_COOKIES["test.php"] = "test"; and see what happens with
var_dump($_COOKIE);
Also don't use the quotes around the $cookie variable. Thus make it
setcookie($cookie, "work");
instead of
setcookie("$cookie", "work");
Last, you can run PHP locally with your own server. The easiest way on Windows is the WAMPP stack. I find this one very easy to install and run: http://www.apachefriends.org/en/xampp.html
Good luck!
Why would you have a .php extension in the cookie name? It should be:
$cookie = 'test';
See http://www.ietf.org/rfc/rfc2109.txt point 4.1:
The two state management headers, Set-Cookie and Cookie, have common
syntactic properties involving attribute-value pairs. The
following grammar uses the notation, and tokens DIGIT (decimal
digits) and token (informally, a sequence of non-special, non-white
space characters) from the HTTP/1.1 specification [RFC 2068] to
describe their syntax.
av-pairs = av-pair *(";" av-pair)
av-pair = attr ["=" value] ; optional value
attr = token
value = word
word = token | quoted-string
Attributes (names) (attr) are case-insensitive. White space is
permitted between tokens. Note that while the above syntax
description shows value as optional, most attrs require them.
NOTE: The syntax above allows whitespace between the attribute and
the = sign.
Related
I have an api logging system which records logins but I do not want to store passwords in the logs.
This is an example of a request string to the log:
NOTE: the string will not be exactly the same and will contain parameters in different order, so I am thinking maybe someREGEX can handle this?
api.my.geatapim/live/?action=login_user&username=joe#bloggs.com&password=PassWord&session_length=10080
What I need to do, is:
Detect if the parameter "password=" is in the string
If its in the string replace the password part with OBFUSCATED so result will be:
api.my.geatapim/live/?action=login_user&username=joe#bloggs.com&password=OBFUSCATED&session_length=10080
I have tried this but does not work: $request_string = preg_replace("/password=\d+/", "password=OBFUSCATED", $request_string);
The Expression
\d+ is for digits ([0-9]). You'll want to include more character sets for the password, considering the one you provided is using [A-Za-z].
$request_string = preg_replace("/password=\w+/", "password=OBFUSCATED", $request_string);
Though, considering a typical password will have a bigger character set than [a-zA-Z0-9_], taking into account special characters (but since it's in a URL, it'll possibly be urlencoded()'d. For example, P&ssW0rd! will become P%26ssW0rd!.)
$request_string = preg_replace("/password=[^&]+/", "password=OBFUSCATED", $request_string);
"I do not want to store passwords in the logs."
This logic won't modify what is put into your Apache/Nginx/Whatever access_log (unless you write these logs to /dev/null or another void place). You can also not write the passwords in the logs if you change it from a HTTP GET to a HTTP POST (or HTTP PUT) and have the credentials in the body, or, use HTTP Authentication headers.
Although your question is quite easy to solve, it has nothing to do with your actual problem. you simply should never transfer password data via $_GET - it's one of the big no no-s of handling credentials. — Franz Gleichmann
Try this code, it works
<?php
$request_string = "api.my.geatapim/live/?action=login_user&username=joe#bloggs.com&password=PassWord&session_length=10080";
echo $request_string = preg_replace("/password=\w+/", "password=OBFUSCATED", $request_string);
?>
Output : api.my.geatapim/live/?action=login_user&username=joe#bloggs.com&password=OBFUSCATED&session_length=10080
Thought this was super easy, but I've spent the last half hour trying to figure it out to no avail.
$unique_id = uniqid(microtime(),1);
if (is_null($_COOKIE['client_id']))
{
setcookie("client_id", $unique_id);
}
But when I go to check the cookie through $_COOKIE['client_id'], I get a null value. Any ideas whats going on?
Cookies have to be set before ANYTHING is outputted. also I've had many problems with cookies before.
Also, see Can't set cookies in PHP? for explanation why you cant check its existence at the same time as setting it.
The _COOKIE array is created when the script initializes, and is then left alone by PHP. Setting a cookie within the script will not magically add it to $_COOKIE. It will only show up on the next script request, or you manually assign it into $_COOKIE.
You should set cookie with
$_COOKIE['key'] = 'value';
Yeah FallingBullets has right. Be affraid when you use UTF8 file encoding - the first chars with is sent to client is UTF8 file head ( 0xEF 0xBB 0xBF). In this case is ob-start http://php.net/manual/en/function.ob-start.php not work (UTF8 file head is sent before ob-start).
What I describe is probably characteristic of the web server. Try save jour script in ascii encoding.
I made a .htaccess file that redirects, for example, link:
website.com/module#controller
to:
website.com/?url=module#controller
As # is the PHP comment declarer, I get a problem when need to load:
$bootstrap->init($url) // $url = module#controller;
I tried to use addslashees($url);, but still when I:
echo $url;
I still get an output of:
module
How I should clear that string, to treat the # sign as part of the string?
$url = module#controller; is not valid PHP.
$url = 'module#controller'; will (correctly) not treat the # as a comment initiator.
Additionally, a # in a URL isn't going to work the way you expect. That's the marker for the URL hash/anchor, which is not passed to the web server. This is likely why you get output of module - your problem is at the browser level, not PHP.
The hashtag fragment identifier is a client-side concept only. The browser would never send a hashtag value to the server.
If you are relying on this functionality, your are going to be disappointed as server has absolutely no way to do redirection based on the hashtag, as it never even sees the hashtag.
I'm using this code on top of my PHP file for loading cached files and I'm worried whether it's secure enough:
//quick! load from cache if exists!
if (is_file('cache/'.($cachefile=basename('/',$_GET['f']))))
{
header('content-type: text/css');
require('cache/'.$cachefile);
die(); //ALL OK, loaded from cache
}
EDIT: I would also like to know if it isn't, how is it exploitable and how to rewrite it in safe manner.
EDIT 2: I edited code, from previous code, I don't know how I could thought that is_file will filter bad paths >.<
EDIT 3: Changed it again, so it uses basename() instead of end(explode()) and also changed inclusion from repeating the code into assigning the value into variable during first comparison (or file check).
I never just include($_GET), but today, I somehow thought is_file will filter out paths, that may harm my system. I don't know how.
Thank you
I could send $_GET['f'] = '../../database_passwords.xml' ...
Use basename to eliminate anything but the last segment of the passed path. Alternatively, construct the path, then compute the absolute path that corresponds and check if it's still within cache/.
BAD!
What about:
page.php?f=../../../../../etc/password
Never do such things
Check f against a white list or specific pattern like "[a-z]+.php"
No it isn't. I could put '../../anypath' in $_GET['f'] and gain access to any file on your server, even those outside your www root.
[edit]
It would be a lot safer if you would check for '/' and other invalid characters in the value. It is pretty safe if that filename only contains alphanumeric characters and . and _.
Thought this was super easy, but I've spent the last half hour trying to figure it out to no avail.
$unique_id = uniqid(microtime(),1);
if (is_null($_COOKIE['client_id']))
{
setcookie("client_id", $unique_id);
}
But when I go to check the cookie through $_COOKIE['client_id'], I get a null value. Any ideas whats going on?
Cookies have to be set before ANYTHING is outputted. also I've had many problems with cookies before.
Also, see Can't set cookies in PHP? for explanation why you cant check its existence at the same time as setting it.
The _COOKIE array is created when the script initializes, and is then left alone by PHP. Setting a cookie within the script will not magically add it to $_COOKIE. It will only show up on the next script request, or you manually assign it into $_COOKIE.
You should set cookie with
$_COOKIE['key'] = 'value';
Yeah FallingBullets has right. Be affraid when you use UTF8 file encoding - the first chars with is sent to client is UTF8 file head ( 0xEF 0xBB 0xBF). In this case is ob-start http://php.net/manual/en/function.ob-start.php not work (UTF8 file head is sent before ob-start).
What I describe is probably characteristic of the web server. Try save jour script in ascii encoding.