Skip to content

Python Taint Flow: False negative when taint originates in default value of function argument #2749

Open
@gbleaney

Description

@gbleaney

I'm trying to catch CVE-2019-19775 with CodeQL. The flow is from the REQ function called to create the default argument value, to the redirect function call:

@has_request_variables
def backend_serve_thumbnail(request: HttpRequest, user_profile: UserProfile,
                            url: str=REQ(), size_requested: str=REQ("size")) -> HttpResponse:
    ...
    thumbnail_url = generate_thumbnail_url(url, size)
    return redirect(thumbnail_url)

This is the code I've been using (yes I know I'm reinventing the wheel, but I wanted to make the example self contained and do some sanity checking):

import python
import semmle.python.security.TaintTracking
import semmle.python.web.HttpRequest

class ZulipReqSource extends TaintTracking::Source {
    ZulipReqSource() {
        exists( FunctionValue f | f.getName() = "REQ" and f.getACall() = this)
    }
    override predicate isSourceOf(TaintKind kind) { kind instanceof DjangoRequest }
    override string toString() { result = "Zulip's custom 'Req' source" }
}

class RedirectSink extends TaintTracking::Sink {
    RedirectSink() {
        Module::named("django").attr("redirect").getACall().getArg(0) = this
    }
    override predicate sinks(TaintKind kind) {
        kind instanceof DjangoRequest
    }
    override string toString() { result = "Django's redirect sink" }
}

class UrlRedirectConfiguration extends TaintTracking::Configuration {
    UrlRedirectConfiguration() { this = "URL redirect configuration" }
    override predicate isSource(TaintTracking::Source source) {
        source instanceof ZulipReqSource
    }
    override predicate isSink(TaintTracking::Sink sink) {
        sink instanceof RedirectSink
    }
}

from UrlRedirectConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink() , src, sink, "This argument to 'unsafe' depends on $@.", src.getSource(), "a user-provided value"

I can't seem to catch the flow when running on the Zulip database from lgtm.com. As best I can tell, I think taint flow through the defaulted parameter might not be being tracked properly. If I run the above code, but swap generate_thumbnail_url for REQ, it works and I am able to catch the flow from generate_thumbnail_url -> redirect

Metadata

Metadata

Assignees

No one assigned

    Labels

    PythonquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions