I need to extract the cookie time from a cookie when a user visits the page. The cookie text will be stored in a variable. I'm pretty sure I can do this with preg_match or maybe strpos but I'm not sure how to structure the code. I'd appreciate any help.
The cookie text will look like this...
09/02-13:05 : Array
(
[_fbp] => fb.1.1739106196697.235924611659269905
[_fbc] => fb.1.1739106196727.IwZXh0bgNhZW0CMTAAAR3y6z47O2mW29lM1GoX2fijs4oYAehPYgcoxpSO2FiCv60XMF8MnxgSOJk_aem_KYAWfzaaJNjl06suPL6ExA
[_ga] => GA1.1.765488705.1739106207
[hash] => 96f5de6147cb0fdfbbcd97e7fb074294
[user] => 51895204
)
I want to return the 1739106196727 number from the line which starts with [_fbc]. This doesn't always appear in the 2nd line of the array.
Thanks
$_COOKIE
is an array, so you can access the entry with its key. But the cookie may
not be present, so you also have to check if it's there or not.
First, the regex to extract it: ^fb\.\d\.(\d+)
^fb
starting with "fb".\.
to match a dot (".").\d
to match a digit (actually the "1" after "fb.").\.
to match the dot after this number.( )
is a capturing group, n°1, accessible via $match[1]
. And here we would like
to match all the digits, so this will be (\d+)
, because +
means
"one or several times".Secondly, depending what you want to do with this number, you may want to convert it from string to integer. Be aware that this number is longer than an integer on a 32 bit system. So to be sure, check this before conversion.
Here's the PHP code I would use (here, I just did some prints in the console, but you'll probably do something else with it):
<?php
$_COOKIE = [
'_fbp' => 'fb.1.1739106196697.235924611659269905',
'_fbc' => 'fb.1.1739106196727.IwZXh0bgNhZW0CMTAAAR3y6z47O2mW29lM1GoX2fijs4oYAehPYgcoxpSO2FiCv60XMF8MnxgSOJk_aem_KYAWfzaaJNjl06suPL6ExA',
'_ga' => 'GA1.1.765488705.1739106207',
'hash' => '96f5de6147cb0fdfbbcd97e7fb074294',
'user' => 51895204
];
// If the _fbc cookie is present.
if (isset($_COOKIE['_fbc'])) {
// Try to extract the second number after "fb.1." (assuming 1 could be another digit).
if (preg_match('/^fb\.\d\.(\d+)/i', $_COOKIE['_fbc'], $match)) {
printf('$match = ' . var_export($match, true) . PHP_EOL);
// On 32 bit PHP, max int val is 2147483647.
// On 64 bit PHP, max int val is 9223372036854775807.
// The desired number is 1739106196727, which is higher than the max 32 bit value.
// So up to you to see if you want to keep it as a string, or convert it to
// an int number or a float number.
$number = intval($match[1]);
if (0 < $number && $number < PHP_INT_MAX)
printf('The desired number is %d' . PHP_EOL, $number);
else {
printf('ERROR: "%s" is out of the integer range!' . PHP_EOL, $match[1]);
printf(' PHP_INT_SIZE = %d bytes, so max value is %d' . PHP_EOL, PHP_INT_SIZE, PHP_INT_MAX);
printf(' Keep it as a string or save it as a float (with some risk).' . PHP_EOL);
}
} else {
printf('ERROR: Could not find the desired number in the cookie!' . PHP_EOL);
}
}
else {
printf('ERROR: The _fbc cookie does not exist!' . PHP_EOL);
}
Execution output:
$match = array (
0 => 'fb.1.1739106196727',
1 => '1739106196727',
)
The desired number is 1739106196727
You can test it here: https://onlinephp.io/c/7cff3
You mentionned in your comment below that you finally used this piece of PHP:
extract($_COOKIE);
$fbc = $_fbc;
This is very dangerous, because the $_COOKIE
array is sent by the
customer, who is anybody, including a potential attacker.
Imagine that your code is having a $user
variable containing "James".
You would like to print it in your HTML output. But, bad luck, you are
receiving the cookie user
(which is already the case in your example).
So instead of printing "Hello James", you'll print "Hello 51895204".
Now, if you receive a cookie called _COOKIE
, _GET
or _SERVER
,
the extract()
operation will ovewrite the global variables, leading to
big problems.
The $_COOKIE
array can contain anything. Cookies can be created by
JavaScript code in the browser or sent in the HTTP request with many
available browser extensions (tamper, request editors, cookie editors).
A safer alternative to extract()
is
array destructuring:
['_fbc' => $fbc] = $_COOKIE;
This will create a variable called $fbc
with the value of the entry
_fbc
of your $_COOKIE
array.
But the problem is that you'll get a warning if the key doesn't exist.
This is why I used isset($_COOKIE['_fbc'])
to check that it exists.
<script>alert('XSS attack')</script>
then
be sure you are printing it after using htmlspecialchars()
or
equivalent escaping or filtering functions.