Skip to content

Commit bdb143c

Browse files
authored
Merge pull request github#10913 from thiggy1342/expand-ruby-ssrf-sinks-faraday-connection-new
Ruby: Add Faraday::Connection.new as sink for SSRF query
2 parents fac383a + 9c1fbfd commit bdb143c

File tree

6 files changed

+41
-8
lines changed

6 files changed

+41
-8
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
5+
- Instantiations using `Faraday::Connection.new` are now recognized as part of `FaradayHttpRequest`s, meaning they will be considered as sinks for queries such as `rb/request-forgery`.

ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ class FaradayHttpRequest extends Http::Client::Request::Range, DataFlow::CallNod
3434
// one-off requests
3535
API::getTopLevelMember("Faraday"),
3636
// connection re-use
37-
API::getTopLevelMember("Faraday").getInstance()
37+
API::getTopLevelMember("Faraday").getInstance(),
38+
// connection re-use with Faraday::Connection.new instantiation
39+
API::getTopLevelMember("Faraday").getMember("Connection").getInstance()
3840
] and
3941
requestNode =
4042
connectionNode

ruby/ql/test/library-tests/frameworks/http_clients/Faraday.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@
3333

3434
connection = Faraday.new(url: "http://example.com")
3535
resp11 = connection.get("/")
36-
resp11.body
36+
resp11.body
37+
38+
connection = Faraday::Connection.new(url: "https://example.com")
39+
resp12 = connection.get("/")
40+
resp12.body

ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
| Faraday.rb:35:10:35:28 | call to get | Faraday | Faraday.rb:34:26:34:50 | Pair | Faraday.rb:36:1:36:11 | call to body |
2929
| Faraday.rb:35:10:35:28 | call to get | Faraday | Faraday.rb:34:31:34:50 | "http://example.com" | Faraday.rb:36:1:36:11 | call to body |
3030
| Faraday.rb:35:10:35:28 | call to get | Faraday | Faraday.rb:35:25:35:27 | "/" | Faraday.rb:36:1:36:11 | call to body |
31+
| Faraday.rb:39:10:39:28 | call to get | Faraday | Faraday.rb:38:38:38:63 | Pair | Faraday.rb:40:1:40:11 | call to body |
32+
| Faraday.rb:39:10:39:28 | call to get | Faraday | Faraday.rb:38:43:38:63 | "https://example.com" | Faraday.rb:40:1:40:11 | call to body |
33+
| Faraday.rb:39:10:39:28 | call to get | Faraday | Faraday.rb:39:25:39:27 | "/" | Faraday.rb:40:1:40:11 | call to body |
3134
| HttpClient.rb:3:9:3:45 | call to get | HTTPClient | HttpClient.rb:3:24:3:44 | "http://example.com/" | HttpClient.rb:4:1:4:10 | call to body |
3235
| HttpClient.rb:6:9:6:65 | call to post | HTTPClient | HttpClient.rb:6:25:6:45 | "http://example.com/" | HttpClient.rb:7:1:7:13 | call to content |
3336
| HttpClient.rb:9:9:9:64 | call to put | HTTPClient | HttpClient.rb:9:24:9:44 | "http://example.com/" | HttpClient.rb:10:1:10:15 | call to http_body |
Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
edges
2-
| ServerSideRequestForgery.rb:9:32:9:37 | call to params : | ServerSideRequestForgery.rb:9:32:9:60 | ...[...] : |
3-
| ServerSideRequestForgery.rb:9:32:9:60 | ...[...] : | ServerSideRequestForgery.rb:10:31:10:62 | "#{...}/logins" |
2+
| ServerSideRequestForgery.rb:10:32:10:37 | call to params : | ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : |
3+
| ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" |
4+
| ServerSideRequestForgery.rb:15:33:15:38 | call to params : | ServerSideRequestForgery.rb:15:33:15:44 | ...[...] |
5+
| ServerSideRequestForgery.rb:20:45:20:50 | call to params : | ServerSideRequestForgery.rb:20:45:20:56 | ...[...] |
46
nodes
5-
| ServerSideRequestForgery.rb:9:32:9:37 | call to params : | semmle.label | call to params : |
6-
| ServerSideRequestForgery.rb:9:32:9:60 | ...[...] : | semmle.label | ...[...] : |
7-
| ServerSideRequestForgery.rb:10:31:10:62 | "#{...}/logins" | semmle.label | "#{...}/logins" |
7+
| ServerSideRequestForgery.rb:10:32:10:37 | call to params : | semmle.label | call to params : |
8+
| ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : | semmle.label | ...[...] : |
9+
| ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | semmle.label | "#{...}/logins" |
10+
| ServerSideRequestForgery.rb:15:33:15:38 | call to params : | semmle.label | call to params : |
11+
| ServerSideRequestForgery.rb:15:33:15:44 | ...[...] | semmle.label | ...[...] |
12+
| ServerSideRequestForgery.rb:20:45:20:50 | call to params : | semmle.label | call to params : |
13+
| ServerSideRequestForgery.rb:20:45:20:56 | ...[...] | semmle.label | ...[...] |
814
subpaths
915
#select
10-
| ServerSideRequestForgery.rb:10:31:10:62 | "#{...}/logins" | ServerSideRequestForgery.rb:9:32:9:37 | call to params : | ServerSideRequestForgery.rb:10:31:10:62 | "#{...}/logins" | The URL of this request depends on a $@. | ServerSideRequestForgery.rb:9:32:9:37 | call to params | user-provided value |
16+
| ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | ServerSideRequestForgery.rb:10:32:10:37 | call to params : | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | The URL of this request depends on a $@. | ServerSideRequestForgery.rb:10:32:10:37 | call to params | user-provided value |
17+
| ServerSideRequestForgery.rb:15:33:15:44 | ...[...] | ServerSideRequestForgery.rb:15:33:15:38 | call to params : | ServerSideRequestForgery.rb:15:33:15:44 | ...[...] | The URL of this request depends on a $@. | ServerSideRequestForgery.rb:15:33:15:38 | call to params | user-provided value |
18+
| ServerSideRequestForgery.rb:20:45:20:56 | ...[...] | ServerSideRequestForgery.rb:20:45:20:50 | call to params : | ServerSideRequestForgery.rb:20:45:20:56 | ...[...] | The URL of this request depends on a $@. | ServerSideRequestForgery.rb:20:45:20:50 | call to params | user-provided value |

ruby/ql/test/query-tests/security/cwe-918/ServerSideRequestForgery.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require "excon"
2+
require "faraday"
23
require "json"
34

45
class PostsController < ActionController::Base
@@ -10,6 +11,16 @@ def create
1011
response = Excon.post("#{users_service_domain}/logins", body: {user_id: user}).body
1112
token = JSON.parse(response)["token"]
1213

14+
# BAD - user can control the entire URL for the request using Faraday library
15+
conn = Faraday.new(url: params[:url])
16+
resp = conn.post
17+
token = JSON.parse(resp)["token"]
18+
19+
# BAD - user can control the entire URL for the request using Faraday::Connection library
20+
conn = Faraday::Connection.new(url: params[:url])
21+
resp = conn.post
22+
token = JSON.parse(resp)["token"]
23+
1324
# GOOD - user can only control the suffix of the URL
1425
users_service_path = params[:users_service_path]
1526
response = Excon.post("users-service/#{users_service_path}", body: {user_id: user}).body

0 commit comments

Comments
 (0)