Hacker News new | past | comments | ask | show | jobs | submit login
Evil.js: A JavaScript library for thwarting hot-linkers (github.com/kitcambridge)
109 points by surreal on March 31, 2014 | hide | past | favorite | 66 comments



Reminds me of a script I wrote when a site based in China cloned our entire domain and put it up at a new URL, complete with clumsily photoshopped logos. They left a single stray call to our ad server, though, and I was able to "hack in" and randomly flash a "This site is stolen!" message or insert an auto-playing Youtube clip of my choice.


YouTube is blocked in China...


He could link to Falun Dafa exercise videos and watch as their customers disappear one by one...


That will get his ad server blocked in China, which he might not want.


    window.location = "http://someone-elses-site.com/Falun_Dafa_exercise_video.mpg";


Trolling the GFW... that could be an interesting experiment :) http://gov.cn/taiwan-is-a-sovereign-state/


Fair point, though the audience for the pranks was more the people they were trying to sell advertising space to.


I did not realize until checking out this source that dividing by zero in JS outputs "Infinity".

https://github.com/kitcambridge/evil.js/blob/gh-pages/evil.j...


This is happening because all numbers in JavaScript are IEEE 754 [0] double. +/-infinite may be returned for finite, non zero number divided by zero. This is also common behavior in many other languages with support for IEEE 754 floats, from the top of my head: JVM, .NET languages and Haskell do so too.

[0] http://en.wikipedia.org/wiki/IEEE_754


Longer answer on StackOverflow (including V8 source): http://stackoverflow.com/a/21893602/1216976


And, awfully-enough, even though Infinity is a required part of IEEE754, and happens all the time in Javascript, JSON doesn't recognize it.


Why is that awful? JSON is not JavaScript. The string encoded value of the integer 1 is not a IEEE754 numeric either - it's just the character 1. In modern usage: JSON is to JavaScript as JavaScript is to Java.


It's awful because you would expect a network encoding of a set of types to be able to encode all the valid values of those types. If you claim that your encoding can represent floats, but it can't represent Infinity or NaN, then your encoding cannot, in fact, represent floats.


It makes no such claim!

See http://www.json.org/ - it is very cleary defined. *It's a string notation for a number. Don't get hung up on the implementations of floats or integers - it's irrelevant!


> In modern usage: JSON is to JavaScript as JavaScript is to Java.

This is totally wrong. Javascript has nothing whatsoever to do with Java. It only has a few very superficial syntactical similarities (curly brackets, semi-colon at the end of each line, and that awful 'new' keyword). JSON, on the other hand, stands for "Javascript Object Notation", and can be interpreted as Javascript (with 'eval'). It's explicitly meant for storing and transmitting javascript data, so when there's a javascript data value that is not supported by JSON, that is absolutely relevant.


In modern usage, you don't eval it. In modern usage is used for far more that just "javascript" applications.

Of the four letters in the acryonym, the "J" is the least significant. Yes, it's javascript-y, but that's it. So many misunderstandings come from focusing on the "J". So, as JavaScript has basically nothing to do with Java (aside from superficial syntax similarities) so does JSON to JavaScript, for the same reasons. This "JSON is a subset of JavaScript" is just not true - at best it's "inspired by and interoperable with".


No, Javascript has far, far less to do with Java than with JSON. JSON is legal javascript. Ever heard of jsonp?

Java, on the other hand, is a totally different language. Any similarities are superficial and exist primarily for PR reasons. You can't pretend javascript is legal Java or vice versa. But JSON is totally legal javascript. That is exactly how you can declare objects in javascript. The name JSON fits the bill perfectly: it is the javascript object notation.


"it is the javascript object notation."

Except it's not, which is part of the reason this sub thread started. JSON encoded numbers are not IEEE754 floats either. And JSONP is purely a convenient hack around browser security issues only, again it has noting to do with JSON as a format.

You can argue the specifics,, but you miss the point that the claim that "JSON is JavaScript" is false and leads to tricky edge cases when the assumption breaks down.


> And JSONP is purely a convenient hack around browser security issues only, again it has noting to do with JSON as a format.

It gets around those browser security issues by having the JSON wrapped in a function call and interpreted as javascript. I've never heard of a server converting all the values for JSONP.

There are absolutely edge cases, and those are important to note, exactly because outside those edge cases JSON is valid javascript. Claiming that they are totally completely unrelated (like javascript and Java) is false.


IIRC, JSON is a strict subset of JS and Python.


I have never heard anyone else make this assertion.


The Python is new to me, but JSON's strong relationship to javascript is not new at all: http://en.wikipedia.org/wiki/JSON


JSON originated from Javascript alone


is it? "null" is not valid python, I think


If you do this first:

    null = None
    Infinity = float('Infinity')
    NaN = float('nan')
(But no, it's not quite Python)


It isn't. It would be None. I believe parent is mistaken.


I stand corrected; I am not that familiar with python. Though I remember reading somewhere that JSON can be evaled in both JS and Python. Perhaps the python bit is not true.


JSON looks more-or-less like a Python dict, but you still wouldn't be able to parse {"x": NaN} or {"x": Infinity}


Oddly, there's actually no language that I know of that has NaN and Infinity constants. Many languages pretty-print those float values that way, but none of the parsers can interpret them back in.


...do you mean other than JavaScript? They're not actually parser-level constants, they're just defined as globals/on the window object, but they work.


Not always. 0/0 == NaN, but of course typing that into the console will yield false.


Because, of course, NaN != NaN


Very cute. :-)

Now that we've all had a laugh, wouldn't it make more sense to have the server respond with a redirect to a shared copy of the script hosted somewhere that provides bandwidth for free? (Perhaps this is a sign that the script should be open-sourced as well.)


If someone hotlinked one of my scripts, I'd update the head of the script and use the opportunity for free marketing:

    if(!window.location.host.match(/(www\.)?myapp.com/)) window.location = 'http://www.myapp.com';
I bet they won't hotlink after that.


I know someone who had, of all people, Facebook hot-linking to his stuff. He redirected all visitors to his homepage. Then Facebook's legal department called his home number, his wife answered and got nervous, and it all ended there.


Interesting! I personally would have loved to have a chat with Facebook's legal team about the issue. Although I'm a bit surprised they'd actually call him instead of either a) not hotlinking anymore (seems to be the most obvious solution) or b) just sending a quick C&D.

I'd be surprised if they actually have a leg to stand on legally if they are hotlinking off someone's site, especially if there's have no prior agreement to allow them to do so.


Sounds fishy. It would take days for any kind of legal action like this. Doesn't FB push code like every couple of hours? A code patch would have been many times quicker.


I like this. I'd think it'd be even better if instead of getting them to stop linking, you could turn them into a permanent source of referrals.


If you added a `Math.random() < .01` in the if clause, I doubt they'd ever even notice, and depending on how much traffic they get you could have a nice steady flow of referrals =].


But bandwidth isn't free. Someone's gotta pay for it in some way or another, and if a major company lets say is using your hosted copy without asking, then perhaps they should host their own?


there are cdns happy to host useful opensource scripts for free, assuming you want to release your script as open source.


This script is used by rawgithub.io. It allows to punish the 'abusers'. There isn't really a notion of open-source in it.

I think the idea is more that if someone is eating your bandwidth by hotlinking your jQuery.js, then you can serve them this instead.


What if someone hotlinks evil.js?


So we can check the hostname from our code and hot-link evil.js from http://kitcambridge.be/evil.js/evil.min.js :)


The documentation is lacking.


The non-minified source is pretty self-explanatory. It modifies a lot of the standard javascript functions. My favorite is the document.write(element) is modified to surround the element with <marquee> and <blink> tags and then write that to the DOM.


I like Math.pow = function() { return "pow pow pow!"; }


To an extent, yes. I already looked at the source. But it just says to include evil.js on my site. How is that protecting my site from bandwidth thieves? Won't it also screw up my own site's functions?


Can we get a demo?


From the github page: http://kitcambridge.be/evil.js/


Is something supposed to happen interaction-wise when I go to that page though?


No, it just prevents other scripts linked from the same page from working via sneaky, nefarious means that make it hard to debug.


Oh! OK. cool.


As a "bonus" you will make your site unusable for suffix proxy users.


And the logical follow up, evil.css: https://github.com/tlrobinson/evil.css


To stop leechers - couldn't you just, in your script >

    (function(){
      if(document.domain != 'mydomain.com') return;
    // my script
    })();


Why be nice? >:)

  (function () { if (document.domain !== "mydomain.com") { while (1); }})();


Where's the fun in that?


Not to be confused with evil.js: http://andjs.com/code/eviljs/


combination and minification also prevent hot-linking


I've had experience where someone doesn't just hotlink a resource, but they "clone" it, and replace our ads with their ads. Assuming evil.js works by detecting host names, this would help prevent that.


It doesn't, as a cursory glance at the source would show.


The server could check which page is embedding the script and then server evil.js instead of good.js :)


Better hope they don't visit the real site after the fake site!


Don't cache the fake version?


Better not minify the library with JSMin.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: