Class: WPScan::Finders::Themes::WpJsonApi

Inherits:
Finder
  • Object
show all
Defined in:
app/finders/themes/wp_json_api.rb

Overview

Authenticated theme inventory via the WordPress REST API endpoint /wp-json/wp/v2/themes (WP >= 5.7).

Requires admin credentials with the switch_themes capability.

Constant Summary collapse

FOUND_BY =
'WP REST API (Authenticated)'

Constants inherited from Finder

Finder::DIRECT_ACCESS

Instance Attribute Summary

Attributes inherited from Finder

#progress_bar, #target

Instance Method Summary collapse

Methods inherited from Finder

#browser, #create_progress_bar, #found_by, #hydra, #initialize, #passive, #titleize

Constructor Details

This class inherits a constructor from WPScan::Finders::Finder

Instance Method Details

#aggressive(opts = {}) ⇒ Array<Model::Theme>

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :userpwd (String)

    “user:password” credentials for Basic Auth

Returns:



17
18
19
20
21
22
23
24
25
26
# File 'app/finders/themes/wp_json_api.rb', line 17

def aggressive(opts = {})
  response = Browser.get(api_url, userpwd: opts[:userpwd], headers: { 'Accept' => 'application/json' })

  raise Error::WpAuthFailed.new(response.code, api_url) if [401, 403].include?(response.code)
  raise Error::WpAuthEndpointUnavailable.new(response.code, api_url) unless response.code == 200

  themes_from_response(response)
rescue JSON::ParserError, TypeError
  []
end

#api_urlString

Returns The REST API URL for the themes endpoint.

Returns:

  • (String)

    The REST API URL for the themes endpoint



39
40
41
# File 'app/finders/themes/wp_json_api.rb', line 39

def api_url
  @api_url ||= target.url('wp-json/wp/v2/themes')
end

#themes_from_response(response) ⇒ Array<Model::Theme>

Parameters:

Returns:



31
32
33
34
35
36
# File 'app/finders/themes/wp_json_api.rb', line 31

def themes_from_response(response)
  json = JSON.parse(response.body)
  return [] unless json.is_a?(Enumerable)

  json.filter_map { |entry| build_theme(entry, response.effective_url) }
end