yawast 0.7.0.beta2 → 0.7.0.beta3
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 +4 -4
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +3 -0
- data/README.md +5 -1
- data/lib/resources/common_file.txt +208 -0
- data/lib/scanner/core.rb +3 -2
- data/lib/scanner/plugins/applications/cms/generic.rb +11 -1
- data/lib/scanner/plugins/applications/framework/rails.rb +39 -0
- data/lib/scanner/plugins/applications/generic/password_reset.rb +40 -14
- data/lib/scanner/plugins/dns/caa.rb +1 -1
- data/lib/scanner/plugins/http/generic.rb +18 -8
- data/lib/scanner/plugins/servers/apache.rb +113 -15
- data/lib/scanner/plugins/servers/generic.rb +8 -0
- data/lib/scanner/plugins/servers/iis.rb +26 -3
- data/lib/scanner/plugins/servers/nginx.rb +33 -0
- data/lib/scanner/plugins/servers/python.rb +8 -0
- data/lib/scanner/plugins/spider/spider.rb +7 -3
- data/lib/scanner/vuln_scan.rb +18 -5
- data/lib/shared/http.rb +1 -5
- data/lib/shared/output.rb +10 -7
- data/lib/version.rb +1 -1
- data/test/data/dir.txt +9 -0
- data/test/data/etc_passwd.txt +16 -0
- data/test/data/nginx_status_page.txt +4 -0
- data/test/test_app_fw_rails.rb +28 -0
- data/test/test_scan_apache.rb +23 -0
- data/test/test_scan_nginx.rb +33 -0
- data/yawast.gemspec +0 -1
- metadata +13 -18
- data/test/test_scan_nginx_banner.rb +0 -17
@@ -17,12 +17,17 @@ module Yawast
|
|
17
17
|
puts "\t\t\"curl -X PROPFIND #{uri}\""
|
18
18
|
|
19
19
|
puts ''
|
20
|
-
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
22
|
+
'http_propfind_enabled',
|
23
|
+
{vulnerable: true, body: res.body, code: res.code,
|
24
|
+
content_type: res['Content-Type'], length: res.body.length}
|
25
|
+
else
|
26
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
27
|
+
'http_propfind_enabled',
|
28
|
+
{vulnerable: false, body: res.body, code: res.code,
|
29
|
+
content_type: res['Content-Type'], length: res.body.length}
|
30
|
+
end
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
@@ -38,10 +43,15 @@ module Yawast
|
|
38
43
|
puts "\t\t\"curl -X TRACE #{uri}\""
|
39
44
|
|
40
45
|
puts ''
|
41
|
-
end
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
48
|
+
'http_trace_enabled',
|
49
|
+
{vulnerable: true, body: res.body, code: res.code}
|
50
|
+
else
|
51
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
52
|
+
'http_trace_enabled',
|
53
|
+
{vulnerable: false, body: res.body, code: res.code}
|
54
|
+
end
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
@@ -9,6 +9,16 @@ module Yawast
|
|
9
9
|
module Servers
|
10
10
|
class Apache
|
11
11
|
def self.check_banner(banner)
|
12
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
13
|
+
'apache_openssl_version_exposed',
|
14
|
+
{vulnerable: false, version: nil}
|
15
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
16
|
+
'apache_httpd_version_exposed',
|
17
|
+
{vulnerable: false, version: nil}
|
18
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
19
|
+
'apache_httpd_modules_exposed',
|
20
|
+
{vulnerable: false, modules: nil}
|
21
|
+
|
12
22
|
# don't bother if this doesn't look like Apache
|
13
23
|
return unless banner.include? 'Apache'
|
14
24
|
@apache = true
|
@@ -26,23 +36,33 @@ module Yawast
|
|
26
36
|
# print the server info no matter what we do next
|
27
37
|
Yawast::Utilities.puts_info "Apache Server: #{server}"
|
28
38
|
modules.delete_at 0
|
39
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
40
|
+
'apache_httpd_version_exposed',
|
41
|
+
{vulnerable: true, version: server}
|
29
42
|
|
30
43
|
if modules.count.positive?
|
31
44
|
Yawast::Utilities.puts_warn 'Apache Server: Module listing enabled'
|
32
45
|
modules.each { |mod| Yawast::Utilities.puts_warn "\t\t#{mod}" }
|
33
46
|
puts ''
|
47
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
48
|
+
'apache_httpd_modules_exposed',
|
49
|
+
{vulnerable: true, modules: banner}
|
34
50
|
|
35
51
|
# check for special items
|
36
52
|
modules.each do |mod|
|
37
53
|
if mod.include? 'OpenSSL'
|
38
54
|
Yawast::Utilities.puts_warn "OpenSSL Version Disclosure: #{mod}"
|
39
55
|
puts ''
|
56
|
+
|
57
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
58
|
+
'apache_openssl_version_exposed',
|
59
|
+
{vulnerable: true, version: mod}
|
40
60
|
end
|
41
61
|
end
|
42
62
|
end
|
43
63
|
end
|
44
64
|
|
45
|
-
def self.check_all(uri)
|
65
|
+
def self.check_all(uri, links = nil)
|
46
66
|
# run all the defined checks
|
47
67
|
check_server_status(uri.copy)
|
48
68
|
check_server_info(uri.copy)
|
@@ -50,6 +70,10 @@ module Yawast
|
|
50
70
|
check_tomcat_version(uri.copy)
|
51
71
|
check_tomcat_put_rce(uri.copy)
|
52
72
|
check_struts2_samples(uri.copy)
|
73
|
+
|
74
|
+
unless links.nil?
|
75
|
+
check_cve_2019_0232(links)
|
76
|
+
end
|
53
77
|
end
|
54
78
|
|
55
79
|
def self.check_server_status(uri)
|
@@ -61,6 +85,10 @@ module Yawast
|
|
61
85
|
end
|
62
86
|
|
63
87
|
def self.check_tomcat_version(uri)
|
88
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
89
|
+
'apache_tomcat_version_exposed',
|
90
|
+
{vulnerable: false, version: nil, body: nil}
|
91
|
+
|
64
92
|
begin
|
65
93
|
req = Yawast::Shared::Http.get_http(uri)
|
66
94
|
req.use_ssl = uri.scheme == 'https'
|
@@ -73,11 +101,17 @@ module Yawast
|
|
73
101
|
|
74
102
|
if !version.nil? && !version[0].nil?
|
75
103
|
Yawast::Utilities.puts_warn "Apache Tomcat Version Found: #{version[0]}"
|
76
|
-
Yawast::Shared::Output.
|
104
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
105
|
+
'apache_tomcat_version_exposed',
|
106
|
+
{vulnerable: true, version: version[0], body: res.body}
|
77
107
|
|
78
108
|
puts "\t\t\"curl -X XYZ #{uri}\""
|
79
109
|
|
80
110
|
puts ''
|
111
|
+
else
|
112
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
113
|
+
'apache_tomcat_version_exposed',
|
114
|
+
{vulnerable: false, version: nil, body: res.body}
|
81
115
|
end
|
82
116
|
end
|
83
117
|
end
|
@@ -89,6 +123,13 @@ module Yawast
|
|
89
123
|
end
|
90
124
|
|
91
125
|
def self.check_tomcat_manager_paths(uri, base_path, manager)
|
126
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
127
|
+
'apache_tomcat_manager_exposed',
|
128
|
+
{vulnerable: false, uri: nil}
|
129
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
130
|
+
'apache_tomcat_host_manager_exposed',
|
131
|
+
{vulnerable: false, uri: nil}
|
132
|
+
|
92
133
|
uri.path = "/#{base_path}/html"
|
93
134
|
uri.query = '' unless uri.query.nil?
|
94
135
|
|
@@ -97,7 +138,9 @@ module Yawast
|
|
97
138
|
if ret.include? '<tt>conf/tomcat-users.xml</tt>'
|
98
139
|
# this will get Tomcat 7+
|
99
140
|
Yawast::Utilities.puts_warn "Apache Tomcat #{manager} page found: #{uri}"
|
100
|
-
Yawast::Shared::Output.
|
141
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
142
|
+
'apache_tomcat_manager_exposed',
|
143
|
+
{vulnerable: true, uri: uri}
|
101
144
|
check_tomcat_manager_passwords uri, manager
|
102
145
|
|
103
146
|
puts ''
|
@@ -109,7 +152,9 @@ module Yawast
|
|
109
152
|
|
110
153
|
if ret.include? '<tt>conf/tomcat-users.xml</tt>'
|
111
154
|
Yawast::Utilities.puts_warn "Apache Tomcat #{manager} page found: #{uri}"
|
112
|
-
Yawast::Shared::Output.
|
155
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
156
|
+
'apache_tomcat_host_manager_exposed',
|
157
|
+
{vulnerable: true, uri: uri}
|
113
158
|
check_tomcat_manager_passwords uri, manager
|
114
159
|
|
115
160
|
puts ''
|
@@ -118,6 +163,9 @@ module Yawast
|
|
118
163
|
end
|
119
164
|
|
120
165
|
def self.check_tomcat_manager_passwords(uri, manager)
|
166
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
167
|
+
'apache_tomcat_manager_weak_pass',
|
168
|
+
{vulnerable: false, uri: nil, credentials: nil}
|
121
169
|
# check for known passwords
|
122
170
|
check_tomcat_manager_pwd_check uri, manager, 'tomcat:tomcat'
|
123
171
|
check_tomcat_manager_pwd_check uri, manager, 'tomcat:password'
|
@@ -133,7 +181,9 @@ module Yawast
|
|
133
181
|
ret.include?('<font size="+2">Tomcat Virtual Host Manager</font>')
|
134
182
|
Yawast::Utilities.puts_vuln "Apache Tomcat #{manager} weak password: #{credentials}"
|
135
183
|
|
136
|
-
Yawast::Shared::Output.
|
184
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
185
|
+
'apache_tomcat_manager_weak_pass',
|
186
|
+
{vulnerable: true, uri: uri, credentials: credentials}
|
137
187
|
end
|
138
188
|
end
|
139
189
|
|
@@ -142,13 +192,9 @@ module Yawast
|
|
142
192
|
uri.path = "/#{SecureRandom.hex}.jsp/"
|
143
193
|
uri.query = '' unless uri.query.nil?
|
144
194
|
|
145
|
-
Yawast::Shared::Output.log_value 'apache', 'cve_2017_12615', 'path', uri
|
146
|
-
|
147
195
|
# we'll use this to verify that it actually worked
|
148
196
|
check_value = SecureRandom.hex
|
149
197
|
|
150
|
-
Yawast::Shared::Output.log_value 'apache', 'cve_2017_12615', 'check_value', check_value
|
151
|
-
|
152
198
|
# upload the JSP file
|
153
199
|
req_data = "<% out.println(\"#{check_value}\");%>"
|
154
200
|
Yawast::Shared::Http.put(uri, req_data)
|
@@ -157,13 +203,15 @@ module Yawast
|
|
157
203
|
uri.path = uri.path.chomp('/')
|
158
204
|
res = Yawast::Shared::Http.get(uri)
|
159
205
|
|
160
|
-
Yawast::Shared::Output.log_value 'apache', 'cve_2017_12615', 'body', res
|
161
|
-
|
162
206
|
if res.include? check_value
|
163
207
|
Yawast::Utilities.puts_vuln "Apache Tomcat PUT RCE (CVE-2017-12615): #{uri}"
|
164
|
-
Yawast::Shared::Output.
|
208
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
209
|
+
'apache_tomcat_cve_2017_12615',
|
210
|
+
{vulnerable: true, uri: uri, check_value: check_value, body: res}
|
165
211
|
else
|
166
|
-
Yawast::Shared::Output.
|
212
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
213
|
+
'apache_tomcat_cve_2017_12615',
|
214
|
+
{vulnerable: false, uri: uri, check_value: check_value, body: res}
|
167
215
|
end
|
168
216
|
end
|
169
217
|
|
@@ -188,16 +236,66 @@ module Yawast
|
|
188
236
|
end
|
189
237
|
end
|
190
238
|
|
239
|
+
def self.check_cve_2019_0232(links)
|
240
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
241
|
+
'apache_tomcat_cve_2019_0232',
|
242
|
+
{vulnerable: false, uri: nil, body: nil}
|
243
|
+
|
244
|
+
# create a list of possible targets - this would be links that include "cgi-bin"
|
245
|
+
targets = []
|
246
|
+
links.each do |link|
|
247
|
+
targets.push link if link.include? '/cgi-bin/'
|
248
|
+
end
|
249
|
+
|
250
|
+
# check to see if we have any targets
|
251
|
+
unless targets.count.zero?
|
252
|
+
# we have targets
|
253
|
+
targets.each do |target|
|
254
|
+
# now, we need to build the URI we'll use
|
255
|
+
target = if target.include? '?'
|
256
|
+
target + '&dir'
|
257
|
+
else
|
258
|
+
target + '?dir'
|
259
|
+
end
|
260
|
+
|
261
|
+
# now, send the request and see if it includes "<DIR>"
|
262
|
+
target_uri = URI.parse target
|
263
|
+
body = Yawast::Shared::Http.get(target_uri)
|
264
|
+
|
265
|
+
if body.include? '<DIR>'
|
266
|
+
# we have a hit
|
267
|
+
|
268
|
+
Yawast::Utilities.puts_vuln "Apache Tomcat RCE (CVE-2019-0232): #{uri}"
|
269
|
+
|
270
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
271
|
+
'apache_tomcat_cve_2019_0232',
|
272
|
+
{vulnerable: true, uri: target_uri, body: body}
|
273
|
+
|
274
|
+
break
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
191
280
|
def self.check_page_for_string(uri, path, search)
|
192
281
|
uri.path = path
|
193
282
|
uri.query = '' unless uri.query.nil?
|
194
283
|
|
195
|
-
|
284
|
+
body = Yawast::Shared::Http.get(uri)
|
196
285
|
|
197
|
-
if
|
286
|
+
if body.include? search
|
198
287
|
Yawast::Utilities.puts_vuln "#{search} page found: #{uri}"
|
199
288
|
Yawast::Shared::Output.log_value 'apache', 'page_search', search, uri
|
289
|
+
|
290
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
291
|
+
"apache_#{path.tr('-', '_').tr('/', '')}_found",
|
292
|
+
{vulnerable: true, uri: uri, body: body}
|
293
|
+
|
200
294
|
puts ''
|
295
|
+
else
|
296
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
297
|
+
"apache_#{path.tr('-', '_').chomp('/')}_found",
|
298
|
+
{vulnerable: false, uri: uri, body: body}
|
201
299
|
end
|
202
300
|
end
|
203
301
|
end
|
@@ -6,6 +6,10 @@ module Yawast
|
|
6
6
|
module Servers
|
7
7
|
class Generic
|
8
8
|
def self.check_banner_php(banner)
|
9
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
10
|
+
'php_version_exposed',
|
11
|
+
{vulnerable: false, version: nil}
|
12
|
+
|
9
13
|
# don't bother if this doesn't include PHP
|
10
14
|
return unless banner.include? 'PHP/'
|
11
15
|
|
@@ -15,6 +19,10 @@ module Yawast
|
|
15
19
|
if mod.include? 'PHP/'
|
16
20
|
Yawast::Utilities.puts_warn "PHP Version: #{mod}"
|
17
21
|
puts ''
|
22
|
+
|
23
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
24
|
+
'php_version_exposed',
|
25
|
+
{vulnerable: true, version: mod}
|
18
26
|
end
|
19
27
|
end
|
20
28
|
end
|
@@ -6,12 +6,20 @@ module Yawast
|
|
6
6
|
module Servers
|
7
7
|
class Iis
|
8
8
|
def self.check_banner(banner)
|
9
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
10
|
+
'iis_version_exposed',
|
11
|
+
{vulnerable: false, version: nil}
|
12
|
+
|
9
13
|
# don't bother if this doesn't include IIS
|
10
14
|
return unless banner.include? 'Microsoft-IIS/'
|
11
15
|
@iis = true
|
12
16
|
|
13
17
|
Yawast::Utilities.puts_warn "IIS Version: #{banner}"
|
14
18
|
puts ''
|
19
|
+
|
20
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
21
|
+
'iis_version_exposed',
|
22
|
+
{vulnerable: true, version: banner}
|
15
23
|
end
|
16
24
|
|
17
25
|
def self.check_all(uri, head)
|
@@ -34,6 +42,14 @@ module Yawast
|
|
34
42
|
if k.downcase == search
|
35
43
|
Yawast::Utilities.puts_warn "#{message} Version: #{v}"
|
36
44
|
puts ''
|
45
|
+
|
46
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
47
|
+
"asp_net_#{search.tr('-', '_')}_version_exposed",
|
48
|
+
{vulnerable: true, version: v}
|
49
|
+
else
|
50
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
51
|
+
"asp_net_#{search.tr('-', '_')}_version_exposed",
|
52
|
+
{vulnerable: false, version: nil}
|
37
53
|
end
|
38
54
|
end
|
39
55
|
end
|
@@ -47,10 +63,17 @@ module Yawast
|
|
47
63
|
headers['Accept'] = '*/*'
|
48
64
|
res = req.request(Debug.new('/', headers))
|
49
65
|
|
50
|
-
|
66
|
+
if res.code == 200
|
67
|
+
Yawast::Utilities.puts_vuln 'ASP.NET Debugging Enabled'
|
51
68
|
|
52
|
-
|
53
|
-
|
69
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
70
|
+
'asp_net_debug_enabled',
|
71
|
+
{vulnerable: true, body: res.body, code: res.code}
|
72
|
+
else
|
73
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
74
|
+
'asp_net_debug_enabled',
|
75
|
+
{vulnerable: false, body: res.body, code: res.code}
|
76
|
+
end
|
54
77
|
end
|
55
78
|
end
|
56
79
|
end
|
@@ -6,11 +6,44 @@ module Yawast
|
|
6
6
|
module Servers
|
7
7
|
class Nginx
|
8
8
|
def self.check_banner(banner)
|
9
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
10
|
+
'nginx_version_exposed',
|
11
|
+
{vulnerable: false, version: nil}
|
12
|
+
|
9
13
|
# don't bother if this doesn't include nginx
|
10
14
|
return unless banner.include? 'nginx/'
|
11
15
|
|
12
16
|
Yawast::Utilities.puts_warn "nginx Version: #{banner}"
|
13
17
|
puts ''
|
18
|
+
|
19
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
20
|
+
'nginx_version_exposed',
|
21
|
+
{vulnerable: true, version: banner}
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.check_all(uri)
|
25
|
+
check_status_page uri.copy
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.check_status_page(uri)
|
29
|
+
uri.path = '/status'
|
30
|
+
uri.query = '' unless uri.query.nil?
|
31
|
+
|
32
|
+
body = Yawast::Shared::Http.get(uri)
|
33
|
+
|
34
|
+
if body.include? 'Active connections:'
|
35
|
+
Yawast::Utilities.puts_vuln "Nginx status page found: #{uri}"
|
36
|
+
|
37
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
38
|
+
'nginx_status_found',
|
39
|
+
{vulnerable: true, uri: uri, body: body}
|
40
|
+
|
41
|
+
puts ''
|
42
|
+
else
|
43
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
44
|
+
'nginx_status_found',
|
45
|
+
{vulnerable: false, uri: uri, body: body}
|
46
|
+
end
|
14
47
|
end
|
15
48
|
end
|
16
49
|
end
|
@@ -6,11 +6,19 @@ module Yawast
|
|
6
6
|
module Servers
|
7
7
|
class Python
|
8
8
|
def self.check_banner(banner)
|
9
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
10
|
+
'python_version_exposed',
|
11
|
+
{vulnerable: false, version: nil}
|
12
|
+
|
9
13
|
# don't bother if this doesn't include Python
|
10
14
|
return unless banner.include? 'Python/'
|
11
15
|
|
12
16
|
Yawast::Utilities.puts_warn "Python Version: #{banner}"
|
13
17
|
puts ''
|
18
|
+
|
19
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
20
|
+
'python_version_exposed',
|
21
|
+
{vulnerable: true, version: banner}
|
14
22
|
end
|
15
23
|
end
|
16
24
|
end
|
@@ -7,7 +7,7 @@ module Yawast
|
|
7
7
|
module Plugins
|
8
8
|
module Spider
|
9
9
|
class Spider
|
10
|
-
def self.spider(uri)
|
10
|
+
def self.spider(uri, silent = false)
|
11
11
|
@uri = uri.copy
|
12
12
|
|
13
13
|
@workers = []
|
@@ -15,7 +15,7 @@ module Yawast
|
|
15
15
|
|
16
16
|
@links = []
|
17
17
|
@links.push @uri.to_s
|
18
|
-
puts 'Spidering site...'
|
18
|
+
puts 'Spidering site...' unless silent
|
19
19
|
get_links @uri
|
20
20
|
|
21
21
|
results = Thread.new do
|
@@ -23,7 +23,9 @@ module Yawast
|
|
23
23
|
while true
|
24
24
|
if @results.length.positive?
|
25
25
|
out = @results.pop(true)
|
26
|
-
|
26
|
+
|
27
|
+
Yawast::Utilities.puts_info out unless silent
|
28
|
+
|
27
29
|
Yawast::Shared::Output.log_append_value 'spider', 'get', out
|
28
30
|
end
|
29
31
|
end
|
@@ -36,6 +38,8 @@ module Yawast
|
|
36
38
|
results.terminate
|
37
39
|
|
38
40
|
puts
|
41
|
+
|
42
|
+
@links
|
39
43
|
end
|
40
44
|
|
41
45
|
def self.get_links(uri)
|