Skip to content
This repository has been archived by the owner on Dec 19, 2023. It is now read-only.

Mitigation for arbitrary code execution / sandbox breakout #1

Merged
merged 7 commits into from
Aug 3, 2020

Conversation

bbeale
Copy link

@bbeale bbeale commented Jul 30, 2020

📊 Metadata *

Bounty URL: https://www.huntr.dev/bounties/1-npm-safer-eval

⚙️ Description *

Mitigating potential sandbox breakout by checking user supplied input for statements that might be trying to manipulate system processes.

💻 Technical Description *

After a couple attempts at specifically addressing the RangeError mentioned in the disclosure, I ended up going with a simpler solution of checking the user supplied template literal for statements that might be trying to access system processes that they should not be accessing. This solution involves runInContext() logging a warning to the console and returning undefined if this situation is detected, otherwise it returns vm.runInContext the same as before.

🐛 Proof of Concept (PoC) *

Unit tests based on existing proofs of concept:
https://gist.github.com/JLLeitschuh/609bb2efaff22ed84fe182cf574c023a
commenthol#10
commenthol#11

    it('tries to breakout', function () {
      const maliciousFunction = function () {
        const f = Buffer.prototype.write
        const ft = {
          length: 10,
          utf8Write () {

          }
        }
        function r (i) {
          var x = 0
          try {
            x = r(i)
          } catch (e) {}
          if (typeof (x) !== 'number') { return x }
          if (x !== i) { return x + 1 }
          try {
            f.call(ft)
          } catch (e) {
            return e
          }
          return null
        }
        var i = 1
        while (1) {
          try {
            i = r(i).constructor.constructor('return process')()
            break
          } catch (x) {
            i++
          }
        }
        return i.mainModule.require('child_process').execSync('id').toString()
      }

      const evil = `(${maliciousFunction})()`
      const res = saferEval(evil)
      assert.strictEqual(res, undefined)
    })

    it('tries to breakout another way', function () {
      const anotherMaliciousFunction = function () {
        const process = clearImmediate.constructor('return process;')()
        return process.mainModule.require('child_process').execSync('whoami').toString()
      }
      const evil = `(${anotherMaliciousFunction})()`
      const res = saferEval(evil)
      assert.strictEqual(res, undefined)
    })

    it('tries to break out yet another way using setInterval', function () {
      const code = "setInterval.constructor('return" +
        " process')().mainModule.require('child_process').execSync('whoami').toString();"
      const res = saferEval(code)
      assert.strictEqual(res, undefined)
    })

    it('tries to break out yet another way using setInterval', function () {
      const code = "Buffer.of.constructor('return" +
        " process')().mainModule.require('child_process').execSync('whoami').toString();"
      const res = saferEval(code)
      assert.strictEqual(res, undefined)
    })

🔥 Proof of Fix (PoF) *

safer-eval-tests

Copy link

@toufik-airane toufik-airane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huntr

Copy link

@Mik317 Mik317 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome fix 😄 ❤️

Best,
Mik

@JamieSlome JamieSlome removed the request for review from mufeedvh August 3, 2020 11:10
@JamieSlome JamieSlome merged commit f7b56d6 into 418sec:master Aug 3, 2020
@huntr-helper
Copy link
Member

Congratulations bbeale - your fix has been selected! 🎉

Thanks for being part of the community & helping secure the world's open source code.
If you have any questions, please respond in the comments section. Your bounty is on its way - keep hunting!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
5 participants