最近のJavaScriptフレームワークでのXSS

所謂、最近流行っているJavaScriptフレームワークでのXSSの例をいくつか挙げようと思う。 最近のJavaScriptフレームワークは賢いので、データをバインドする際にHTMLエスケープしてくれてXSSから保護してくれる。 しかしながら、保護が適用されないケースもあるため、過度にフレームワークに信頼しているとXSSを作り込んでしまう。 ここではReactとVue.jsでその例をいくつか挙げようと思う。 あくまで「やってしまうかもしれない例」というだけで、ReactやVue.jsの固有の問題というわけではないです。 React javascript:スキーム aタグのhref属性にjavascript:やdata:text/htmlなどの任意のスキームをユーザーが設定できる場合、XSSが生じる。 これはReactに限った話ではなく、古くからある手法だが、未だにたまに見る。 import React, { Component } from 'react'; class App extends Component { render() { return ( <div className="App"> <a href={this.props.link}>{this.props.link}</a> </div> ); } } ReactDOM.render(<App link="javascript:alert(1)" />, document.getElementById('root')); 対策としてはスキームをhttp://かhttps://のみに制限するなどする。 ユーザーが任意のpropsを注入できる場合 https://hackerone.com/reports/49652 にあるように、ユーザーの入力値をそのままReact.createElementのpropsとして渡した場合などにはXSSが生じる。 import React from 'react'; import ReactDOM from 'react-dom'; // const props = JSON.parse('{"name": "foo"}'); const props = JSON.parse('{"name": {"dangerouslySetInnerHTML" : { "__html": "<svg/onload=alert(1)>"}}}'); ReactDOM.render(React.createElement("p", props.name), document.getElementById('root')) dangerouslySetInnerHTML はい。 https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml