get http url parameter without auto decoding using PHP - php

I have a url like
test.php?x=hello+world&y=%00h%00e%00l%00l%00o
when i write it to file
file_put_contents('x.txt', $_GET['x']); // -->hello world
file_put_contents('y.txt', $_GET['y']); // -->\0h\0e\0l\0l\0o
but i need to write it to without encoding
file_put_contents('x.txt', ????); // -->hello+world
file_put_contents('y.txt', ????); // -->%00h%00e%00l%00l%00o
how can i do?
Thanks

You can get unencoded values from the $_SERVER["QUERY_STRING"] variable.
function getNonDecodedParameters() {
$a = array();
foreach (explode ("&", $_SERVER["QUERY_STRING"]) as $q) {
$p = explode ('=', $q, 2);
$a[$p[0]] = isset ($p[1]) ? $p[1] : '';
}
return $a;
}
$input = getNonDecodedParameters();
file_put_contents('x.txt', $input['x']);

Because the The $_GET and $_REQUEST superglobals are automatically run through a decoding function (equivalent to urldecode()), you simply need to re-urlencode() the data to get it to match the characters passed in the URL string:
file_put_contents('x.txt', urlencode($_GET['x'])); // -->hello+world
file_put_contents('y.txt', urlencode($_GET['y'])); // -->%00h%00e%00l%00l%00o
I've tested this out locally and it's working perfectly. However, from your comments, you might want to look at your encoding settings as well. If the result of urlencode($_GET['y']) is %5C0h%5C0e%5C0l%5C0l%5C0o then it appears that the null character that you're passing in (%00) is being interpreted as a literal string "\0" (like a \ character concatenated to a 0 character) instead of correctly interpreting the \0 as a single null character.
You should have a look at the PHP documentation on string encoding and ASCII device control characters.

i think you can use urlencode() to pass the value in URL and urldecode() to get the value.

Related

How can I convert this string into a human readable IP address in PHP?

I've got a string representing an IPv4 address:
$ip = '\x7F\0\0\x01';
When I try to pass that to inet_ntop($ip) it's giving me grief:
PHP Warning: inet_ntop(): Invalid in_addr value
If I declare the variable manually using double quotes it works:
$ip = "\x7F\0\0\x01";
inet_ntop($ip); // "127.0.0.1"
However, I am not declaring these variables manually. I'm working with what is given to me in an object.
How can I convert '\x7F\0\0\x01' into a string that inet_ntop() will accept?
In other words, how can I make PHP parse a string literally as if I were manually declaring it with double quotes?
Some interesting facts:
gettype('\x7F\0\0\x01'); // string
gettype("\x7F\0\0\x01"); // string
ord('\x7F\0\0\x01'); // 92
ord("\x7F\0\0\x01"); // 127
implode(unpack('H*', '\x7F\0\0\x01')); // 5c7837465c305c305c783031
implode(unpack('H*', "\x7F\0\0\x01")); // 7f000001
mb_detect_encoding('\x7F\0\0\x01'); // ASCII
mb_detect_encoding("\x7F\0\0\x01"); // UTF-8
"\x7F\0\0\x01" == '\x7F\0\0\x01'; // false
// and for the haters
long2ip('\x7F\0\0\x01'); // PHP Warning: long2ip() expects parameter 1 to be integer, string given
One possibility is to parse the string into its component pieces (starting with \); convert them to the decimal equivalent and use chr to get back the original characters. These can then be joined into a string which is suitable for inet_ntop:
$ip = '\x7F\0\0\x01';
preg_match_all('/\\\x?([\dA-F]+)/', $ip, $parts);
$ip = implode('', array_map(function ($v) { return chr(hexdec($v)); }, $parts[1]));
echo inet_ntop($ip);
Another alternative is to use pack, after stripping out the \x parts and replacing \0 with 00:
$ip = '\x7F\0\0\x01';
$ip = pack('H*', str_replace(array('\x', '\0'), array('', '00'), $ip));
echo inet_ntop($ip);
In both cases the output is:
127.0.0.1
Demo on 3v4l.org
The problem is that you've got the literal ASCII output of a binary string and not the real binary value you expect it to be. I'm not sure how you got the literal ASCII value. There is a way to convert it, but you're not going to like it.
You can use eval() to accomplish what you're trying to do. All arguments for eval() being evil still apply.
$ip = '\x7F\0\0\x01';
eval("\$ip = \"$ip\";");
echo inet_ntop($ip);
This will print out 127.0.0.1.
Since binary doesn’t always result in literal ASCII characters, I worry you’ll see literal characters like � in the strings, and these won’t convert properly to the binary value you expect them to be.
For example, here are the characters printed to screen in Psysh:
>>> hex2bin('7f000001') // This is 127.0.0.1
=> "\x7F\0\0\x01"
>>> hex2bin('ffffffff') // This is 255.255.255.255
=> b"ÿÿÿÿ"
The first value looks familiar, right? That's the string literal that we can convert back into a binary string using eval(), like we did in the example above. But the binary value for ffffffff is a different story. If we try to convert it, it doesn't give us the 255.255.255.255 value we expect.
$ip = 'ÿÿÿÿ';
eval("\$ip = \"$ip\";");
echo inet_ntop($ip);
In this case, inet_ntop() returns false, but we know it should work:
>>> inet_ntop(hex2bin('ffffffff'));
=> "255.255.255.255"
So, I worry that any attempt to convert these values from string literals into binary strings is not going to work in all cases, whether using eval() or any of the other answers provided here.
However, if everything is coming to you in the format \0\0\0\0, where each "segment" is either a zero or a hex value in the format x00, then you should be in good shape, because these are the same:
>>> "\xFF\xFF\xFF\xFF"
=> b"ÿÿÿÿ"
You can make your own function like this
function convertStringToInAddr(string $string) {
$return = null;
$exploded = explode("\\", $string);
foreach($exploded as $hex) {
if( $hex != "" ) {
$return .= chr(hexdec(str_replace("x", "", $hex)));
}
}
return $return;
}

PHP Issue with $_GET

I'm having a really weird problem with a $_GET var.
This is my code :
if(isset($_GET['offer'])) {
$params = array();
$params['wifi'] = "%wifi%";
$params['publisher'] = "%pubid%";
$params['framework'] = "%framework%";
$params['date'] = "%cachebuster%";
foreach($params as $key=>$param){
$array[$_GET[$key]] = $_GET[$key];
}
print_r($array);
}
This is the URL i'm sending :
http://example.com/track/?offer=g58fFPK49fk4&click_id=%guid%&wifi=%wifi%&publisher=%pubid%&framework=%framework%&date=%cachebuster%
And this is the weird output I get :
Array ( [%wifi%] => %wifi% [%pubid%] => %pubid% [%framework%] => %framework% [Êchebuster%] => Êchebuster% )
Why does %cachebuster% turn into Êchebuster% ?
Percent signs in URLs escape special characters. The url seems to be interpreted as ISO 8869-I, and in that character set, ca is the code for Ê.
You should change the url to properly escape % as %25:
http://example.com/track/?offer=g58fFPK49fk4&click_id=%25guid%25&wifi=%25wifi%25&publisher=%25pubid%25&framework=%25framework%25&date=%25cachebuster%25
Because %ca is the url-encoded form of Ê (0xCA)
% should be encoded as %25.
It's interesting that %wifi% works... I would have expected it to return 400 Bad Request for that...
While dealing with "%" character, we should use php function
//should be used for encoding URL
urlencode()
//should be used for decoding URL
urldecode()
Checkout php documentation in below link:
http://php.net/manual/en/function.urlencode.php

Pass HEX value in PHP use GET method

If i have some code in index.php
if ($_GET['x']==="\x01\x03\x03\x07")
{
echo 'OK';
}
So, how i could pass value x in url index.php?x=??? to get output 'OK'.
Thanks!
so, url must be like this:
... index.php?x=\x01\x03\x03\x07
and your $_GET must be like this:
$_GET['x'] = "\\x01\\x03\\x03\\x07";
It will return "OK"
To compare '\x01\x03\x03\x07'(hex value) with variable x that you sent in the url, first you have to change '\x01\x03\x03\x07' to '\\x01\\x03\\x03\\x07'. Why ? because if you don't double the '\' you won't be able to compare these.
So, you have to place the hex in a variable like this:
$hex = "\x01\x03\x03\x07";
and you will compare 'x' with edited $hex (the value be "\\x01\\x03\\x03\\x07").
to make edited/fixed $hex we have to use a function, str_ireplace().
here's the example:
$hex = "\x01\x03\x03\x07";
$hex_able_to_compare = "\\x01\\x03\\x03\\x07";
$fixed = str_ireplace($hex,$hex_able_to_compare,$hex);
if ($_GET['x'] == $fixed){
echo "OK!";
}
else {
echo "Not OK!";
}
So you can still compare your hex with place your hex to $hex variable.
But the problem is: what if the the hex value is dynamic? we should make the value of $hex_able_to_compare as dynamic too,. :D
To passing the hex value in URL you need character "%" before hex code. For example, %20 stand for space character.
So URL you need is:
index.php/x=%01%03%03%07
You can references HTML URL Encode here
P/s: I think you are playing ctf.wargamevn.vn ;))

Stop PHP from decoding my url parameter

I'm sending comma separated values through a URL (key, value). I'm encoding them with Javascript's escape() and then replacing the commas within each value with %2c . The problem is at the PHP end the commas that are encoded are turned into "," BEFORE explode() takes place and then my string containing commas is broken up and it doesn't save right.
How can I stop PHP from converting my encoded bits back into unencoded bits?
My JS for each input is:
fieldData += $(this).attr("id")+","+escape($(this).html()).replace(/,/g,"%2c")+",";
My PHP is:
$fieldData = explode(",", $_POST['fieldData']);
Tried (along with other things):
$fieldData = explode(",", urlencode($_POST['fieldData']));
I would suggest using base64encode/decode for this.
The javascript would look something like this: http://jsfiddle.net/Y6yuN/
<script src='http://javascriptbase64.googlecode.com/svn/trunk/base64.js'></script>
fieldData += $(this).attr("id")+","+escape(Base64.encode($(this).html()))+",";
The escape is for the trailing =
So you would end up with comma delimited base64 encoded strings.
On the PHP side:
$fieldData = explode(",", $_POST['fieldData']);
foreach ($fieldData as $k => $v){
$fieldData[$k] = base64_decode(urldecode($v));
}
Your post is not really well explained, but I think you want to decode the data passed by JS. So, the code should be:
$fieldData = explode(",", urldecode($_POST['fieldData']));
Try to write it better if I am wrong!

PHP regex issue: cannot find $C

I'm trying to parse dollar amounts from a text of in mixed French (Canadian) and English. The text is in UTF-8. They use $C to denote currency. For some reason when I use preg_match neither the '$' nor the 'C' can be found. Everything else works fine. Any ideas?
e.g. use
preg_match_all('/\$C/u', $match)
on "Thanks for a payment of 46,00 $C" returns empty.
I think the regex can't find those characters because they aren't there. If you initialize the string like this:
$source = "Thanks for a payment of 46,00 $C";
...(i.e., as a double-quoted string literal), $C gets interpreted as a variable name. Since you never initialized that variable, it gets replaced with nothing in the actual string. You should either use single-quotes to initialize the string, or escape the dollar sign with a backslash like you did in the regex.
By the way, this couldn't be an encoding problem, because (in the example, at least), all the characters are from the ASCII character set. Whether it was encoded as UTF-8, ISO-8859-1 or ASCII, the binary representation of the string would be identical.
preg_match_all('/\$C/u', 'Thanks for a payment of 46,00 $C', $matches);
print_r($matches);
works fine for me:
Array
(
[0] => Array
(
[0] => $C
)
)
Maybe this helps:
// assuming $text is the input string
$matches = array();
preg_match_all('/([0-9,\\.]+)\\s*\\$C/u', $text, $matches);
if ($matches) {
$price = floatval(str_replace(',', '.', $matches[1][0]));
printf("%.2f\n", $price);
} else {
printf("No price found\n");
}
Just make sure the input string ($text) has been properly decoded into an Unicode string. (For example, if it's in UTF-8, use the utf8_decode function.)

Categories