javascript.express.security.audit.express-third-party-object-deserialization.express-third-party-object-deserialization

profile photo of semgrepsemgrep
Author
unknown
Download Count*

The following function call $SER.$FUNC accepts user controlled data which can result in Remote Code Execution (RCE) through Object Deserialization. It is recommended to use secure data processing alternatives such as JSON.parse() and Buffer.from().

Run Locally

Run in CI

Defintion

rules:
  - id: express-third-party-object-deserialization
    message: The following function call $SER.$FUNC accepts user controlled data
      which can result in Remote Code Execution (RCE) through Object
      Deserialization. It is recommended to use secure data processing
      alternatives such as JSON.parse() and Buffer.from().
    options:
      interfile: true
    metadata:
      interfile: true
      technology:
        - express
      category: security
      cwe:
        - "CWE-502: Deserialization of Untrusted Data"
      references:
        - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
      source_rule_url:
        - https://github.com/ajinabraham/njsscan/blob/75bfbeb9c8d72999e4d527dfa2548f7f0f3cc48a/njsscan/rules/semantic_grep/eval/eval_deserialize.yaml
      owasp:
        - A08:2017 - Insecure Deserialization
        - A08:2021 - Software and Data Integrity Failures
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: HIGH
      impact: HIGH
      confidence: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - "Insecure Deserialization "
    languages:
      - javascript
      - typescript
    severity: WARNING
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-either:
              - pattern-inside: function ... ($REQ, $RES) {...}
              - pattern-inside: function ... ($REQ, $RES, $NEXT) {...}
              - patterns:
                  - pattern-either:
                      - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...})
                      - pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...})
                  - metavariable-regex:
                      metavariable: $METHOD
                      regex: ^(get|post|put|head|delete|options)$
          - pattern-either:
              - pattern: $REQ.query
              - pattern: $REQ.body
              - pattern: $REQ.params
              - pattern: $REQ.cookies
              - pattern: $REQ.headers
              - pattern: $REQ.files.$ANYTHING.data.toString('utf8')
              - pattern: $REQ.files.$ANYTHING['data'].toString('utf8')
      - patterns:
          - pattern-either:
              - pattern-inside: |
                  ({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) =>
                  {...}
              - pattern-inside: |
                  ({ $REQ }: Request,$RES: Response) => {...}
          - focus-metavariable: $REQ
          - pattern-either:
              - pattern: params
              - pattern: query
              - pattern: cookies
              - pattern: headers
              - pattern: body
              - pattern: files.$ANYTHING.data.toString('utf8')
              - pattern: files.$ANYTHING['data'].toString('utf8')
    pattern-sinks:
      - pattern-either:
          - patterns:
              - pattern-either:
                  - pattern-inside: |
                      $SER = require('$IMPORT')
                      ...
                  - pattern-inside: |
                      import $SER from '$IMPORT'
                       ...
                  - pattern-inside: |
                      import * as $SER from '$IMPORT'
                      ...
              - metavariable-regex:
                  metavariable: $IMPORT
                  regex: ^(node-serialize|serialize-to-js)$
              - pattern: $SER.$FUNC(...)
              - metavariable-regex:
                  metavariable: $FUNC
                  regex: ^(unserialize|deserialize)$

Examples

express-third-party-object-deserialization.ts

var node_serialize = require("node-serialize")
var serialize_to_js = require('serialize-to-js');

module.exports.value = function (req,res){
	// ruleid: express-third-party-object-deserialization
	node_serialize.unserialize(req.files.products.data.toString('utf8'))
	// ok: express-third-party-object-deserialization
	fake.unserialize(req.files)
}


module.exports.value1 = function (req,res){
	var str = new Buffer(req.cookies.profile, 'base64').toString();
	// ruleid: express-third-party-object-deserialization
	serialize_to_js.deserialize(str)
	// ok: express-third-party-object-deserialization
	foo.deserialize(str)
}