PHP form auto escaping posted data? - php

I have an HTML form POSTing to a PHP page.
I can read in the data using the $_POST variable on the PHP.
However, all the data seems to be escaped.
So, for example
a comma (,) = %2C
a colon (:) = %3a
a slash (/) = %2
so things like a simple URL of such as http://example.com get POSTed as http%3A%2F%2Fexample.com
Any ideas as to what is happening?

Actually you want urldecode. %xx is an URL encoding, not a html encoding. The real question is why are you getting these codes. PHP usually decodes the URL for you as it parses the request into the $_GET and $_REQUEST variables. POSTed forms should not be urlencoded. Can you show us some of the code generating the form? Maybe your form is being encoded on the way out for some reason.
See the warning on this page: http://us2.php.net/manual/en/function.urldecode.php

Here is a simple PHP loop to decode all POST vars
foreach($_POST as $key=>$value) {
$_POST[$key] = urldecode($value);
}
You can then access them as per normal, but properly decoded. I, however, would use a different array to store them, as I don't like to pollute the super globals (I believe they should always have the exact data in them as by PHP).

This shouldn't be happening, and though you can fix it by manually urldecode()ing, you will probably be hiding a basic bug elsewhere that might come round to bite you later.
Although when you POST a form using the default content-type ‘application/x-www-form-encoded’, the values inside it are URL-encoded (%xx), PHP undoes that for you when it makes values available in the $_POST[] array.
If you are still getting unwanted %xx sequences afterwards, there must be another layer of manual URL-encoding going on that shouldn't be there. You need to find where that is. If it's a hidden field, maybe the page that generates it is accidentally encoding it using urlencode() instead of htmlspecialchars(), or something? Putting some example code online might help us find out.

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).

Not using & when POSTing to php

I'm building a very AJAX site which means posting a lot of information to the server, sometimes typed by a user.
this is how I'm posting things
xmlhttp.open("POST", 'somepage.php' ,true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send('post=stuuf I want to send');
An example of my problem is this, someone types FOO BAR as their name which would post firstName=FOO&lastName=BAR
which in php gets you $_POST['firstName'] is FOO and $_POST['lastName'] is BAR
but if someone types the name FOO&BAR SMITH it would post like this firstName=FOO&BAR&lastName=SMITH
which in php gets you $_POST['firstName'] is FOO and $_POST['BAR'] which has no value and this start to fall apart. It means I have to replace & in everything that is posted and I'm finding it annoying.
Is there a way to tell php to ignore any &, and just send one big string. when I need to send multiple values I was planning to break them up with an '_' I could then replace any user typed _ with &#95 and never have to worry about it again.
Could this be done in .htaccess or if not then in the php file itself?
Thanks for any help
Don't do this on the PHP end... send a proper HTTP request! You are mangling all of your data client-side. If you're sending URL encoded data, send it URL encoded.
No, but you absolutely must escape your data before using it as a string inside the ajax request.
You should encode the data you want to sent using encodeURI or encodeURIComponent. That way you can send whatever characters you want.

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.

mysql_real_escape_string() -> stripslashes() -> jquery.append()

im letting my users type in texts, then take them to server side php and process them, and if everything goes as it should, i just append the text with jquery without the page having to load all over again.
This is the procedure:
$post_text = htmlspecialchars(mysql_real_escape_string($_POST['post_text']));
some logic...
everything ok!
stripslashes(str_replace("\\n", "", $post_text))
and then i send all the nessesary data witj json
echo json_encode($return);
on the client side i append the html chunk saved in a variable from the server side.
this seems to work on localhost, it removes all the slashes and so on, but online it just doenst remove the slashes, and they keep coming up, when i hit refresh they dissapear becouse then its a
stripslashes($comment['statusmsg_text'])
written out with php straight from the database. Is it the json that adds some extra stuff? i dont get it becouse it works perfectly on localhost.
best of regards,
alexander
The additional slashes might be magic quotes. You shouldn’t rely on them and disable them.
Additionally, mysql_real_escape_string should only be used to prepare strings to be put into a string context in an MySQL statement. Similar applies to htmlspecialchars that should only be used for sanitizing data to be put into an HTML context.
It may be, that on your server and your localhost the magic_quotes_gpc directive is set differently, so your string is double encoded on server side.
Try it without stripslashes, json_encode should handle that. All you need to do is use mysql_real_escape once, before your string touches your database.

Clean php output into javascript

Due to the nature of my project. I am pulling data from my db and outputting to javascript. Things were working just fine till I got to the main content. It has strings like (;, :, - ''). How do I ensure that these are displayed without crushing my script coz as for now nothing seems to work.
If all you have is a single string value then see answer by Tomalak Geret'kal.
If there is any chance of getting something more than a single value from your database, like an array, object, null, or anything more complex, then I would suggest using json_encode. By using something like this:
<script>
var your_JavaScript_variable = <?php echo json_encode(your_PHP_variable); ?>;
</script>
you can pass complex data structures, arrays, or even single strings from PHP to JavaScript with all of your backslash escaping done automatically.
Additionally when you use JSON for moving your data from PHP to JavaScript it will be easy to make your application get the data from your server asynchronously without page refreshes using AJAX in the future.
You can use the PHP addslashes function for inserting into Javascript, and htmlspecialchars for inserting into HTML.
You should be encoding that data into json. PHP has a handy function to do this, json_encode.
Be sure to use the JSON_HEX_QUOTE option or the quotes in your data will break your js.
Read this: http://php.net/manual/en/function.json-encode.php

Categories