Skip to content

Commit

Permalink
Detect atob (#143)
Browse files Browse the repository at this point in the history
* chore: update @nodesecure/estree-ast-utils (1.3.1 to 1.4.0)

* feat(isRequire): support atob obfuscation

* chore: update @nodesecure/estree-ast-utils (1.4.0 to 1.4.1)

* chore: use getCallExpressionArguments
  • Loading branch information
fraxken authored Sep 3, 2023
1 parent 3f29aab commit 6cb745f
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 65 deletions.
122 changes: 61 additions & 61 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,61 +1,61 @@
{
"name": "@nodesecure/js-x-ray",
"version": "6.1.1",
"description": "JavaScript AST XRay analysis",
"type": "module",
"exports": "./index.js",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"scripts": {
"lint": "eslint src test",
"prepublishOnly": "pkg-ok",
"test-only": "cross-env esm-tape-runner 'test/**/*.spec.js' | tap-monkey",
"test": "c8 --all --src ./src --reporter=lcov npm run test-only",
"check": "cross-env npm run lint && npm run test-only"
},
"repository": {
"type": "git",
"url": "git+https://github.com/NodeSecure/js-x-ray.git"
},
"keywords": [
"ast",
"nsecure",
"nodesecure",
"analysis",
"dependencies",
"security"
],
"files": [
"src",
"types",
"index.js",
"index.d.ts"
],
"author": "GENTILHOMME Thomas <gentilhomme.thomas@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/NodeSecure/js-x-ray/issues"
},
"homepage": "https://github.com/NodeSecure/js-x-ray#readme",
"dependencies": {
"@nodesecure/estree-ast-utils": "^1.3.1",
"@nodesecure/sec-literal": "^1.2.0",
"estree-walker": "^3.0.1",
"is-minified-code": "^2.0.0",
"meriyah": "^4.3.3",
"safe-regex": "^2.1.1"
},
"devDependencies": {
"@nodesecure/eslint-config": "^1.6.0",
"@slimio/is": "^2.0.0",
"@small-tech/esm-tape-runner": "^2.0.0",
"@small-tech/tap-monkey": "^1.4.0",
"@types/node": "^20.3.0",
"c8": "^8.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.31.0",
"pkg-ok": "^3.0.0",
"tape": "^5.6.1"
}
}
{
"name": "@nodesecure/js-x-ray",
"version": "6.1.1",
"description": "JavaScript AST XRay analysis",
"type": "module",
"exports": "./index.js",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"scripts": {
"lint": "eslint src test",
"prepublishOnly": "pkg-ok",
"test-only": "cross-env esm-tape-runner 'test/**/*.spec.js' | tap-monkey",
"test": "c8 --all --src ./src --reporter=lcov npm run test-only",
"check": "cross-env npm run lint && npm run test-only"
},
"repository": {
"type": "git",
"url": "git+https://github.com/NodeSecure/js-x-ray.git"
},
"keywords": [
"ast",
"nsecure",
"nodesecure",
"analysis",
"dependencies",
"security"
],
"files": [
"src",
"types",
"index.js",
"index.d.ts"
],
"author": "GENTILHOMME Thomas <gentilhomme.thomas@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/NodeSecure/js-x-ray/issues"
},
"homepage": "https://github.com/NodeSecure/js-x-ray#readme",
"dependencies": {
"@nodesecure/estree-ast-utils": "^1.4.1",
"@nodesecure/sec-literal": "^1.2.0",
"estree-walker": "^3.0.1",
"is-minified-code": "^2.0.0",
"meriyah": "^4.3.3",
"safe-regex": "^2.1.1"
},
"devDependencies": {
"@nodesecure/eslint-config": "^1.6.0",
"@slimio/is": "^2.0.0",
"@small-tech/esm-tape-runner": "^2.0.0",
"@small-tech/tap-monkey": "^1.4.0",
"@types/node": "^20.3.0",
"c8": "^8.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.31.0",
"pkg-ok": "^3.0.0",
"tape": "^5.6.1"
}
}
20 changes: 16 additions & 4 deletions src/probes/isRequire.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
concatBinaryExpression,
arrayExpressionToString,
getMemberExpressionIdentifier,
getCallExpressionIdentifier
getCallExpressionIdentifier,
getCallExpressionArguments
} from "@nodesecure/estree-ast-utils";

function validateNode(node, { tracer }) {
Expand Down Expand Up @@ -89,7 +90,7 @@ function main(node, options) {

// require(Buffer.from("...", "hex").toString());
case "CallExpression": {
walkRequireCallExpression(arg)
walkRequireCallExpression(arg, tracer)
.forEach((depName) => analysis.dependencies.add(depName, node.loc, true));

analysis.addWarning("unsafe-import", null, node.loc);
Expand All @@ -103,7 +104,7 @@ function main(node, options) {
}
}

function walkRequireCallExpression(nodeToWalk) {
function walkRequireCallExpression(nodeToWalk, tracer) {
const dependencies = new Set();

walk(nodeToWalk, {
Expand All @@ -122,8 +123,19 @@ function walkRequireCallExpression(nodeToWalk) {
const fullName = node.callee.type === "MemberExpression" ?
[...getMemberExpressionIdentifier(node.callee)].join(".") :
node.callee.name;
const tracedFullName = tracer.getDataFromIdentifier(fullName)?.name ?? fullName;

switch (tracedFullName) {
case "atob": {
const nodeArguments = getCallExpressionArguments(node, { tracer });
if (nodeArguments !== null) {
dependencies.add(
Buffer.from(nodeArguments.at(0), "base64").toString()
);
}

switch (fullName) {
break;
}
case "Buffer.from": {
const [element] = node.arguments;

Expand Down
20 changes: 20 additions & 0 deletions test/probes/isRequire.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,23 @@ test("(require CallExpression): it should detect MemberExpression require.resolv

tape.end();
});

test("(require CallExpression): it should detect obfuscated atob value", (tape) => {
const str = `
const myFunc = atob;
const ff = myFunc('b3' + 'M=');
const dep = require(ff);
`;
const ast = parseScript(str);
const sastAnalysis = getSastAnalysis(str, isRequire)
.execute(ast.body);

tape.strictEqual(sastAnalysis.warnings().length, 0);

const dependencies = sastAnalysis.dependencies();
tape.strictEqual(Object.keys(dependencies).length, 1);
tape.ok("os" in dependencies);

tape.end();
});

0 comments on commit 6cb745f

Please sign in to comment.