UNPKG

@hclsoftware/secagent

Version:

IAST agent

93 lines (84 loc) 4.38 kB
//IASTIGNORE /* * **************************************************** * Licensed Materials - Property of HCL. * (c) Copyright HCL Technologies Ltd. 2017, 2025. * Note to U.S. Government Users *Restricted Rights. * **************************************************** */ 'use strict' const VerificationTracker = require('../Verification/VerificationTracker') const Vulnerability = require('../Vulnerability') const SinkTask = require('./SinkTask') const TaskType = require('./TaskType') const IastLogger = require('../Logger/IastLogger') const logger = IastLogger.eventLog const TaintTracker = require('../TaintTracker') const {ParameterUnderTest} = require('./ParameterUnderTest') const SinkTaskInfo = require("./SinkInfo/SinkTaskInfo") const ContextType = require("./ContextType"); const {SinkInfoStringGenerator} = require("./SinkInfo/SinkInfoStringGenerator") const AdditionalInfo = require("../AdditionalInfo") class PathTraversalSinkTask extends SinkTask.SinkTask { constructor(source, vulnerability, stack, parameters, obj){ super(source, vulnerability, stack, parameters) this.taskType = TaskType.PATH_TRAVERSAL this.sinkStr = obj } performAction() { const parameterUnderTest = new ParameterUnderTest(this.taintedObjectFlow.entity.value, this.taintedObjectFlow.taskList) // check control const source = parameterUnderTest.originalProcessedParam const sinkWithSlash = this.sinkStr + "/" const sinkWithoutExtension = this.removeExtension(this.sinkStr) let vulnerabilitySanitized = true let exploitExample = null let sinkTaskInfo = null const signature = this.getTasksInfo() const verified = VerificationTracker.getVerifiedState(signature, this.vulnerability) if (verified == null) { logger.debug(`Checking vulnerability ${Vulnerability} for signature ${signature}`) for (const currExploit of exploits) { const processingResult = parameterUnderTest.getMutatedProcessedParam(currExploit) const processedLegitimateExploitForCodePath = processingResult.afterProcessing if( processedLegitimateExploitForCodePath !=null && (processedLegitimateExploitForCodePath.origStringIncludes('..\\') || processedLegitimateExploitForCodePath.origStringIncludes('../'))){ vulnerabilitySanitized = false exploitExample = currExploit break } } if (vulnerabilitySanitized){ logger.debug(`Signature ${signature} is verified as a sanitizer`) } else { logger.debug(`Signature ${signature} is verified as vulnerable`) } sinkTaskInfo = new SinkTaskInfo(exploitExample, [ContextType["PATH"].contextTypeName], exploits, this.vulnerability) VerificationTracker.setSignatureAsVerified(signature, this.vulnerability, vulnerabilitySanitized, sinkTaskInfo) } else { logger.debug(`Signature ${signature} was already verified`) sinkTaskInfo = verified.sinkInfo vulnerabilitySanitized = verified.verifiedOk } if(vulnerabilitySanitized) { this.taintedObjectFlow.sanitize(this.vulnerability) } else { let additionalInfoEntry = source != null && !(this.sinkStr.origEndsWith(source) || sinkWithSlash.origEndsWith(source) || sinkWithoutExtension.origEndsWith(source)) ? {[AdditionalInfo.keys.PATH_TRAVERSAL_PARTIAL_CONTROL]:"Note that this issue is partial path traversal, end of path is out of user control" } : null TaintTracker.sinkTaskTrigger(this.taintedObjectFlow, this.vulnerability, new SinkInfoStringGenerator(sinkTaskInfo), true, this.stack, this.parameters, additionalInfoEntry) } return !vulnerabilitySanitized } removeExtension(filename){ let index = filename.origLastIndexOf(".") return (index === -1) ? filename : filename.origSlice(0,index) } } // "..\\", "../", "..././", "...\\.\\", "%2e%2e%2f", "%252e%252e%252f", "%252e%252e%255c", "\u002e\u002e\u2215", "\uff0e\uff0e\u2215", "\uff0e\uff0e\u2216" const exploits = [ "..\\", "../", "..././", "...\\.\\" ] module.exports = PathTraversalSinkTask