Skip to content

Support Java wait/notify pattern #6296

@pwntester

Description

@pwntester

In some cases, CodeQL may not be able to follow a data flow where tainted data is stored in a class field on a synchronized block which then calls notify or notifyAll to awake a thread which in turn end up using the tainted field into a sink.

A good example is the code injection vulnerability described in this SonarSource Blog post.

I was able to get the issue reported by adding a new TaintStep which models the wait/notify pattern by connecting fields writes on a synchronized version calling notify with the same field reads on a synchronized version calling wait:

class NotifyWaitTaintStep extends TaintTracking::AdditionalTaintStep {
  override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
    exists(MethodAccess notify, RefType t, MethodAccess wait, SynchronizedStmt notifySync, SynchronizedStmt waitSync |

      notify.getMethod().getName() = ["notify", "notifyAll"] and
      notify.getAnEnclosingStmt() = notifySync and
      notifySync.getExpr().getType() = t and

      wait.getMethod().getName() = "wait" and
      wait.getAnEnclosingStmt() = waitSync and
      waitSync.getExpr().getType() = t and

      exists(AssignExpr write, FieldAccess read, Field f |
        write.getAnEnclosingStmt() = notifySync and
        write.getDest().(FieldAccess).getField() = f and
        write = n1.asExpr() and

        read.getAnEnclosingStmt() = waitSync and
        read.getField() = f and
        read = n2.asExpr()
      )
    )
  }
}

The taint step may need improvements though, but I think is a good starting point.

Metadata

Metadata

Assignees

No one assigned

    Labels

    JavaquestionFurther information is requested

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions