Class: Wordstress::Site
- Inherits:
-
Object
- Object
- Wordstress::Site
- Defined in:
- lib/wordstress/site.rb
Instance Attribute Summary collapse
-
#plugins ⇒ Object
readonly
Returns the value of attribute plugins.
-
#scanning_mode ⇒ Object
readonly
Returns the value of attribute scanning_mode.
-
#themes ⇒ Object
readonly
Returns the value of attribute themes.
-
#themes_vuln_json ⇒ Object
readonly
Returns the value of attribute themes_vuln_json.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
-
#wp_vuln_json ⇒ Object
readonly
Returns the value of attribute wp_vuln_json.
Instance Method Summary collapse
- #detect_version ⇒ Object
- #find_plugins ⇒ Object
- #find_themes ⇒ Object
- #get(page) ⇒ Object
- #get_plugin_vulnerabilities(theme) ⇒ Object
- #get_theme_vulnerabilities(theme) ⇒ Object
- #get_themes_vulnerabilities ⇒ Object
- #get_wp_vulnerabilities ⇒ Object
-
#initialize(options = {:target=>"http://localhost", :scanning_mode=>:gentleman, :interactive=>{}}) ⇒ Site
constructor
A new instance of Site.
- #is_valid? ⇒ Boolean
- #online? ⇒ Boolean
- #post_and_get(url, pass) ⇒ Object
- #version_pad(version) ⇒ Object
Constructor Details
#initialize(options = {:target=>"http://localhost", :scanning_mode=>:gentleman, :interactive=>{}}) ⇒ Site
Returns a new instance of Site.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/wordstress/site.rb', line 8 def initialize(={:target=>"http://localhost", :scanning_mode=>:gentleman, :interactive=>{}}) begin @uri = URI([:target]) @raw_name = [:target] @valid = true rescue @valid = false end @scanning_mode = [:scanning_mode] @robots_txt = get(@raw_name + "/robots.txt") @readme_html = get(@raw_name + "/readme.html") @homepage = get(@raw_name) @version = detect_version @online = true @wp_vuln_json = get_wp_vulnerabilities unless @version[:version] == "0.0.0" @wp_vuln_json = Hash.new.to_json if @version[:version] == "0.0.0" @wordstress_page = post_and_get([:interactive][:url], [:interactive][:pwd]) if [:scanning_mode] == :interactive && ![:interactive][:pwd].empty? @wordstress_page = get([:interactive][:url]) if [:scanning_mode] == :interactive && [:interactive][:pwd].empty? @plugins = find_plugins @themes = find_themes # @themes_vuln_json = get_themes_vulnerabilities end |
Instance Attribute Details
#plugins ⇒ Object (readonly)
Returns the value of attribute plugins.
6 7 8 |
# File 'lib/wordstress/site.rb', line 6 def plugins @plugins end |
#scanning_mode ⇒ Object (readonly)
Returns the value of attribute scanning_mode.
6 7 8 |
# File 'lib/wordstress/site.rb', line 6 def scanning_mode @scanning_mode end |
#themes ⇒ Object (readonly)
Returns the value of attribute themes.
6 7 8 |
# File 'lib/wordstress/site.rb', line 6 def themes @themes end |
#themes_vuln_json ⇒ Object (readonly)
Returns the value of attribute themes_vuln_json.
6 7 8 |
# File 'lib/wordstress/site.rb', line 6 def themes_vuln_json @themes_vuln_json end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
6 7 8 |
# File 'lib/wordstress/site.rb', line 6 def version @version end |
#wp_vuln_json ⇒ Object (readonly)
Returns the value of attribute wp_vuln_json.
6 7 8 |
# File 'lib/wordstress/site.rb', line 6 def wp_vuln_json @wp_vuln_json end |
Instance Method Details
#detect_version ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/wordstress/site.rb', line 82 def detect_version # # 1. trying to detect wordpress version from homepage body meta generator # tag = "" doc = Nokogiri::HTML(@homepage.body) doc.xpath("//meta[@name='generator']/@content").each do |attr| = attr.value.split(' ')[1] end # # 2. trying to detect wordpress version from readme.html in the root # directory v_readme = "" doc = Nokogiri::HTML(@readme_html.body) v_readme = doc.at_css('h1').children.last.text.chop.lstrip.split(' ')[1] v_rss = "" rss_doc = Nokogiri::HTML(@homepage.body) begin rss = Nokogiri::HTML(get(rss_doc.css('link[type="application/rss+xml"]').first.attr('href')).body) unless l.nil? v_rss= rss.css('generator').text.split('=')[1] rescue => e v_rss = "0.0.0" end return {:version => , :accuracy => 1.0} if == v_readme && == v_rss return {:version => , :accuracy => 0.8} if == v_readme || == v_rss # we failed detecting wordpress version return {:version => "0.0.0", :accuracy => 0} end |
#find_plugins ⇒ Object
136 137 138 139 140 141 142 143 144 145 |
# File 'lib/wordstress/site.rb', line 136 def find_plugins return find_plugins_gentleman if @scanning_mode == :gentleman return find_plugins_interactive if @scanning_mode == :interactive # bruteforce check must start with error page discovery. # the idea is to send 2 random plugin names (e.g. 2 sha256 of time seed) # and see how webserver answers and then understand if we can rely on a # pattern for the error page. return [] end |
#find_themes ⇒ Object
131 132 133 134 135 |
# File 'lib/wordstress/site.rb', line 131 def find_themes return find_themes_gentleman if @scanning_mode == :gentleman return find_themes_interactive if @scanning_mode == :interactive return [] end |
#get(page) ⇒ Object
119 120 121 122 |
# File 'lib/wordstress/site.rb', line 119 def get(page) return get_http(page) if @uri.scheme == "http" return get_https(page) if @uri.scheme == "https" end |
#get_plugin_vulnerabilities(theme) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/wordstress/site.rb', line 41 def get_plugin_vulnerabilities(theme) begin json= get_https("https://wpvulndb.com/api/v1/plugins/#{theme}").body return "Plugin #{theme} is not present on wpvulndb.com" if json.include?"The page you were looking for doesn't exist (404)" return json rescue => e $logger.err e. @online = false return [] end end |
#get_theme_vulnerabilities(theme) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/wordstress/site.rb', line 53 def get_theme_vulnerabilities(theme) begin json=get_https("https://wpvulndb.com/api/v1/themes/#{theme}").body return "Theme #{theme} is not present on wpvulndb.com" if json.include?"The page you were looking for doesn't exist (404)" return json rescue => e $logger.err e. @online = false return [] end end |
#get_themes_vulnerabilities ⇒ Object
34 35 36 37 38 39 |
# File 'lib/wordstress/site.rb', line 34 def get_themes_vulnerabilities vuln = [] @themes.each do |t| vuln << {:theme=>t, :vulns=>get_theme_vulnerabilities(t)} end end |
#get_wp_vulnerabilities ⇒ Object
65 66 67 68 69 70 71 72 73 |
# File 'lib/wordstress/site.rb', line 65 def get_wp_vulnerabilities begin return get_https("https://wpvulndb.com/api/v1/wordpresses/#{version_pad(@version[:version])}").body rescue => e $logger.err e. @online = false return "" end end |
#is_valid? ⇒ Boolean
124 125 126 |
# File 'lib/wordstress/site.rb', line 124 def is_valid? return @valid end |
#online? ⇒ Boolean
127 128 129 |
# File 'lib/wordstress/site.rb', line 127 def online? return @online end |
#post_and_get(url, pass) ⇒ Object
147 148 149 150 151 152 |
# File 'lib/wordstress/site.rb', line 147 def post_and_get(url, pass) uri = URI(url) res = Net::HTTP.post_form(uri, {'post_password' => pass, 'Submit'=>'Submit'}) get(url) res.body end |
#version_pad(version) ⇒ Object
75 76 77 78 79 80 |
# File 'lib/wordstress/site.rb', line 75 def version_pad(version) # 3.2.1 => 321 # 4.0 => 400 return version.gsub('.', '') if version.split('.').count == 3 return version.gsub('.', '')+'0' if version.split('.').count == 2 end |