0

I have a section of website that reads input and displays it back on the site. Only difference is that text is converted to all capitals.

I want to prove that javascript injection is possible.

For example, if I save

 <script>alert('hello');</script>

this gets written into the html as

 <SCRIPT>ALERT('HELLO');</SCRIPT>

As ALERT isn't javascript keyword, nothing gets run.

Is it possible to create something that can be converted to all caps that javascript could compile to show other people that code injection is possible?

The text is truncated to 60 characters.

Tadhg
  • 193
  • 1
  • 3
  • 20
  • 1
    if you count `X = 1;` then yes. But it's not a very dangerous piece of code.... :-). To my knowledge there are no useful functions or keywords which can be expressed in capitals. Having said that, it's an unusual technique. Most injection protection usually relies on HTML-encoding the script tags so the code won't appear within an executable block. – ADyson Jun 06 '19 at 13:46
  • 3
    Take whatever you want and run it through this [JSFuck](http://www.jsfuck.com/). It converts it to just symbols which have no case. – zero298 Jun 06 '19 at 13:46
  • @zero298 never seen that before. That's bonkers...but yeah it gets all the way round this all-caps injection protection. – ADyson Jun 06 '19 at 13:48

2 Answers2

4

Hypothetically, if the converter is foolish enough to only act on letters, you could convert malicious code to something like JSFuck which only uses the following characters to operate: ()+[]! none of which have an uppercase alternative.

The idea is just to find the characters that you need without actually expressing them. In fact that's the whole point of this particular esoteric language, mapping specific characters and then having them evaluated.

For example: (![]+"")[1] means "a"

  1. ![] means false
  2. false+"" means "false"
  3. ("false")[1] means "a"

From there you can construct whatever function you want without typing a single lowercase letter. The difficult part getting this code to execute in a global context in under 60 characters. The given library shows that you can get to Window with []["filter"]["constructor"]("return this")() but you would need to get those lower case Strings mapped to other symbols first.


No matter what, it's far better to just find a way to explicitly prevent user provided content from executing in a global context. You don't beat around the bush on this by finding soft measures to make it not work. What if the next version of JavaScript introduces a language feature that undermines this prevention mechanism?

If you want to give yourself a headache, consider all the ways that you can find a way evade XSS filtering: XSS Filter Evasion Cheat Sheet. You should also take a look at this question, it offers a broad discussion on user generated script injection: How to prevent Javascript injection attacks within user-generated HTML.

zero298
  • 25,467
  • 10
  • 75
  • 100
  • 1
    This is amazing! In running a test however I have discovered the text is truncated to 60 characters. I've added that to the question. – Tadhg Jun 06 '19 at 13:53
  • 2
    @Tadhg Ah, then I'm not sure how I would try and break it at that point. However, it's still a terrible idea to hinge your injection projection on converting to uppercase and limiting string length. Script injection is a big topic and needs complex rules to be anywhere near safe. – zero298 Jun 06 '19 at 13:58
  • @Tadhg 60 characters *in total* or 60 characters at one time? – VLAZ Jun 06 '19 at 13:58
  • There is text field, on keypress and the contents are written straight back to the html elsewhere on the page. – Tadhg Jun 06 '19 at 14:04
  • The issue is there is no protection and the uppercase is separate feature. I'm trying to produce a nice test case – Tadhg Jun 06 '19 at 14:05
  • @Tadhg then you are relying on security through random chance. What if the feature is removed or changed? – VLAZ Jun 06 '19 at 14:07
  • @VLAZ I've just discovered this so I'm trying to provide a simple test case to highlight the issue. It absolutely needs changing. – Tadhg Jun 06 '19 at 14:14
  • 1
    This reminds me of a somewhat-related question I asked on [Security.se] a long time ago: https://security.stackexchange.com/questions/18007/why-do-attackers-bother-trivially-obfuscating-their-source-code – msanford Jun 06 '19 at 14:51
0

If you use jQuery in your website, then you can simply reassign $ which will kill any code that uses it directly:

//some normal code
$("div").css("color", "red"); //boom!
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<SCRIPT>$ = "I COME FROM EVIL INPUT"</SCRIPT>

<div>Some content</div>

Yes, you can protect it via making sure jQuery is injected correctly into each script that needs it. That used to be pretty common when multiple libraries might grab the global $, so you'd ensure that the $ variable is correct:

//some normal code but this time protected
(function($) {
//        ^---<-- not using the global $ <-----
  $("div").css("color", "red");//             |
})(jQuery)//                                  |
// ^^^^^^-->---------------------->-----------^
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<SCRIPT>$ = "I COME FROM EVIL INPUT"</SCRIPT>

<div>Some content</div>

However, this has slightly fallen out of favour recently - it's usually just jQuery that uses $, so you don't always need to protect it. Are you sure every line where you have $ is not the global one?

If you are, then here is the next attack that is as simple as this one:

const someJSON = '{ "name" : "Fred", "age" : 42 }';

const obj = JSON.parse(someJSON); //boom!
console.log(obj.name);
<SCRIPT>JSON = "I COME FROM EVIL INPUT"</SCRIPT>

Do you use AJAX to communicate with the server? Or try to fetch stuff from localStorage? Well, I very much doubt you're as protective of JSON as of $ and I doubt you have custom JSON readers.

I hope you can see the pattern now - anything that's attached to window and is all caps can be targetted and thus cripple the application further.

I have little doubt that all caps JS can be manipulated to produce lowercase letters. I can't think of how right now, but when the attacker figures it out, you can expect even more brute but effective things:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<SCRIPT>$("HTML")["html"]("I COME FROM EVIL INPUT")</SCRIPT>
<!--               ^^^^ this needs to be lowercased...and boom! -->
<body>
  <div>Some content</div>

  <div>Some more content</div>

  <div>Final content</div>
</body>
VLAZ
  • 26,331
  • 9
  • 49
  • 67