Skip to content

Commit

Permalink
Fix location in mysql vulnerability (#4006)
Browse files Browse the repository at this point in the history
* Fix location in mysql vulnerability

* export logic to report evidence to reuse instead of copying

* Fix lint

* Improve refactor
  • Loading branch information
uurien authored and tlhunter committed Feb 12, 2024
1 parent f8b6f17 commit 1fdf994
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ const InjectionAnalyzer = require('./injection-analyzer')
const { SQL_INJECTION } = require('../vulnerabilities')
const { getRanges } = require('../taint-tracking/operations')
const { storage } = require('../../../../../datadog-core')
const { getIastContext } = require('../iast-context')
const { addVulnerability } = require('../vulnerability-reporter')
const { getNodeModulesPaths } = require('../path-line')

const EXCLUDED_PATHS = getNodeModulesPaths('mysql', 'mysql2', 'sequelize', 'pg-pool', 'knex')
Expand All @@ -16,9 +14,9 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
}

onConfigure () {
this.addSub('apm:mysql:query:start', ({ sql }) => this.analyze(sql, 'MYSQL'))
this.addSub('apm:mysql2:query:start', ({ sql }) => this.analyze(sql, 'MYSQL'))
this.addSub('apm:pg:query:start', ({ query }) => this.analyze(query.text, 'POSTGRES'))
this.addSub('apm:mysql:query:start', ({ sql }) => this.analyze(sql, undefined, 'MYSQL'))
this.addSub('apm:mysql2:query:start', ({ sql }) => this.analyze(sql, undefined, 'MYSQL'))
this.addSub('apm:pg:query:start', ({ query }) => this.analyze(query.text, undefined, 'POSTGRES'))

this.addSub(
'datadog:sequelize:query:start',
Expand All @@ -42,7 +40,7 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
getStoreAndAnalyze (query, dialect) {
const parentStore = storage.getStore()
if (parentStore) {
this.analyze(query, dialect, parentStore)
this.analyze(query, parentStore, dialect)

storage.enterWith({ ...parentStore, sqlAnalyzed: true, sqlParentStore: parentStore })
}
Expand All @@ -60,29 +58,10 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
return { value, ranges, dialect }
}

analyze (value, dialect, store = storage.getStore()) {
analyze (value, store, dialect) {
store = store || storage.getStore()
if (!(store && store.sqlAnalyzed)) {
const iastContext = getIastContext(store)
if (this._isInvalidContext(store, iastContext)) return
this._reportIfVulnerable(value, iastContext, dialect)
}
}

_reportIfVulnerable (value, context, dialect) {
if (this._isVulnerable(value, context) && this._checkOCE(context)) {
this._report(value, context, dialect)
return true
}
return false
}

_report (value, context, dialect) {
const evidence = this._getEvidence(value, context, dialect)
const location = this._getLocation()
if (!this._isExcluded(location)) {
const spanId = context && context.rootSpan && context.rootSpan.context().toSpanId()
const vulnerability = this._createVulnerability(this._type, evidence, spanId, location)
addVulnerability(context, vulnerability)
super.analyze(value, store, dialect)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ class Analyzer extends SinkIastPlugin {
return false
}

_report (value, context) {
const evidence = this._getEvidence(value, context)
_report (value, context, meta) {
const evidence = this._getEvidence(value, context, meta)
this._reportEvidence(value, context, evidence)
}

_reportEvidence (value, context, evidence) {
const location = this._getLocation(value)
if (!this._isExcluded(location)) {
const locationSourceMap = this._replaceLocationFromSourceMap(location)
Expand All @@ -33,9 +37,9 @@ class Analyzer extends SinkIastPlugin {
}
}

_reportIfVulnerable (value, context) {
_reportIfVulnerable (value, context, meta) {
if (this._isVulnerable(value, context) && this._checkOCE(context, value)) {
this._report(value, context)
this._report(value, context, meta)
return true
}
return false
Expand Down Expand Up @@ -71,11 +75,11 @@ class Analyzer extends SinkIastPlugin {
return store && !iastContext
}

analyze (value, store = storage.getStore()) {
analyze (value, store = storage.getStore(), meta) {
const iastContext = getIastContext(store)
if (this._isInvalidContext(store, iastContext)) return

this._reportIfVulnerable(value, iastContext)
this._reportIfVulnerable(value, iastContext, meta)
}

analyzeAll (...values) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ describe('sql-injection-analyzer', () => {
},
'../overhead-controller': { hasQuota: () => true }
})
sinon.stub(ProxyAnalyzer.prototype, '_reportEvidence')
const reportEvidence = ProxyAnalyzer.prototype._reportEvidence

const InjectionAnalyzer = proxyquire('../../../../src/appsec/iast/analyzers/injection-analyzer', {
'../taint-tracking/operations': TaintTrackingMock,
'./vulnerability-analyzer': ProxyAnalyzer
Expand All @@ -91,11 +94,11 @@ describe('sql-injection-analyzer', () => {
},
'../vulnerability-reporter': { addVulnerability }
})
proxiedSqlInjectionAnalyzer.analyze(TAINTED_QUERY, dialect)
expect(addVulnerability).to.have.been.calledOnce
expect(addVulnerability).to.have.been.calledWithMatch({}, {
type: 'SQL_INJECTION',
evidence: { dialect: dialect }
proxiedSqlInjectionAnalyzer.analyze(TAINTED_QUERY, undefined, dialect)
expect(reportEvidence).to.have.been.calledOnce
expect(reportEvidence).to.have.been.calledWithMatch(TAINTED_QUERY, {}, {
value: TAINTED_QUERY,
dialect
})
})

Expand Down

0 comments on commit 1fdf994

Please sign in to comment.