UNPKG

@hclsoftware/secagent

Version:

IAST agent

717 lines (712 loc) 16.8 kB
//IASTIGNORE /* * **************************************************** * Licensed Materials - Property of HCL. * (c) Copyright HCL Technologies Ltd. 2017, 2025. * Note to U.S. Government Users *Restricted Rights. * **************************************************** */ const { Vulnerability } = require('../TaintTracker') const HookType = require('../Rules/HookRules/HookRuleFactory').Type const BeforeType = require('../Rules/BeforeRules/BeforeRuleFactory').Type const CONSTRUCTOR_NAME = require('../Hooks/HookValues').CONSTRUCTOR_NAME /** * These hooks which are read by setRequireHook Function, to return origModule from require() call, after replacing the methods with proxy. * See instructions for adding a new hook in Hooks.js. * @see HookParser.setRequireHook */ const requireHooks = { bcrypt: [ { methodName: ['hash', 'hashSync', 'compareSync'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0', '1'] } ] }, { methodName: ['compare'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: 'all' } ] } ], bcryptjs: [ { methodName: ['hash', 'hashSync', 'compareSync'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0', '1'] } ] }, { methodName: ['compare'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: 'all' } ] } ], mongodb: [ { scopes: ['Collection', 'prototype'], methodName: 'find', taintCondition: ['0'], beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { return: CONSTRUCTOR_NAME, that: 'mongodb.Collection' } } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.SQL_INJECTION } ] } ], sequelize: [ { scopes: ['prototype'], methodName: 'query', taintCondition: ['0'], beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'sequelize' } } ], rules: [ { type: HookType.SEQUELIZE_SINK, from: '0', vulnerability: Vulnerability.SQL_INJECTION } ] }, { scopes: ['Model'], methodName: ['create'], taintCondition: ['args'], beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'Sequelize.Model' } } ], rules: [ { type: HookType.SINK, from: 'args', vulnerability : Vulnerability.PASSWORD_LEAKAGE_DB } ] } ], child_process: [ { methodName: ['exec','execSync'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { return: CONSTRUCTOR_NAME, that: 'child_process' } } ], rules: [ { type: HookType.COMMAND_INJECTION_CHECK_ARGS_SINK, from: '0', vulnerability: Vulnerability.COMMAND_INJECTION } ] }, { methodName: ['spawn', 'spawnSync'], taintCondition: ['args'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { return: CONSTRUCTOR_NAME, that: 'child_process' } } ], rules: [ { type: HookType.COMMAND_INJECTION_CHECK_ARGS_SINK, from: 'args', vulnerability: Vulnerability.COMMAND_INJECTION } ] } ], sqlite3: [ { scopes: ['Database', 'prototype'], methodName: ['run','each','get','all'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] }, { type: BeforeType.ARG_OBJECTS_TO_STRING, applyFor: ['1'] } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.SQL_INJECTION } ] }, { scopes: ['Database', 'prototype'], methodName: 'prepare', taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.SQL_INJECTION } ] } ], path: [ { methodName: ['join', 'resolve'], taintCondition: ['args'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: 'all' }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'path' } } ], rules: [ { type: HookType.PROPAGATOR_ARRAY_SOURCE, from: 'args', to: 'return' } ] }, { methodName: ['basename', 'dirname', 'normalize', 'parse', 'extname', 'toNameSpacePath'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: 'all' // to cover also optional basename argument 'ext' }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'path' } } ], rules: [ { type: HookType.PROPAGATOR, from: '0', to : 'return' } ] } ], fs: [ // to string on index 0 { methodName: ['access', 'accessSync', 'lstat', 'lstatSync', 'lutimes', 'lutimesSync', 'stat', 'statSync', 'unwatchFile', 'utimes', 'utimesSync', 'watchFile'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] } ] }, { methodName: ['existsSync', 'join'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: 'all' } ] }, // sink and to_string for index 0 { methodName: ['appendFile', 'appendFileSync', 'chmod', 'chmodSync', 'chown', 'chownSync', 'createReadStream', 'createWriteStream', 'lchmod', 'lchmodSync', 'lchown', 'lchownSync', 'mkdir', 'mkdirSync', 'open', 'openSync', 'readFile', 'readFileSync', 'readdir', 'readdirSync', 'opendir', 'opendirSync', 'readlink', 'readlinkSync', 'rmdir', 'rmdirSync', 'rm', 'rmSync', 'truncate', 'truncateSync', 'unlink', 'unlinkSync', 'writeFileSync'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'fs' } }], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.PATH_TRAVERSAL }] }, // sink for indix 0 and to_string for indices 0, 1: { methodName: ['writeFile'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0', '1'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: {that: 'fs'} } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.PATH_TRAVERSAL } ] }, // sink and to_string for indices 0, 1 { methodName: ['rename', 'renameSync', 'symlink', 'symlinkSync', 'copyFile', 'copyFileSync', 'link', 'linkSync'], taintCondition: ['0', '1'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0', '1'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: {that: 'fs'} } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.PATH_TRAVERSAL }, { type: HookType.SINK, from: '1', vulnerability: Vulnerability.PATH_TRAVERSAL } ] }, // fs propagators { methodName: ['realpathSync'], taintCondition: ['0'], rules: [ { type: HookType.PROPAGATOR, from: '0', to: 'return' } ] }, // realpath returns the resolved path to a callback that gets two arguments (err, resolvedPath) { methodName: ['realpath'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.WRAP_CALLBACK_REALPATH } ], callbackRules: [ { type: HookType.PROPAGATOR, from: '0', to: 'callbackArg' } ] }, // to string on index 0 for fsPromises { scopes: ['promises'], methodName: ['access', 'lstat', 'lutimes', 'stat', 'utimes'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] }] }, // sink and to_string for index 0 for fs.promises { scopes: ['promises'], methodName: ['appendFile', 'chmod','chown', 'lchmod', 'lchown', 'mkdir', 'open', 'readFile', 'readdir', 'readlink', 'rmdir', 'truncate', 'unlink', 'writeFile', 'opendir', 'rm'], taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'fs' } } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.PATH_TRAVERSAL } ] }, // sink and to_string for index 1 for fs.promises { scopes: ['promises'], methodName: ['copyFile', 'link', 'rename', 'symlink'], taintCondition: ['0', '1'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['1'] }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'fs' } } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.PATH_TRAVERSAL }, { type: HookType.SINK, from: '1', vulnerability: Vulnerability.PATH_TRAVERSAL } ] } ], url: [ { methodName: 'URL', // we need both this hook and the one in Hooks.js file for URL constructor. rules: [ { type: HookType.PROPAGATOR_ARRAY_SOURCE, from: 'args', to: 'return' }, { type: HookType.PROPAGATOR_ON_GETTERS, targetProperties: ['host', 'hostname', 'href', 'origin', 'pathname', 'search'] }, { type: HookType.PROPAGATOR_ON_SETTERS, targetProperties: ['host', 'hostname', 'href', 'pathname', 'search'] } ] }, { scopes: ['Url', 'prototype'], methodName: 'parse', taintCondition: ['0'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] } ], rules: [ { type: HookType.PROPAGATOR, from: '0', to: 'return' } ] } ], xpath: [ { methodName: ['select', 'useNamespaces'], beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { return: 'NodeElement', 1 : 'Document'} } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.XPATH_INJECTION } ] } ], http: [ { scopes: ['ClientRequest', 'prototype'], //maybe hook OutgoingMessage (the base class) instead of ClientRequest methodName: ['end', 'write'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] } ], } ], jsonwebtoken:[ { methodName: 'sign', beforeRules: [ { type: BeforeType.ARG_OBJECTS_TO_STRING, applyFor: ['0', '1'] } ], rules: [ { type: HookType.PROPAGATOR, from: '0', to: 'return', } ] }, { methodName: 'decode', beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'], } ], rules: [ { type: HookType.PROPAGATOR, from: '0', to: 'return', } ] }, { methodName: 'verify', beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0','1'], } ], rules: [ { type: HookType.PROPAGATOR, from: '0', to: 'return', } ] }, ], stream: [ { scopes: ['Transform', '__proto__', 'prototype'], methodName: 'write', beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] } ], }, { scopes: ['Writable', 'prototype'], methodName: 'write', beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'] } ], }, ], libxmljs: [ { methodName: ['parseXmlString', 'parseXml'], rules: [ { type: HookType.XXE_SINK, from: '0' }] } ], ldapjs: [ { scopes: ['Client', 'prototype'], methodName: ['search'], beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'Client'} } ], rules: [ { type: HookType.SINK, from: '0', vulnerability: Vulnerability.LDAP_INJECTION }] } ], axios: [ { scopes: ['Axios', 'prototype'], methodName: ['_request'], // _request does not exist in old versions of axios (e.g "0.20.0"). Consider change to 'request' instead beforeRules: [ { type: BeforeType.ARG_OBJECTS_TO_STRING, applyFor: 'all', }, { type: BeforeType.CLONE_HOOKS_VALUES, }, { type: BeforeType.AXIOS_SINK, from: 'args', }, { type: BeforeType.AXIOS_SINK, from: 'that', }, { type: BeforeType.AXIOS_GET_TAGS_FROM_FIELDS, }, { type: BeforeType.AXIOS_SENDER, from: 'that', }, ], rules: [ { type: HookType.AXIOS_SOURCE, to: 'return', }, ] } ], "./lib/callback_model": [ { scopes: ['Channel', 'prototype'], methodName: 'publish', beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'RabbitMQ.Channel'} }, { type: BeforeType.RABBITMQ_SENDER, }, ], }, { scopes: ['Channel', 'prototype'], methodName: 'assertQueue', beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'], } ] } ], "./lib/channel_model": [ { scopes: ['Channel', 'prototype'], methodName: 'publish', beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'], }, { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'RabbitMQ.Channel'} }, { type: BeforeType.RABBITMQ_SENDER, }, ], }, { scopes: ['Channel', 'prototype'], methodName: ['assertQueue'], beforeRules: [ { type: BeforeType.ARGS_TO_STRING, applyFor: ['0'], } ] } ], "./channel": [ { scopes: ['BaseChannel', 'prototype'], methodName: 'handleDelivery', beforeRules: [ { type: BeforeType.ADD_HOOK_VALUE_NAMES, hookValueNames: { that: 'RabbitMQ.BaseChannel'} }, { type: BeforeType.REGISTER_TAINT_ON_RABBITMQ_MESSAGE, }, { type: BeforeType.RABBITMQ_RECEIVER, } ] } ] } module.exports = requireHooks