ssrf_proxy 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/LICENSE.md +1 -1
- data/README.md +87 -62
- data/bin/console +10 -8
- data/bin/ssrf-proxy +212 -99
- data/lib/ssrf_proxy.rb +4 -2
- data/lib/ssrf_proxy/banner.rb +15 -0
- data/lib/ssrf_proxy/http.rb +857 -436
- data/lib/ssrf_proxy/server.rb +98 -61
- data/lib/ssrf_proxy/version.rb +2 -10
- metadata +134 -92
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZGJhNjA3ZTRkODE5YTNlZmQyYTY3MGJjM2Q1YWE1NTNhOThhYmE2ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YzZlMmY0ODI2NGM0MmNiNzk0MjcxZTAwMDM5YjZhNWNmMTA1ZDVlOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MGI5ZTA1NDAyNGJiMGM3ODdlMmU3M2VlZGRlODAwN2MwNmM0YzIzZjllM2Qw
|
10
|
+
ZjBlM2RjMzc5ODZhNDYwNTk2MTgwN2NmOTJiNWJjYmFlZjI2YTM0YjNlMzc2
|
11
|
+
MWEwZWYwMDI5YjFiNmUyM2I5ODY1NWE2OTY0Y2M5NTY5ODBjMDA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MWVmZTJlYTRmZDk3NjdjOWNmYjY0MGZhYzM3ODhiMjRhZGJkN2Q0ZDEzODQ5
|
14
|
+
MzI0ZjkwNzMwYTllZjVlNmVjMWJjZWUxOThlMTg2OWUxZDhmOGJhZjlkODc0
|
15
|
+
OTA3ZmZjODRiYTYxMTQwNjY3YjE3NWQwODBjYWYyYTZhNTJkYzc=
|
data/LICENSE.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2015-
|
3
|
+
Copyright (c) 2015-2017 Brendan Coles <bcoles@gmail.com>
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# SSRF Proxy
|
2
2
|
|
3
3
|
<a href="https://github.com/bcoles/ssrf_proxy" target="_blank">
|
4
|
-
<img src="https://img.shields.io/badge/version-0.0.
|
4
|
+
<img alt="Version 0.0.4" src="https://img.shields.io/badge/version-0.0.4-brightgreen.svg"/>
|
5
5
|
</a>
|
6
6
|
<a href="https://travis-ci.org/bcoles-ci/ssrf_proxy" target="_blank">
|
7
7
|
<img src="https://api.travis-ci.org/bcoles-ci/ssrf_proxy.svg?branch=master"/>
|
@@ -22,12 +22,13 @@
|
|
22
22
|
<img src="https://inch-ci.org/github/bcoles/ssrf_proxy.svg?branch=master"/>
|
23
23
|
</a>
|
24
24
|
<a href="https://github.com/bcoles/ssrf_proxy/blob/master/LICENSE.md" target="_blank">
|
25
|
-
<img src="https://img.shields.io/badge/license-MIT-brightgreen.svg"/>
|
25
|
+
<img alt="MIT License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg"/>
|
26
26
|
</a>
|
27
27
|
|
28
|
+
|
28
29
|
**SSRF Proxy** is a multi-threaded HTTP proxy server designed
|
29
30
|
to tunnel client HTTP traffic through HTTP servers vulnerable
|
30
|
-
to
|
31
|
+
to Server-Side Request Forgery (SSRF).
|
31
32
|
|
32
33
|
Once configured, SSRF Proxy attempts to format client HTTP
|
33
34
|
requests appropriately for the vulnerable server. Likewise,
|
@@ -35,8 +36,8 @@ the server's response is parsed and formatted for the client.
|
|
35
36
|
|
36
37
|
By correctly formatting the client request and stripping
|
37
38
|
unwanted junk from the response it is possible to use
|
38
|
-
SSRF Proxy as a HTTP proxy for web browsers
|
39
|
-
tools such as sqlmap and nikto.
|
39
|
+
SSRF Proxy as a HTTP proxy for web browsers, proxychains,
|
40
|
+
and scanning tools such as sqlmap, nmap, dirb and nikto.
|
40
41
|
|
41
42
|
SSRF Proxy also assists with leveraging blind SSRF
|
42
43
|
vulnerabilities to perform time-based attacks, such
|
@@ -45,7 +46,11 @@ as blind time-based SQL injection with sqlmap.
|
|
45
46
|
<table>
|
46
47
|
<tr>
|
47
48
|
<th>Version</th>
|
48
|
-
<td>
|
49
|
+
<td>
|
50
|
+
<a href="https://github.com/bcoles/ssrf_proxy" target="_blank">
|
51
|
+
<img alt="Version 0.0.4" src="https://img.shields.io/badge/version-0.0.4-brightgreen.svg"/>
|
52
|
+
</a>
|
53
|
+
</td>
|
49
54
|
</tr>
|
50
55
|
<tr>
|
51
56
|
<th>Github</th>
|
@@ -55,7 +60,9 @@ as blind time-based SQL injection with sqlmap.
|
|
55
60
|
</tr>
|
56
61
|
<tr>
|
57
62
|
<th>Wiki</th>
|
58
|
-
<td
|
63
|
+
<td>
|
64
|
+
<a href="https://github.com/bcoles/ssrf_proxy/wiki">https://github.com/bcoles/ssrf_proxy/wiki</a>
|
65
|
+
</td>
|
59
66
|
</tr>
|
60
67
|
<tr>
|
61
68
|
<th>Documentation</th>
|
@@ -69,18 +76,22 @@ as blind time-based SQL injection with sqlmap.
|
|
69
76
|
</tr>
|
70
77
|
<tr>
|
71
78
|
<th>Copyright</th>
|
72
|
-
<td>2015-
|
79
|
+
<td>2015-2017 Brendan Coles</td>
|
73
80
|
</tr>
|
74
81
|
<tr>
|
75
82
|
<th>License</th>
|
76
|
-
<td>
|
83
|
+
<td>
|
84
|
+
<a href="https://github.com/bcoles/ssrf_proxy/blob/master/LICENSE.md" target="_blank">
|
85
|
+
<img alt="MIT License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg"/>
|
86
|
+
</a>
|
87
|
+
</td>
|
77
88
|
</tr>
|
78
89
|
</table>
|
79
90
|
|
80
91
|
|
81
92
|
## Requirements
|
82
93
|
|
83
|
-
Ruby
|
94
|
+
Ruby 2.2.2 or newer.
|
84
95
|
|
85
96
|
Ruby Gems:
|
86
97
|
|
@@ -92,6 +103,7 @@ Ruby Gems:
|
|
92
103
|
- base32
|
93
104
|
- htmlentities
|
94
105
|
- socksify
|
106
|
+
- mimemagic
|
95
107
|
|
96
108
|
## Installation
|
97
109
|
|
@@ -107,24 +119,34 @@ Example: ssrf-proxy -u http://target/?url=xxURLxx
|
|
107
119
|
Options:
|
108
120
|
|
109
121
|
-h, --help Help
|
122
|
+
--version Display version
|
123
|
+
|
124
|
+
Output options:
|
110
125
|
-v, --verbose Verbose output
|
111
126
|
-d, --debug Debugging output
|
127
|
+
--no-color Disable colored output
|
112
128
|
|
113
129
|
Server options:
|
114
130
|
-p, --port=PORT Listen port (Default: 8081)
|
115
131
|
--interface=IP Listen interface (Default: 127.0.0.1)
|
116
132
|
|
117
133
|
SSRF request options:
|
118
|
-
-u, --url=URL
|
119
|
-
|
134
|
+
-u, --url=URL Target URL vulnerable to SSRF.
|
135
|
+
-f, --file=FILE Load HTTP request from a file.
|
136
|
+
--placeholder=STR Placeholder indicating SSRF insertion point.
|
137
|
+
(Default: xxURLxx)
|
138
|
+
--method=METHOD HTTP method (GET/HEAD/DELETE/POST/PUT/OPTIONS)
|
120
139
|
(Default: GET)
|
121
140
|
--post-data=DATA HTTP post data
|
122
141
|
--cookie=COOKIE HTTP cookies (separated by ';')
|
123
|
-
--user
|
124
|
-
--
|
142
|
+
--user=USER[:PASS] HTTP basic authentication credentials.
|
143
|
+
--user-agent=AGENT HTTP user-agent (Default: none)
|
144
|
+
--rules=RULES Rules for parsing client request
|
125
145
|
(separated by ',') (Default: none)
|
146
|
+
--no-urlencode Do not URL encode client request
|
126
147
|
|
127
148
|
SSRF connection options:
|
149
|
+
--ssl Connect using SSL/TLS.
|
128
150
|
--proxy=PROXY Use a proxy to connect to the server.
|
129
151
|
(Supported proxies: http, https, socks)
|
130
152
|
--insecure Skip server SSL certificate validation.
|
@@ -136,83 +158,85 @@ Options:
|
|
136
158
|
--strip=HEADERS Headers to remove from the response.
|
137
159
|
(separated by ',') (Default: none)
|
138
160
|
--decode-html Decode HTML entities in response body.
|
161
|
+
--unescape Unescape special characters in response body.
|
139
162
|
--guess-status Replaces response status code and message
|
140
163
|
headers (determined by common strings in the
|
141
164
|
response body, such as 404 Not Found.)
|
142
165
|
--guess-mime Replaces response content-type header with the
|
143
166
|
appropriate mime type (determined by the file
|
144
167
|
extension of the requested resource.)
|
145
|
-
--
|
146
|
-
|
147
|
-
|
168
|
+
--sniff-mime Replaces response content-type header with the
|
169
|
+
appropriate mime type (determined by magic bytes
|
170
|
+
in the response body.)
|
171
|
+
--timeout-ok Replaces timeout HTTP status code 504 with 200.
|
172
|
+
--detect-headers Replaces response headers if response headers
|
173
|
+
are identified in the response body.
|
174
|
+
--fail-no-content Return HTTP status 502 if the response body
|
175
|
+
is empty.
|
176
|
+
--cors Adds a 'Access-Control-Allow-Origin: *' header.
|
148
177
|
|
149
178
|
Client request modification:
|
150
|
-
--forward-
|
151
|
-
|
152
|
-
--
|
153
|
-
--
|
179
|
+
--forward-method Forward client request method.
|
180
|
+
--forward-headers Forward all client request headers.
|
181
|
+
--forward-body Forward client request body.
|
182
|
+
--forward-cookies Forward client request cookies.
|
183
|
+
--cookies-to-uri Add client request cookies to URI query string.
|
184
|
+
--body-to-uri Add client request body to URI query string.
|
154
185
|
--auth-to-uri Use client request basic authentication
|
155
186
|
credentials in request URI.
|
156
187
|
--ip-encoding=MODE Encode client request host IP address.
|
157
188
|
(Modes: int, ipv6, oct, hex, dotted_hex)
|
158
|
-
|
189
|
+
--cache-buster Append a random value to the client request
|
190
|
+
query string.
|
159
191
|
|
160
192
|
```
|
161
193
|
|
162
194
|
|
163
195
|
## Usage (ruby)
|
164
196
|
|
165
|
-
|
197
|
+
Load the ```ssrf_proxy``` library:
|
166
198
|
|
199
|
+
```ruby
|
200
|
+
require 'ssrf_proxy'
|
167
201
|
```
|
168
|
-
# SSRF URL with 'xxURLxx' placeholder
|
169
|
-
url = 'http://example.local/index.php?url=xxURLxx'
|
170
|
-
# options
|
171
|
-
opts = {
|
172
|
-
'proxy' => '',
|
173
|
-
'method' => 'GET',
|
174
|
-
'post_data' => '',
|
175
|
-
'rules' => '',
|
176
|
-
'ip_encoding' => '',
|
177
|
-
'match' => "\\A(.+)\\z",
|
178
|
-
'strip' => '',
|
179
|
-
'decode_html' => false,
|
180
|
-
'guess_mime' => false,
|
181
|
-
'guess_status' => false,
|
182
|
-
'ask_password' => false,
|
183
|
-
'forward_cookies'=> false,
|
184
|
-
'body_to_uri' => false,
|
185
|
-
'auth_to_uri' => false,
|
186
|
-
'cookies_to_uri' => false,
|
187
|
-
'cookie' => '',
|
188
|
-
'timeout' => 10,
|
189
|
-
'user_agent' => 'Mozilla/5.0',
|
190
|
-
'insecure' => false
|
191
|
-
}
|
192
|
-
# create SSRFProxy::HTTP object
|
193
|
-
ssrf = SSRFProxy::HTTP.new(url, opts)
|
194
|
-
# set log level (optional)
|
195
|
-
ssrf.logger.level = Logger::DEBUG
|
196
|
-
```
|
197
202
|
|
198
|
-
|
203
|
+
Initialize the `SSRFProxy::HTTP` object:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
# Initialize with a URL containing 'xxURLxx' placeholder
|
207
|
+
ssrf = SSRFProxy::HTTP.new(url: 'http://example.local/?url=xxURLxx')
|
208
|
+
|
209
|
+
# Or, provide the placeholder elsewhere in the request
|
210
|
+
ssrf = SSRFProxy::HTTP.new(url: 'http://example.local/', method: 'POST', post_data: 'xxURLxx')
|
211
|
+
|
212
|
+
# Alternatively, the object can be initialized
|
213
|
+
# with a file containing a raw HTTP request:
|
214
|
+
ssrf = SSRFProxy::HTTP.new(file: 'ssrf.txt')
|
199
215
|
|
216
|
+
# Or, initialized with a StringIO object containing a raw HTTP request:
|
217
|
+
http = StringIO.new("GET http://example.local/?url=xxURLxx HTTP/1.1\n\n")
|
218
|
+
ssrf = SSRFProxy::HTTP.new(file: http)
|
200
219
|
```
|
201
|
-
# fetch http://127.0.0.1/ via SSRF by String
|
202
|
-
uri = 'http://127.0.0.1/'
|
203
|
-
ssrf.send_uri(uri)
|
204
220
|
|
221
|
+
Refer to the documentation for additional configuration options.
|
205
222
|
|
206
|
-
|
207
|
-
|
208
|
-
ssrf.send_uri(uri)
|
223
|
+
Once initialized, the `SSRFProxy::HTTP` object can be used to send HTTP
|
224
|
+
requests via the SSRF using the ```send_uri``` and ```send_request``` methods.
|
209
225
|
|
226
|
+
```ruby
|
227
|
+
# GET via SSRF
|
228
|
+
ssrf.send_uri('http://127.0.0.1/')
|
210
229
|
|
211
|
-
#
|
212
|
-
http
|
213
|
-
|
230
|
+
# POST via SSRF
|
231
|
+
ssrf.send_uri('http://127.0.0.1/', method: 'POST', headers: {}, body: '')
|
232
|
+
|
233
|
+
# GET via SSRF (using a raw HTTP request)
|
234
|
+
ssrf.send_request("GET http://127.0.0.1/ HTTP/1.1\n\n")
|
214
235
|
```
|
215
236
|
|
237
|
+
Refer to the documentation for additional request options.
|
238
|
+
|
239
|
+
|
216
240
|
## Documentation
|
217
241
|
|
218
242
|
Refer to the wiki for more information and example usage:
|
@@ -220,3 +244,4 @@ https://github.com/bcoles/ssrf_proxy/wiki
|
|
220
244
|
|
221
245
|
Refer to RubyDoc for code documentation:
|
222
246
|
http://www.rubydoc.info/github/bcoles/ssrf_proxy
|
247
|
+
|
data/bin/console
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
# Copyright (c) 2015-
|
3
|
+
# Copyright (c) 2015-2017 Brendan Coles <bcoles@gmail.com>
|
4
4
|
# SSRF Proxy - https://github.com/bcoles/ssrf_proxy
|
5
5
|
# See the file 'LICENSE.md' for copying permission
|
6
6
|
#
|
7
7
|
|
8
8
|
require 'irb'
|
9
9
|
require 'irb/completion'
|
10
|
+
require 'ssrf_proxy'
|
10
11
|
|
11
12
|
begin
|
12
|
-
puts "\n_________________________________________________________
|
13
|
-
puts SSRFProxy::BANNER
|
13
|
+
puts "\n_________________________________________________________".blue
|
14
|
+
puts SSRFProxy::BANNER.blue
|
14
15
|
puts "\n SSRF Proxy v#{SSRFProxy::VERSION}"
|
15
16
|
puts " https://github.com/bcoles/ssrf_proxy\n"
|
16
|
-
puts "\n_________________________________________________________\n
|
17
|
+
puts "\n_________________________________________________________\n".blue
|
17
18
|
|
18
|
-
puts "SSRFProxy[#{SSRFProxy::VERSION}], " \
|
19
|
-
"Ruby[#{RUBY_VERSION}], " \
|
20
|
-
"Platform[#{RUBY_PLATFORM}]"
|
19
|
+
puts "SSRFProxy[#{SSRFProxy::VERSION.yellow}], " \
|
20
|
+
"Ruby[#{RUBY_VERSION.yellow}], " \
|
21
|
+
"Platform[#{RUBY_PLATFORM.yellow}]"
|
22
|
+
puts
|
21
23
|
rescue => e
|
22
|
-
puts "Error: Could not load
|
24
|
+
puts "Error: Could not load SSRF Proxy: #{e.message}"
|
23
25
|
end
|
24
26
|
IRB.start
|
data/bin/ssrf-proxy
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
# Copyright (c) 2015-
|
3
|
+
# Copyright (c) 2015-2017 Brendan Coles <bcoles@gmail.com>
|
4
4
|
# SSRF Proxy - https://github.com/bcoles/ssrf_proxy
|
5
5
|
# See the file 'LICENSE.md' for copying permission
|
6
6
|
#
|
@@ -22,29 +22,40 @@ end
|
|
22
22
|
# @note output usage
|
23
23
|
#
|
24
24
|
def usage
|
25
|
+
banner
|
25
26
|
puts 'Usage: ssrf-proxy [options] -u <SSRF URL>'
|
26
27
|
puts 'Example: ssrf-proxy -u http://target/?url=xxURLxx'
|
27
28
|
puts 'Options:'
|
28
29
|
puts "
|
29
30
|
-h, --help Help
|
31
|
+
--version Display version
|
32
|
+
|
33
|
+
Output options:
|
30
34
|
-v, --verbose Verbose output
|
31
35
|
-d, --debug Debugging output
|
36
|
+
--no-color Disable colored output
|
32
37
|
|
33
38
|
Server options:
|
34
39
|
-p, --port=PORT Listen port (Default: 8081)
|
35
40
|
--interface=IP Listen interface (Default: 127.0.0.1)
|
36
41
|
|
37
42
|
SSRF request options:
|
38
|
-
-u, --url=URL
|
39
|
-
|
43
|
+
-u, --url=URL Target URL vulnerable to SSRF.
|
44
|
+
-f, --file=FILE Load HTTP request from a file.
|
45
|
+
--placeholder=STR Placeholder indicating SSRF insertion point.
|
46
|
+
(Default: xxURLxx)
|
47
|
+
--method=METHOD HTTP method (GET/HEAD/DELETE/POST/PUT/OPTIONS)
|
40
48
|
(Default: GET)
|
41
49
|
--post-data=DATA HTTP post data
|
42
50
|
--cookie=COOKIE HTTP cookies (separated by ';')
|
43
|
-
--user
|
44
|
-
--
|
51
|
+
--user=USER[:PASS] HTTP basic authentication credentials.
|
52
|
+
--user-agent=AGENT HTTP user-agent (Default: none)
|
53
|
+
--rules=RULES Rules for parsing client request
|
45
54
|
(separated by ',') (Default: none)
|
55
|
+
--no-urlencode Do not URL encode client request
|
46
56
|
|
47
57
|
SSRF connection options:
|
58
|
+
--ssl Connect using SSL/TLS.
|
48
59
|
--proxy=PROXY Use a proxy to connect to the server.
|
49
60
|
(Supported proxies: http, https, socks)
|
50
61
|
--insecure Skip server SSL certificate validation.
|
@@ -56,25 +67,36 @@ def usage
|
|
56
67
|
--strip=HEADERS Headers to remove from the response.
|
57
68
|
(separated by ',') (Default: none)
|
58
69
|
--decode-html Decode HTML entities in response body.
|
70
|
+
--unescape Unescape special characters in response body.
|
59
71
|
--guess-status Replaces response status code and message
|
60
72
|
headers (determined by common strings in the
|
61
73
|
response body, such as 404 Not Found.)
|
62
74
|
--guess-mime Replaces response content-type header with the
|
63
75
|
appropriate mime type (determined by the file
|
64
76
|
extension of the requested resource.)
|
65
|
-
--
|
66
|
-
|
67
|
-
|
77
|
+
--sniff-mime Replaces response content-type header with the
|
78
|
+
appropriate mime type (determined by magic bytes
|
79
|
+
in the response body.)
|
80
|
+
--timeout-ok Replaces timeout HTTP status code 504 with 200.
|
81
|
+
--detect-headers Replaces response headers if response headers
|
82
|
+
are identified in the response body.
|
83
|
+
--fail-no-content Return HTTP status 502 if the response body
|
84
|
+
is empty.
|
85
|
+
--cors Adds a 'Access-Control-Allow-Origin: *' header.
|
68
86
|
|
69
87
|
Client request modification:
|
70
|
-
--forward-
|
71
|
-
|
72
|
-
--
|
73
|
-
--
|
88
|
+
--forward-method Forward client request method.
|
89
|
+
--forward-headers Forward all client request headers.
|
90
|
+
--forward-body Forward client request body.
|
91
|
+
--forward-cookies Forward client request cookies.
|
92
|
+
--cookies-to-uri Add client request cookies to URI query string.
|
93
|
+
--body-to-uri Add client request body to URI query string.
|
74
94
|
--auth-to-uri Use client request basic authentication
|
75
95
|
credentials in request URI.
|
76
96
|
--ip-encoding=MODE Encode client request host IP address.
|
77
97
|
(Modes: int, ipv6, oct, hex, dotted_hex)
|
98
|
+
--cache-buster Append a random value to the client request
|
99
|
+
query string.
|
78
100
|
|
79
101
|
"
|
80
102
|
exit 1
|
@@ -87,34 +109,52 @@ def start_server
|
|
87
109
|
# get args
|
88
110
|
opts = GetoptLong.new(
|
89
111
|
['-h', '--help', GetoptLong::NO_ARGUMENT],
|
112
|
+
['--version', GetoptLong::NO_ARGUMENT],
|
113
|
+
|
90
114
|
['-v', '--verbose', GetoptLong::NO_ARGUMENT],
|
91
115
|
['-d', '--debug', GetoptLong::NO_ARGUMENT],
|
116
|
+
['--no-color', GetoptLong::NO_ARGUMENT],
|
92
117
|
|
93
118
|
['-p', '--port', GetoptLong::REQUIRED_ARGUMENT],
|
94
119
|
['--interface', GetoptLong::REQUIRED_ARGUMENT],
|
95
|
-
['--proxy', GetoptLong::REQUIRED_ARGUMENT],
|
96
120
|
|
97
121
|
['-u', '--url', GetoptLong::REQUIRED_ARGUMENT],
|
122
|
+
['-f', '--file', GetoptLong::REQUIRED_ARGUMENT],
|
123
|
+
['--placeholder', GetoptLong::REQUIRED_ARGUMENT],
|
98
124
|
['--method', GetoptLong::REQUIRED_ARGUMENT],
|
99
125
|
['--post-data', GetoptLong::REQUIRED_ARGUMENT],
|
100
126
|
['--cookie', GetoptLong::REQUIRED_ARGUMENT],
|
127
|
+
['--user', GetoptLong::REQUIRED_ARGUMENT],
|
101
128
|
['--user-agent', GetoptLong::REQUIRED_ARGUMENT],
|
129
|
+
|
130
|
+
['--ssl', GetoptLong::NO_ARGUMENT],
|
131
|
+
['--proxy', GetoptLong::REQUIRED_ARGUMENT],
|
102
132
|
['--insecure', GetoptLong::NO_ARGUMENT],
|
103
133
|
['--timeout', GetoptLong::REQUIRED_ARGUMENT],
|
104
134
|
|
105
|
-
['--ip-encoding', GetoptLong::REQUIRED_ARGUMENT],
|
106
135
|
['--rules', GetoptLong::REQUIRED_ARGUMENT],
|
136
|
+
['--no-urlencode', GetoptLong::NO_ARGUMENT],
|
137
|
+
['--forward-method', GetoptLong::NO_ARGUMENT],
|
138
|
+
['--forward-headers', GetoptLong::NO_ARGUMENT],
|
139
|
+
['--forward-body', GetoptLong::NO_ARGUMENT],
|
107
140
|
['--forward-cookies', GetoptLong::NO_ARGUMENT],
|
141
|
+
['--cookies-to-uri', GetoptLong::NO_ARGUMENT],
|
108
142
|
['--body-to-uri', GetoptLong::NO_ARGUMENT],
|
109
143
|
['--auth-to-uri', GetoptLong::NO_ARGUMENT],
|
110
|
-
['--
|
144
|
+
['--cache-buster', GetoptLong::NO_ARGUMENT],
|
145
|
+
['--ip-encoding', GetoptLong::REQUIRED_ARGUMENT],
|
111
146
|
|
112
147
|
['--match', GetoptLong::REQUIRED_ARGUMENT],
|
113
148
|
['--strip', GetoptLong::REQUIRED_ARGUMENT],
|
114
149
|
['--decode-html', GetoptLong::NO_ARGUMENT],
|
150
|
+
['--unescape', GetoptLong::NO_ARGUMENT],
|
115
151
|
['--guess-status', GetoptLong::NO_ARGUMENT],
|
116
152
|
['--guess-mime', GetoptLong::NO_ARGUMENT],
|
117
|
-
['--
|
153
|
+
['--sniff-mime', GetoptLong::NO_ARGUMENT],
|
154
|
+
['--cors', GetoptLong::NO_ARGUMENT],
|
155
|
+
['--detect-headers', GetoptLong::NO_ARGUMENT],
|
156
|
+
['--fail-no-content', GetoptLong::NO_ARGUMENT],
|
157
|
+
['--timeout-ok', GetoptLong::NO_ARGUMENT]
|
118
158
|
)
|
119
159
|
|
120
160
|
# local proxy server defaults
|
@@ -123,114 +163,188 @@ def start_server
|
|
123
163
|
|
124
164
|
# ssrf defaults
|
125
165
|
url = nil
|
126
|
-
|
127
|
-
|
166
|
+
file = nil
|
167
|
+
rules = nil
|
168
|
+
ip_encoding = nil
|
169
|
+
placeholder = 'xxURLxx'
|
128
170
|
method = 'GET'
|
129
|
-
post_data =
|
171
|
+
post_data = nil
|
130
172
|
match = '\\A(.*)\\z'
|
131
|
-
strip =
|
173
|
+
strip = nil
|
174
|
+
no_urlencode = false
|
132
175
|
decode_html = false
|
176
|
+
unescape = false
|
133
177
|
guess_status = false
|
134
178
|
guess_mime = false
|
135
|
-
|
179
|
+
sniff_mime = false
|
180
|
+
cors = false
|
181
|
+
timeout_ok = false
|
182
|
+
detect_headers = false
|
183
|
+
fail_no_content = false
|
184
|
+
forward_method = false
|
185
|
+
forward_headers = false
|
186
|
+
forward_body = false
|
136
187
|
forward_cookies = false
|
137
188
|
body_to_uri = false
|
138
189
|
auth_to_uri = false
|
139
190
|
cookies_to_uri = false
|
191
|
+
cache_buster = false
|
140
192
|
|
141
193
|
# http connection defaults
|
142
|
-
cookie =
|
194
|
+
cookie = nil
|
195
|
+
user = nil
|
143
196
|
timeout = 10
|
197
|
+
ssl = false
|
144
198
|
upstream_proxy = nil
|
145
|
-
user_agent =
|
199
|
+
user_agent = nil
|
146
200
|
insecure = false
|
147
201
|
|
148
202
|
# logging
|
149
203
|
log_level = ::Logger::WARN
|
150
204
|
|
151
205
|
# handle args
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
interface
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
206
|
+
begin
|
207
|
+
opts.each do |opt, arg|
|
208
|
+
case opt
|
209
|
+
when '-p', '--port'
|
210
|
+
port = arg
|
211
|
+
when '--interface'
|
212
|
+
interface = arg
|
213
|
+
when '-u', '--url'
|
214
|
+
url = arg
|
215
|
+
when '-f', '--file'
|
216
|
+
file = arg
|
217
|
+
when '--ip-encoding'
|
218
|
+
ip_encoding = arg
|
219
|
+
when '--rules'
|
220
|
+
rules = arg
|
221
|
+
when '--no-urlencode'
|
222
|
+
no_urlencode = true
|
223
|
+
when '--ssl'
|
224
|
+
ssl = true
|
225
|
+
when '--proxy'
|
226
|
+
upstream_proxy = URI.parse(arg)
|
227
|
+
when '--cookie'
|
228
|
+
cookie = arg
|
229
|
+
when '--user'
|
230
|
+
user = arg
|
231
|
+
when '--timeout'
|
232
|
+
timeout = arg.to_i
|
233
|
+
when '--user-agent'
|
234
|
+
user_agent = arg
|
235
|
+
when '--insecure'
|
236
|
+
insecure = true
|
237
|
+
when '--placeholder'
|
238
|
+
placeholder = arg
|
239
|
+
when '--method'
|
240
|
+
method = arg
|
241
|
+
when '--post-data'
|
242
|
+
post_data = arg
|
243
|
+
when '--match'
|
244
|
+
match = arg
|
245
|
+
when '--strip'
|
246
|
+
strip = arg
|
247
|
+
when '--decode-html'
|
248
|
+
decode_html = true
|
249
|
+
when '--unescape'
|
250
|
+
unescape = true
|
251
|
+
when '--guess-status'
|
252
|
+
guess_status = true
|
253
|
+
when '--guess-mime'
|
254
|
+
guess_mime = true
|
255
|
+
when '--sniff-mime'
|
256
|
+
sniff_mime = true
|
257
|
+
when '--cors'
|
258
|
+
cors = true
|
259
|
+
when '--timeout-ok'
|
260
|
+
timeout_ok = true
|
261
|
+
when '--detect-headers'
|
262
|
+
detect_headers = true
|
263
|
+
when '--fail-no-content'
|
264
|
+
fail_no_content = true
|
265
|
+
when '--forward-method'
|
266
|
+
forward_method = true
|
267
|
+
when '--forward-headers'
|
268
|
+
forward_headers = true
|
269
|
+
when '--forward-body'
|
270
|
+
forward_body = true
|
271
|
+
when '--forward-cookies'
|
272
|
+
forward_cookies = true
|
273
|
+
when '--body-to-uri'
|
274
|
+
body_to_uri = true
|
275
|
+
when '--auth-to-uri'
|
276
|
+
auth_to_uri = true
|
277
|
+
when '--cookies-to-uri'
|
278
|
+
cookies_to_uri = true
|
279
|
+
when '--cache-buster'
|
280
|
+
cache_buster = true
|
281
|
+
when '-h', '--help'
|
282
|
+
usage
|
283
|
+
when '-v', '--verbose'
|
284
|
+
log_level = ::Logger::INFO unless log_level == ::Logger::DEBUG
|
285
|
+
when '-d', '--debug'
|
286
|
+
log_level = ::Logger::DEBUG
|
287
|
+
when '--no-color'
|
288
|
+
String.disable_colorization = true
|
289
|
+
when '--version'
|
290
|
+
puts "SSRF Proxy v#{SSRFProxy::VERSION}"
|
291
|
+
exit
|
292
|
+
end
|
204
293
|
end
|
294
|
+
rescue GetoptLong::InvalidOption, GetoptLong::MissingArgument
|
295
|
+
puts "Error: Invalid usage. Try '#{$PROGRAM_NAME} --help' for usage information."
|
296
|
+
exit 1
|
205
297
|
end
|
206
298
|
|
207
299
|
opts = {
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
300
|
+
url: url,
|
301
|
+
file: file,
|
302
|
+
proxy: upstream_proxy,
|
303
|
+
ssl: ssl,
|
304
|
+
method: method,
|
305
|
+
placeholder: placeholder,
|
306
|
+
post_data: post_data,
|
307
|
+
rules: rules,
|
308
|
+
no_urlencode: no_urlencode,
|
309
|
+
ip_encoding: ip_encoding,
|
310
|
+
match: match,
|
311
|
+
strip: strip,
|
312
|
+
decode_html: decode_html,
|
313
|
+
unescape: unescape,
|
314
|
+
guess_mime: guess_mime,
|
315
|
+
sniff_mime: sniff_mime,
|
316
|
+
guess_status: guess_status,
|
317
|
+
cors: cors,
|
318
|
+
timeout_ok: timeout_ok,
|
319
|
+
detect_headers: detect_headers,
|
320
|
+
fail_no_content: fail_no_content,
|
321
|
+
forward_method: forward_method,
|
322
|
+
forward_headers: forward_headers,
|
323
|
+
forward_body: forward_body,
|
324
|
+
forward_cookies: forward_cookies,
|
325
|
+
body_to_uri: body_to_uri,
|
326
|
+
auth_to_uri: auth_to_uri,
|
327
|
+
cookies_to_uri: cookies_to_uri,
|
328
|
+
cache_buster: cache_buster,
|
329
|
+
cookie: cookie,
|
330
|
+
user: user,
|
331
|
+
timeout: timeout,
|
332
|
+
user_agent: user_agent,
|
333
|
+
insecure: insecure
|
227
334
|
}
|
228
335
|
|
229
|
-
# setup ssrf
|
230
|
-
ssrf = SSRFProxy::HTTP.new(url, opts)
|
231
|
-
ssrf.logger.level = log_level
|
232
|
-
# start server
|
233
336
|
begin
|
337
|
+
banner
|
338
|
+
|
339
|
+
%w[INT QUIT TERM].each do |s|
|
340
|
+
Signal.trap(s) { exit }
|
341
|
+
end
|
342
|
+
|
343
|
+
# setup ssrf
|
344
|
+
ssrf = SSRFProxy::HTTP.new(opts)
|
345
|
+
ssrf.logger.level = log_level
|
346
|
+
|
347
|
+
# start server
|
234
348
|
ssrf_proxy = SSRFProxy::Server.new(ssrf, interface, port)
|
235
349
|
ssrf_proxy.logger.level = log_level
|
236
350
|
ssrf_proxy.serve
|
@@ -239,6 +353,5 @@ def start_server
|
|
239
353
|
end
|
240
354
|
end
|
241
355
|
|
242
|
-
banner
|
243
356
|
usage if ARGV.empty?
|
244
357
|
start_server
|