using a base64 encoded string in url with codeigniter - php

I have an encrypted, base64 encoded array that I need to put into a url and insert into emails we send to clients to enable them to be identified (uniquely) - the problem is that base64_encode() often appends an = symbol or two after it's string of characters, which by default is disallowed by CI.
Here's an example:
http://example.com/cec/pay_invoice/VXpkUmJnMWxYRFZWTEZSd0RXZFRaMVZnQWowR2N3TTdEVzRDZGdCbkQycFFaZ0JpQmd4V09RRmdWbkVMYXdZbUJ6OEdZQVJ1QlNJTU9Bb3RWenNFSmxaaFVXcFZaMXQxQXpWV1BRQThVVEpUT0ZFZ0RRbGNabFV6VkNFTlpsTWxWV29DTmdackEzQU5Nd0lpQURNUGNGQS9BRFlHWTFacUFTWldOZ3M5QmpRSGJBWTlCREVGWkF4V0NtQlhiZ1IzVm1CUk9sVm5XMllEWlZaaEFHeFJZMU51VVdNTmJsdzNWVzlVT0EwZw==
Now I understand I can allow the = sign in config.php, but I don't fully understand the security implications in doing so (it must have been disabled for a reason right?)
Does anyone know why it might be a bad idea to allow the = symbol in URLs?
Thanks!
John.

Not sure why = is disallowed, but you could also leave off the equals signs.
$base_64 = base64_encode($data);
$url_param = rtrim($base_64, '=');
// and later:
$base_64 = $url_param . str_repeat('=', strlen($url_param) % 4);
$data = base64_decode($base_64);
The base64 spec only allows = signs at the end of the string, and they are used purely as padding, there is no chance of data loss.
Edit: It's possible that it doesn't allow this as a compatibility option. There's no reason that I can think of from a security perspective, but there's a possibility that it may mess with query string parsing somewhere in the tool chain.

Please add the character "=" to $config['permitted_uri_chars'] in your config.php file you can find that file at application/config folder

Originally there are no any harmful characters in the url at all. But there are not experienced developers or bad-written software that helps some characters to become evil.
As of = - I don't see any issues with using it in urls

Instead of updating config file you can use urlencode and urldecode function of native php.
$str=base64_encode('test');
$url_to_be_send=urlencode($str);
//send it via url
//now on reciveing side
//assuming value passed via get is stored in $encoded_str
$decoded_str=base64_decode(urldecode($encoded_str));

Related

Sending percent encoding as part of data

I have a site where anyone can leave comments.
By leaving a comment browser makes an ajax request to PHP script, sending encodeURIComponent-ed data to PHP script.
Earlier, in the PHP script, I added
$data = str_replace("\n","\\n",str_replace("\"","\\\"",$_POST["text"]));
Now I’ve been testing by inputting random stuff and found an exploit: if to input %00, it will be added to my comments file as null-terminator and corrupts my data. Also, other percent-encoded value will be decoded.
I am sending data as a regular application/x-www-form-urlencoded.
How to fix that?
So, the solution I’ve made so far is:
$_POST["text"] = str_replace("\"","\\\"",$_POST["text"]);
for($i=0;$i<=40;$i++)
if(chr($i)!="\n"&&chr($i)!="\r"&&chr($i)!=" "&&chr($i)!="("&&chr($i)!="&"&&chr($i)!="!"&&chr($i)!="\""&&chr($i)!="'")
$_POST["text"] = str_replace(chr($i),"",$_POST["text"]);
$_POST["text"] = str_replace("\\","",$_POST["text"]);
It just removes all special and potentially malware non-readable characters with some exceptions (newlines, ampersands etc.).
The only issue of this solution is that it removes backslash (but successfully writes data).

PHP: Detect password parameter in string and replace with default text

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

PHP - alternative to Base64 with shorter results?

I'm currently using base64 to encode a short string and decode it later, and wonder if a better (shorter) alternative is possible.
$string = '/path/to/img/image.jpg';
$convertedString = base64_encode($string);
// New session, new user
$convertedString = 'L3BhdGgvdG8vaW1nL2ltYWdlLmpwZw==';
$originalString = base64_decode('L3BhdGgvdG8vaW1nL2ltYWdlLmpwZw==');
// Can $convertedString be shorter by any means ?
Requirements :
Shorter result possible
Must be reversible any time in a different session (therefore unique)
No security needed (anyone can guess it)
Any kind of characters that can be used in a URL (except slashes)
Can be an external lib
Goal :
Get a clean unique id from a path file that is not the path file and can be used in a URL, without using a database.
I've searched and read a lot, looks like it doesn't exist but couldn't find a definitive answer.
Well since you're using these in a URL, why not use rawurlencode($string) and rawurldecode($encodedString)?
If you can reserve one character like - (i.e., ensure that - never appears in your file names), you can do even better by doing rawurlencode(str_replace('/', '-', $string)) and str_replace('-', '/', rawurldecode($encodedString)). Depending on the file names you pick, this will create IDs that are the same length as the original filename. (This won't work if your file names have multi-byte characters in them; you will need to use some mb_* functions for that case.)
You could try using compression functions, but for strings as short as file paths, compression usually makes the output larger than the input.
Ultimately, unless you are willing to use a database, disallow certain file names, or you know something about what kinds of file names will come up, the best you can hope for is IDs that are as short or almost as short as the original file names. Otherwise, this would be a universal compression function, which is impossible.
I don't think there is anything reliable out there that would significantly shorten the encoded string and keep it URL friendly.
e.g. if you use something like
$test = gzcompress(base64_encode($parameter), 9, ZLIB_ENCODING_DEFLATE);
echo $test;
it would generate characters that are not URL-friendly and any post-transformation would be just a risky mess.
However, you can easily transform text to get URL-friendly parameters.
I use the following code to generate URL-friendly parameters:
$encodedParameter = urlencode(base64_encode($parameter));
And the following code to decode it:
$parameter = base64_decode(urldecode($encodedParameter));
As an alternative solution, you could use generated tokens to map known files using some database.

Codeigniter trying to send HTML content via ajax?

I'm trying send an HTML string from the client to the server via ajax. I keep getting "disallowed key characters" error. So I took this $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; and set it to nothing $config['permitted_uri_chars'] = ''; Since CodeIgniter says Leave blank to allow all characters -- but only if you are insane. But I still get Disallowed Key Characters error.
This is how I'm trying to send it:
var content = '<p class="MsoNormal">Hi {$first_name}</p>\n<p class="MsoNormal">My name is Bill, etc etc.</p>';
$.get('/task/preview_template', {content:content}, function(data) {
console.log(data); //Disallowed Key Characters
});
_clean_input_keys is your likely culprit for what's throwing the error, and you have a large number of characters that fall outside of the allowed characters of "/^[a-z0-9:_\/-]+$/i".
There are a few ways that I can think of that might handle this:
Modify _clean_input_keys so that it accepts the extra characters. This, of course, is an internal function for a reason and shouldn't be changed unless you know what you're doing. (Alternatively, you may be able to modify it to allow the special characters for HTML encoding and HTML encode the string. This helps mitigate the compromise to security that comes with adding such characters to _clean_input_keys.)
Encode your string before sending it, then decode it on the server side. This is a little more work on both your part, and that of the computers involved, but it keeps _clean_input_keys intact, and should allow you to send your string up, if you can find an encoding that is reliable in both directions and doesn't produce any disallowed characters. Since you're using GET, you may also run into GET input limits on not only the server, but browser-side, as well.
Use POST instead of GET and send your content as a data object. Then just use the $_POST variable on the server, instead of $_GET. While this may work, it is a bit unorthodox and nonstandard usage of the REST verbs.
Store your template content on the server, and reference it by name, instead of storing it in the JavaScript. This, of course, only works if you're not generating your template content on the fly in the JavaScript. If you're using the same template(s) in all of your JavaScript calls, though, then there's really no reason to send that information from JavaScript to begin with.

cutting special chars in folder name when using GET

I've been visiting stackoverflow.com for a long time and always found the solution to my problem. But this time it's different. That's why I'm posting my first question here.
The situation looks like this: My website provides a directory explorer which allows users to download whole directory as a zip file. The problem is I end up with error when I want to download a dir containg special characters in it's name, i.e. 'c++'. I don't want to force users to NOT name their folders with those special chars, so I need a clue on this one. I noticed that the whole problem comes down to GET protocol. I use ajax POST for example to roll out the directory content, but for making a .zip file and downloading it I need GET:
var dir_clicked = $(e.target).attr('path'); //let's say it equals '/c++'
window.location = 'myDownloadSite.php?directory_path='+dir_clicked;
I studied whole track of dir_clicked variable, step by step, and it seems that the variable in adress is sent correctly (I see the correct url in browser) but typing:
echo $_GET['directory_path']
in myDownloadSite.php prints
'/c'
instead of
'/c++'
Why the GET protocol is cutting my pluses?
You can use:
encodeURIComponent() //to get the url then use
decodeURIComponent() //to decode and access ur filename.
Use urlencode() and urldecode() on server side.
Try encoding your URI with encodeURI(url) JavaScript function.
window.location = encodeURI('myDownloadSite.php?directory_path=' + dir_clicked);
Maybe use encodeURIComponent() and then remove all %xx occurrences?
When the information is posted it is encoded with special chars, sounds like you just need to decode them before using the information.
You can use php function urldecode() to decode the folder names before using them...
$_GET[directory_path]=urldecode($_GET[directory_path]);

Categories