mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Add Net::HTTP request modelling
This commit is contained in:
71
ql/lib/codeql/ruby/frameworks/stdlib/net/HTTP.qll
Normal file
71
ql/lib/codeql/ruby/frameworks/stdlib/net/HTTP.qll
Normal file
@@ -0,0 +1,71 @@
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.dataflow.internal.DataFlowPublic
|
||||
|
||||
/**
|
||||
* A shortcut for uses of Net::HTTP
|
||||
*/
|
||||
private API::Node netHTTP() { result = API::getTopLevelMember("Net").getMember("HTTP") }
|
||||
|
||||
/**
|
||||
* A call that returns the response body of a `Net::HTTP` request as a String.
|
||||
* ```ruby
|
||||
* req = Net::HTTP.new("example.com")
|
||||
* response = req.get("/")
|
||||
* body = response.body
|
||||
* ```
|
||||
*/
|
||||
private class NetHTTPRequestResponseBody extends CallNode {
|
||||
DataFlow::CallNode requestCall;
|
||||
|
||||
NetHTTPRequestResponseBody() {
|
||||
exists(string methodName, API::Node requestCallNode |
|
||||
requestCall = requestCallNode.getAnImmediateUse()
|
||||
|
|
||||
// Net::HTTP.get(...)
|
||||
methodName = "get" and
|
||||
requestCallNode = netHTTP().getReturn(methodName) and
|
||||
this = requestCall
|
||||
or
|
||||
// Net::HTTP.post(...).body
|
||||
methodName in ["post", "post_form"] and
|
||||
requestCallNode = netHTTP().getReturn(methodName) and
|
||||
this = requestCallNode.getAMethodCall(["body", "read_body", "entity"])
|
||||
or
|
||||
// Net::HTTP.new(..).get(..).body
|
||||
methodName in [
|
||||
"get", "get2", "request_get", "head", "head2", "request_head", "delete", "put", "patch",
|
||||
"post", "post2", "request_post", "request"
|
||||
] and
|
||||
requestCallNode = netHTTP().getInstance().getReturn(methodName) and
|
||||
this = requestCallNode.getAMethodCall(["body", "read_body", "entity"])
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node representing the method call that initiates the request.
|
||||
* This may be different from the node which returns the response body.
|
||||
*/
|
||||
DataFlow::Node getRequestCall() { result = requestCall }
|
||||
|
||||
/**
|
||||
* Gets the node representing the URL of the request.
|
||||
* Currently unused, but may be useful in future, e.g. to filter out certain requests.
|
||||
*/
|
||||
DataFlow::Node getURLArgument() { result = requestCall.getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Net::HTTP` call which initiates an HTTP request.
|
||||
*/
|
||||
class NetHTTPRequest extends HTTP::Client::Request::Range {
|
||||
private NetHTTPRequestResponseBody responseBody;
|
||||
|
||||
NetHTTPRequest() { this = responseBody.getRequestCall().asExpr().getExpr() }
|
||||
|
||||
override DataFlow::Node getResponseBody() { result = responseBody }
|
||||
|
||||
override string getFramework() { result = "Net::HTTP" }
|
||||
}
|
||||
27
ql/test/library-tests/frameworks/stdlib/net/HTTP.rb
Normal file
27
ql/test/library-tests/frameworks/stdlib/net/HTTP.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
require "net/http"
|
||||
|
||||
uri = URI.parse("https://example.com")
|
||||
Net::HTTP.get(uri)
|
||||
|
||||
resp = Net::HTTP.post(URI.parse(uri), "some_body")
|
||||
resp.body
|
||||
resp.read_body
|
||||
resp.entity
|
||||
|
||||
req = Net::HTTP.new("https://example.com")
|
||||
|
||||
r1 = req.get("/")
|
||||
r2 = req.post("/")
|
||||
r3 = req.put("/")
|
||||
r4 = req.patch("/")
|
||||
|
||||
r1.body
|
||||
r2.read_body
|
||||
r3.entity
|
||||
r4.foo
|
||||
|
||||
def get(domain, path)
|
||||
Net::HTTP.new(domain).get(path)
|
||||
end
|
||||
|
||||
get("example.com", "/").body
|
||||
@@ -0,0 +1,8 @@
|
||||
| HTTP.rb:4:1:4:18 | call to get | HTTP.rb:4:1:4:18 | call to get |
|
||||
| HTTP.rb:6:8:6:50 | call to post | HTTP.rb:7:1:7:9 | call to body |
|
||||
| HTTP.rb:6:8:6:50 | call to post | HTTP.rb:8:1:8:14 | call to read_body |
|
||||
| HTTP.rb:6:8:6:50 | call to post | HTTP.rb:9:1:9:11 | call to entity |
|
||||
| HTTP.rb:13:6:13:17 | call to get | HTTP.rb:18:1:18:7 | call to body |
|
||||
| HTTP.rb:14:6:14:18 | call to post | HTTP.rb:19:1:19:12 | call to read_body |
|
||||
| HTTP.rb:15:6:15:17 | call to put | HTTP.rb:20:1:20:9 | call to entity |
|
||||
| HTTP.rb:24:3:24:33 | call to get | HTTP.rb:27:1:27:28 | call to body |
|
||||
4
ql/test/library-tests/frameworks/stdlib/net/Http.ql
Normal file
4
ql/test/library-tests/frameworks/stdlib/net/Http.ql
Normal file
@@ -0,0 +1,4 @@
|
||||
import codeql.ruby.frameworks.stdlib.net.HTTP
|
||||
import codeql.ruby.DataFlow
|
||||
|
||||
query DataFlow::Node netHTTPRequests(NetHTTPRequest e) { result = e.getResponseBody() }
|
||||
Reference in New Issue
Block a user