Disable javascript entry into form - javascript

I'm creating a "HTML editor" for a webpage of mine. At the moment, I only want the editor to allow entry of HTML and CSS elements and not Javascript (or Jquery for that matter).
I'm trying to find a way that disables the use of <script> or <script type="text/javascript"> </script> using PHP. However the current way outputs a messy result!
$content_in_before = str_replace('<script','',$content_in_before);
$content_in_before = str_replace('script>','',$content_in_before);
It's also not very well coded!
Is there a more bulletproof way of coding this, stopping all type of Javascript from being entered into this form? (While still allowing CSS and HTML)?
Thanks in advance!

I'd recommend using a sanitization library, like HTML Purifier, since just stripping <script> tags isn't enough to prevent XSS attacks, since JS can be automatically executed using attributes like onLoad, onMouseOver, onUnload, etc.
To remove tags, and allow some, you can use PHP's strip_tags() function, but it doesn't strip the attributes, hence my recommendation for a HTML sanitization library. If you're able to run it, perhaps one of the best choices is Google's Caja library, albeit it doesn't work in shared hosting environments since it's written in Java, but it can be hosted on Google's AppEngine.
Also, simple regex solutions aren't always reliable, since even malformed tags can still be parsed. For example, <script > wouldn't be caught by simple regex detection of normal script tags unless it's looking for spaces after the tag name. It's possible to check for this, but using an established library would save you time, and would give you the added bonus of a battle-tested library.
Example:
Script Tags with Spaces producing an alert

You could you a regexplike this
echo preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', "", $var);
source: https://stackoverflow.com/a/1886842/2046700
or as stated us a libary to do this for you such as:
http://htmlpurifier.org/
another possible example:
<?php
$javascript = '/<script[^>]*?javascript{1}[^>]*?>.*?<\/script>/si';
$noscript = '';
$document = file_get_contents('test.html');
echo preg_replace($javascript, $noscript, $document);
?>

Whitelist tags you permit, and attributes you permit, then remove everything else. You can use DOMDocument for this.
I wrote this piece of code once but never had anyone else review it
function legal_html($str, $tags='<a><b><br><i><span><table><tbody><tr><td><thead><th><img>', $attribArray=false) {
if ($attribArray===false) {
$attribs = array('id','class','src','href','alt');
} else {
$attribs = $attribArray;
}
$stripped = strip_tags($str,$tags);
$dom = new DOMDocument();
#$dom->loadHTML('<div>'.$stripped.'</div>');
foreach ($dom->getElementsByTagName('*') as $node) {
for ($i = $node->attributes->length -1; $i >= 0; $i--) {
$attrib = $node->attributes->item($i);
if (!in_array($attrib->name,$attribs)) $node->removeAttributeNode($attrib);
}
}
$stripped = $dom->saveHTML();
$start = strpos($stripped,'<div>')+5;
$end = strrpos($stripped,'</div>');
$stripped = trim(substr($stripped,$start,$end-$start));
return $stripped;
}

You can use something likes this-
$content=$_POST['textbox'];
if(strpos($content,'<script>')!==false){
//show error;
}
else{
//proceed with work;
}

Related

Browser does not replace an include file by its including file

I am an absolute beginner in JS.
1) What I'm trying to do:
My web pages are composed of an index.php which is the same for all the files of a directory and one of a set of content.inc, like this: index.php?open=content.inc. This is done by a PHP snippet in the index.php and works well.
However, Google indexes all the content.inc files. The user's browser then displays the content.inc without the framing index.php. This I want to avoid. I therefore add a modest script at the beginning of each content.inc (which I would convert into a function once it runs) to tell the browser that instead of displaying the content.inc, it should display index.php?open=content.inc.
2) My unworkable solution:
var url = window.location.pathname;
var filename = url.substring(url.lastIndexOf('/')+1);
if (filename.indexOf("index.php") = -1)
{ var frame_name = "index.php?open="+filename;
window.location.replace(frame_name);
};
The browser (Firefox 60) ignores this; it displays content.inc. (I also have versions of this script which get the browser into an endless loop.)
What is wrong here? Please help!
PS: Please be assured that I have done extensive web search on this problem and found many pages of complaints about location.replace getting into an infinite loop; but none matches my situation. However, I gratefully accept a helpful link as an answer.
For starters, you have an error in this line:
if (filename.indexOf("index.php") = -1)
That's an assignment and will always evaluate to true, you need to use == or === (which should be more performant).
The guilty line is on your test case (see JP de la Torre answer). And to improve, here's a snippet to demo how to analyze the url with a regular expression :
function redirect(url) {
if(url && url.indexOf('.inc') >= 0) {
return url.replace(/\/(\w+)\.inc/, '/index.php?open=$1');
}
return url;
}
let urls = [
window.location.href,
'http://google.fr',
'http://example.com/index.php?open=wazaa',
'http://example.com/wazza.inc'
];
urls.forEach(url => {
console.log(url, ' => ', redirect(url));
});
The regexp will capture any text between a / and .inc. You can use it then as replacement value with the $1.
And applied to your case, you simply need :
if(window.location.href.indexOf('.inc') >= 0) {
window.location.href = window.location.href.replace(/\/(\w+)\.inc/, '/index.php?open=$1');
}
You can also use .htaccess server side to redirect request for .inc files on your index.php if mod_rewrite is enabled.
The solution to the problem of including an INC file called separately is the one proposed by Bertrand in his second code snippet above. It presupposes (correctly) that the inc extension is omitted in the replacement.
As I reported above, Firefox may get into an endless loop if it opens a PHP file directly, i.e. without involving the local host (with its php module).

Creating a "try it" code editor- any security issues?

I'm creating a simple "try it yourself" code editor like the one found on W3schools. Looking at the source, it seems all that one does is use JavaScript's document.write() command to write whatever is entered into the textarea on the left into the iframe on the right, without any sanitation:
function submitTryit() {
var text = document.getElementById("textareaCode").value;
var ifr = document.createElement("iframe");
ifr.setAttribute("frameborder", "0");
ifr.setAttribute("id", "iframeResult");
document.getElementById("iframewrapper").innerHTML = "";
document.getElementById("iframewrapper").appendChild(ifr);
var ifrw = (ifr.contentWindow) ? ifr.contentWindow : (ifr.contentDocument.document) ? ifr.contentDocument.document : ifr.contentDocument;
ifrw.document.open();
ifrw.document.write(text);
ifrw.document.close();
}
Is that secure in itself, or am I missing something inside the w3school's editor that does something more for security's sake?
Thanks,
If that javascript is not persisted in such a way that it can render to browsers of users other than its authors, you should be fine. Otherwise you are creating a platform that can be used to propagate XSS worms. Just allowing a user to execute arbitrary javascript on their own page is no less secure than that most modern browsers having a debugging console that lets a user execute javascript.

reading content of .aspx using javascript

i am using javascript to read the content of .aspx page. but i am not able to read it. i am using javascript as:
function edit(headtext,totext, bodytext, footertext){
alert('lll');
//var xmlDoc=new ActiveXObject("MSXML.DOMDocument");
xmlDoc.async="false";
xmlDoc.load("theme3ex.aspx");
var students = xmlDoc.documentElement;
alert('0000');
var student = students.childNodes(0);
document.getElementById('txtareahead').innerHTML = headtext;
document.getElementById('txtareato').innerHTML = totext;
document.getElementById('txtareabody').innerHTML = bodytext;
document.getElementById('txtareafooter').innerHTML = footertext;
location.href = "MailSender.aspx";
}
is there any problem eith my javascript..
First problem is that you've commented out the line which creates the AJAX object, so none of the subsequent code will work because they're trying to access an object which doesn't exist.
Second problem is that even if you uncomment that line, it's using Activex/MSXML which will only work with IE (and even then only older versions of IE).
In short, your code isn't good, and needs to be entirely redone rather than being fixed.
My recommendation is that you find a more up-to-date example of how to do AJAX code. Possibly even just use a good quality Javascript library like JQuery.
I agree with #Spudley's point.
It's also worth mentioning that if the textboxes such as txtareahead are ASP.NET TextBox Controls, then the ID's will have most likely changed during rendering.

Dynamic evaluation of functions in JS (is this safe?)

I have a website in which all the pages are processed through an index.php that includes different PHP files depending on the requested URL (this is done through mod_rewrite).
I'm using the following method to execute specific functions at page load:
index.php
<script type="text/javascript">
readyFns = Array();
</script>
<?php
// Do some stuff here, and pull the name of the PHP page to include from the DB
include $pageToInclude
?>
<script type="text/javascript">
commonFunctionToApplyToAllThePages();
otherCommonFunction();
// page-specific functions
for (i=0; i<readyFns.length; i++)
{
if (typeof(window[readyFns[i]]) == "function")
window[readyFns[i]]();
}
</script>
includedPage.php
<?php
// Generate page
?>
<script type="text/javascript">
readyFns.push("someFunction");
readyFns.push("someOtherFunction");
</script>
I quite like this approach because I just have to set readyFns at the end of this page and everything else will be nicely controlled by index.php.
My questions is: is this safe? Could it be sensitive to someone generating a link that arbitrarily sets readyFns to point to some malicious code and then links to my site?
How would I prevent that?
thanks
nico
This is interesting. In principle, it's probably ok, but you're right to be a little concerned. This is just compiling a list of keys to lookup as functions on an object, and execute, so it's not really a security problem in that respect. But, you are essentially providing access to all globals like that. You'd probably be better off making a global object besides window to store your functions on, like so:
var funcs = {};
funcs.someFunction = function() {/*blah*/};
funcs.someOther = function() {/*blah*/};
and then your readyFuncs thing would loop over funcs instead of window. I don't think there'd be anything to worry about past that.
Of course, there are other things with your approach that could be improved, but I think it's ok as-is if it works for you.

Javascript Validation not working on .Net Content Pages

I'm wondering if anyone else has experienced the following issue.
On a single non-linked (to a master page) .aspx page, I'm performing simple JS validations:
function validateMaxTrans(sender, args) {
// requires at least one digit, numeric only characters
var error = true;
var regexp = new RegExp("^[0-9]{1,40}(\.[0-9]{1,2})?$");
var txtAmount = document.getElementById('TxtMaxTransAmount');
if (txtAmount.value.match(regexp) && parseInt(txtAmount.value) >= 30) {
document.getElementById('maxTransValMsg').innerHTML = ""
args.IsValid = true;
}
else {
document.getElementById('maxTransValMsg').innerHTML = "*";
args.IsValid = false;
}
}
Then as soon as I move this into a Master page's content page, I get txtAmount is null.
Is there a different way to access the DOM when attempting to perform client-side JS validation with master/content pages?
Look at the source for your rendered page within the master page. Many elements will have an ID like ControlX$SubControlY$txtMaxTransAmount ... you'll need to adjust your validation accordingly. I will often just inject the IDs into the client doc..
<script type="text/javascript">
var controls = {
'txtAmount': '<%=TxtMaxTransAmount.ClientId%>',
...
}
</script>
I'd put this right before the end of your content area, to make sure the controls are rendered already. This way you can simply use window.controls.txtAmount to reference the server-side control's tag id. You could even make the right-side value a document.getElementById('...') directly.
Are you using asp textboxes? If so I believe you need to do somethign like document.getElementById('<%= txtMaxTransAmount.ClientID %>').
Hope this helps
Tom

Categories

Resources