Model the HTTPClient http client

This commit is contained in:
Harry Maclean
2021-09-27 14:44:25 +01:00
parent 3a4ddc4b4e
commit ca1fc44f21
5 changed files with 80 additions and 0 deletions

View File

@@ -7,3 +7,4 @@ private import codeql.ruby.frameworks.http_clients.Excon
private import codeql.ruby.frameworks.http_clients.Faraday
private import codeql.ruby.frameworks.http_clients.RestClient
private import codeql.ruby.frameworks.http_clients.HTTParty
private import codeql.ruby.frameworks.http_clients.HTTPClient

View File

@@ -0,0 +1,40 @@
private import ruby
private import codeql.ruby.Concepts
private import codeql.ruby.ApiGraphs
/**
* A call that makes an HTTP request using `HTTPClient`.
* ```ruby
* HTTPClient.get("http://example.com").body
* HTTPClient.get_content("http://example.com")
* ```
*/
class HTTPClientRequest extends HTTP::Client::Request::Range {
DataFlow::Node request;
DataFlow::CallNode responseBody;
HTTPClientRequest() {
exists(API::Node requestNode, string method |
request = requestNode.getAnImmediateUse() and
method in [
"get", "head", "delete", "options", "post", "put", "trace", "get_content", "post_content"
]
|
requestNode = API::getTopLevelMember("HTTPClient").getReturn(method) and
(
// The `get_content` and `post_content` methods return the response body as a string.
// The other methods return a `HTTPClient::Message` object which has various methods
// that return the response body.
method in ["get_content", "post_content"] and responseBody = request
or
not method in ["get_content", "put_content"] and
responseBody = requestNode.getAMethodCall(["body", "http_body", "content", "dump"])
) and
this = request.asExpr().getExpr()
)
}
override DataFlow::Node getResponseBody() { result = responseBody }
override string getFramework() { result = "HTTPClient" }
}

View File

@@ -0,0 +1,9 @@
| HTTPClient.rb:3:9:3:45 | call to get | HTTPClient.rb:4:1:4:10 | call to body |
| HTTPClient.rb:6:9:6:65 | call to post | HTTPClient.rb:7:1:7:13 | call to content |
| HTTPClient.rb:9:9:9:64 | call to put | HTTPClient.rb:10:1:10:15 | call to http_body |
| HTTPClient.rb:12:9:12:48 | call to delete | HTTPClient.rb:13:1:13:10 | call to dump |
| HTTPClient.rb:15:9:15:46 | call to head | HTTPClient.rb:16:1:16:10 | call to body |
| HTTPClient.rb:18:9:18:49 | call to options | HTTPClient.rb:19:1:19:13 | call to content |
| HTTPClient.rb:21:9:21:47 | call to trace | HTTPClient.rb:22:1:22:15 | call to http_body |
| HTTPClient.rb:24:9:24:53 | call to get_content | HTTPClient.rb:24:9:24:53 | call to get_content |
| HTTPClient.rb:26:10:26:74 | call to post_content | HTTPClient.rb:26:10:26:74 | call to post_content |

View File

@@ -0,0 +1,4 @@
import codeql.ruby.frameworks.http_clients.HTTPClient
import codeql.ruby.DataFlow
query DataFlow::Node httpClientRequests(HTTPClientRequest e) { result = e.getResponseBody() }

View File

@@ -0,0 +1,26 @@
require "httpclient"
resp1 = HTTPClient.get("http://example.com/")
resp1.body
resp2 = HTTPClient.post("http://example.com/", body: "some_data")
resp2.content
resp3 = HTTPClient.put("http://example.com/", body: "some_data")
resp3.http_body
resp5 = HTTPClient.delete("http://example.com/")
resp5.dump
resp6 = HTTPClient.head("http://example.com/")
resp6.body
resp7 = HTTPClient.options("http://example.com/")
resp7.content
resp8 = HTTPClient.trace("http://example.com/")
resp8.http_body
resp9 = HTTPClient.get_content("http://example.com/")
resp10 = HTTPClient.post_content("http://example.com/", body: "some_data")