ssrf_proxy 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|