Sanitizing HTML Input with Trix - php

I have a strange issue at the moment, and I'm looking for any insight on how to deal with this.
I'm currently accepting HTML input using the Basecamp Trix editor.
When I send the input to my Laravel application, it is saved to my database as:
<div><script>alert('test');</script></div>
However, the problem is that when I insert this into a Vue property using Laravel's blade, it somehow actually converts it back into valid HTML:
<reply :data-reply="{{ $reply }}"></reply>
Result:
It seems that Laravel converts the script tags to valid HTML using the blade echo statements?
My View:
{{ $reply }}
Result:
{"id":63,"created_at":"2017-09-07 13:30:53","updated_at":"2017-09-07 13:35:05","user_id":1,"body":"<div><script>alert('test');<\/script><\/div>","options":null}
The problem is, I can't sanitize this because the HTML data is actually escaped in my database, but when Laravel converts my reply to JSON, it actually unescapes the script tags, and it's actually ran in Vue when using the v-html directive.
I know I'm not supposed to accept user input while using the v-html directive, but I need HTML support for replies, and I can't sanitize already escaped HTML in my Laravel application.
Does anyone have any ideas how I can go about sanitizing Trix's content in some way?

Ok, I've put
<div><script>alert('test');</script></div>
into email field of user.
In Laravel I'm just using:
return view('welcome', ['user' => App\User::find(1)]);
nothing special in model.
My view looks like this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="el">{{ $user }}</div>
<script>
user = JSON.parse(document.getElementById("el").innerHTML);
console.log(user.name);
</script>
</body>
</html>
and in JS console I'm getting:
<div><script>alert('test');</script></div>
so it's not the same as in database but it doesn't look as you showed either.

Related

How to send line breaks from Laravel controller to display multiple lines in blade page message

In my controller I have the I have a redirect if a condition is met and want to use the page message to convey the reason for the redirect. However, I can't find a way to send a line break from the controller to the bootstrap message area so that it displays multiple lines. I can find many answers for what to do in the blade, mainly escaping the HTML with {! markup !}, but that doesn't work in the controller where I'm sending the message.
Here's my controller code:
$message = "Nothing to do. </br>You must first enter account data to generate a report";
return redirect()->route('admin.home')->with('message', $message);
The "</br>" tag is displayed. I've tried "/n" and "
" to no avail, they don't render but also no line break. I need to send more detailed messages depending on the condition for redirecting which won't work if everything has to go on one message line.
I'm using Laravel 5.5 in XAMPP (PHP 7) on Windows 10, Chrome for dev browser, VS Code for coding.
Any suggestions?
Have you tried {!! $message !!} in your blade template?
Just be sure that your return statement cannot contain any user inputted HTML as this may allow XSS.
Please see the following documentation on "displaying unescaped data"
https://laravel.com/docs/5.5/blade#displaying-data
SOLVED: Part of my problem was that "message" is a default variable name that automatically gets displayed in the message area of a bootstrap page, so when I tried using my own code in the blade I would get both the automatic message display as well as my own. By changing from the default name "message" I can pull the session variable in the blade and display it without getting two messages. It's identical to the default message, but now I can escape the markup and get my line breaks. New code as follows:
Controller:
$message = "Nothing to do. </br>You must first enter account data to generate a report";
return redirect()->route('admin.home')->with('special_message', $message);
Blade:
#if(Session::has('special_message'))
<p class="alert alert-info">{!! Session::get('special_message') !!}</p>
#endif

What is the e() method in laravel views for?

I was digging through laravel and I went through how the blade views are interpreted and what I came across was that:
This:
{{ $tenant->name }}
Translates to this:
<?php echo e($tenant->name); ?>
I don't understand what the e() method is for? I could not find it on the php.net too so I am guessing it is a part of laravel 5 itself. But what does it do?
from the docs:
e()
The e function runs htmlentities over the given string:
echo e('<html>foo</html>');
// <html>foo</html>
http://laravel.com/docs/5.1/helpers#method-e
say your going to print some data from the database on a web page, or going to put in to the database as a input like,
{{ $tenant->name }}
and think value of $tenant->name is something like
<script>
alert("Errors....");
</script>
after rendering this in the browser you will get an alert. This is an security issue so we need to avoid from rendering those content and we don't need these kind of data in out database.
so we need to sanitize those data
to do that laravel provides some options
HTML::entities($tenant->name);
and e() is and helper function to HTML::entities
and you can get the same behavior by using
e($tenant->name);
if $tenant->name is <script>alert("Errors....");</script> then after applying to e() you will get something below,
"<script>
alert("Errors....");
</script>"
this is no longer process as a script
here is a good recipe
OR there is a easy way to do this
use triple curly braces {{{ }}} instead of double braces {{ }} this will also sanitize the content.

how to add UTF8 support in PHP?

I have no experience in PHP but I found the following php-code for a wordpress-plugin that asks a user to say Yes or No when user clicks on the Publish-button in Wordpress.
The problem with the code below is that some characters are now shown correctly in the popup-box which appear. I think that the string-message somehow needs to be encoded with UTF8 and I really don't know how to do this or if it is even possible. This is the code:
<?php
/*
Plugin Name: Confirm publish
*/
$c_message = 'รจ un test?'; // your confirm message
function confirm_publish(){
global $c_message;
echo '
<script type="text/javascript"><!--
var publish = document.getElementById("publish");
if (publish !== null) publish.onclick = function(){
return confirm("'.$c_message.'");
};
// --></script>';
}
add_action('admin_footer', 'confirm_publish');
?>
If it is possible, can someone please let me know what I need to look for or what I need to do with above code to make it work?
You should make sure that the data you return to the HTML is displayed correctly by the browser. You can do this with the following meta-tag:
<meta charset="utf-8">
You need to put this as high as possible in the head-tag for everything to be displayed properly. It might even be better to put this above the title tag to avoid issues there.
When working with databases, also make sure that they are set up in utf-8. When doing that, no issues displaying any data whatsoever should occur.

Cannot store <SCRIPT> tag into database via POST method

On my web site I have a TEXTAREA form tag which is intended to accept some HTML content and store it in MySQL database. Everything works fine except when there's script inside <SCRIPT></SCRIPT> tags. If I try to store such a script I get some strange message that I don't have a permission for accessing my php file (containing this TEXTAREA). I can store <SCRIPT> tag sontent in my database through cPanel (mySqlAmin console) but not through web form (POST method used). It seems to me that POST method on ISP's Apache server checks POST methods contents. Can somebody explain to me what's going on here and what could be the solution?
This is the exact error message:
Forbidden
You don't have permission to access /para-actions.php on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
para-actions.php is the PHP with code that receives POST content from FORM and stores it into database. (As I said, it works fine with all other content except when there's <SCRIPT>...</SCRIPT> inside it!)
Even more, the same PHP code works fine on one hosting server and not on another one (the same web hosting provider). The only difference I noticed is that hosting server where I can store <SCRIPT> into database uses PHP v5.2.17 while other one which does not allow <SCRIPT> uses PHP v5.4.32.
In this recent question: Http 406 error on javascript ajax post. Accept header set to accept all one OP had the exact same problem. And Usually mod_security provides some rule for detection of <script in POSTed content.
It's quite certainly your problem. And you cannot alter the ISP mod_security rules.
The only thing you can do, as stated in the previous linked answer is to encode your POST so that mod_security will not detect the strings inside. Using Base64 encoding is usually the simpliest way of managing it.
I just did a simple test on localhost and it worked using this code
<html>
<head>
<title>Untitled Document</title>
<?php
if ($_POST['data'])
{
$con=mysqli_connect("localhost","root","password","abkarino");
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$sql = "INSERT INTO `abkarino`.`test` (`script`) VALUES ('".mysqli_real_escape_string($con,$_POST['data'])."');";
mysqli_query($con,$sql);
}
?>
</head>
<body>
<form action="script.php" method="post">
<textarea name="data" cols="10" rows="5"></textarea>
<input name="submit" type="submit" value="submit" />
</form>
</body>
</html>
and it worked with no error.
which means: 1) you have something wrong with your code.
or 2) mod_security is preventing it to get rid of injecting scripts to your page just like what Nikhil Mohan said.
I'm not sure what you're trying to do, but if you're allowing your users to upload a script, or something, but can't have them type the tags tell them to write the script without the tags. When you post the script add the tags yourself.
a robust method would be allow them to do what they want. If they type the script with tags parse the content and remove the scripts tags before putting it in the DB. There must be a regex function that will allow you to search their entered content for <script> and replace it with ' '. Then search for </script> and replace it with ' '. Then you'll have tagless content to put in your db, or on your page.
try
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
Hope that's at least somewhere in the ballpark of what you're trying to do, lol.
Please do encoding and decoding before POST by using base64_encode and base64_decode the result.

problem in parsing

i have a page,say abc.html, that is having a small form with some fields.
<form name="form" method="post" action="abc.html">.......................</form>
when we submit the form it again comes back to abc.html with some data posted and shows the resulted names on the page which came after processing the posted data.
in the whole procedure the page url remains same.Now i want to parse this abc.html containing data after the submission of the form.I have done parsing in which the original url contains all the data but not like this on which after submission the data gets displayed on the page.Please tell me how can i parse such page??
Well, to get the correct HTML from the server, you have to send a POST request containing the form data. Then you can parse the server response.
Parsing the HTML file is same as us seeing it. So the HTML page rendered after posting the data will have some or any HTML element in which the additional text is displayed. When you parse the page chek if this or a container exists if so then read the rest of the data. The HTML page displayed without the posted data will not have this additional or container.
Edit: Look at this question : PHP Screen Scraping and Sessions
First of all. Your page should be abc.php. Otherwise it will not parse any php.
Second. Here is some code that will help you out (I Hope). Copy/Paste this example and place it in abc.php
<html>
<head></head>
<body>
<?php
if (isset($_POST['submit'])) {
echo 'you posted the following value :'.$_POST['foo'];
}
?>
<form name="form" action="abc.php" method="post">
<input type="text" name="foo" value="" />
<input type="submit" name="submit" value="Press Me" />
</form>
</body>
</html>
If this is not the case. And you want to parse HTML like parsing XML you should use the DOMDocument class of PHP
$oDom = new DOMDocument();
$oDom->loadHTML($sHTMLstring);
// or
$oDom->loadHTMLFile($sFileName);
// now you can walk the dom like
$oDomElement = $oDom->getElementByTagName('form');
http://nl.php.net/manual/en/domdocument.loadhtml.php
http://nl.php.net/manual/en/domdocument.loadhtmlfile.php
http://nl.php.net/manual/en/domdocument.getelementsbytagname.php
Hope this helps
Good question, but I think it's not possible with PHP. My company doing that with very advanced tool in C. It just grab any page and send the any form and get rsponse HTML.
But You can found maybe some tools. Don't know.
I think the point here is that you can't just open the URL and read the HTML that comes back. You will have to play the part of the browser in order to interact with the server side form. To do this, you'll have to write your own code to HTTP POST the form input data. The HTTP response to your POST will contain the generated HTML, which you can then parse for the processed results.
If you want to send the form to the web server (i.e. "fill" it first) you need something similar to Perls WWW::Mechanize. See this question for possible solutions to do this. Afterwards, you need to parse the resulting page, and that heavily depends on the site in question itself: one site might use named elements you can easily retrieve using regular expressions, a different site might not, making it much harder to get the values you're interested in.

Categories