Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adff971d62 | ||
|
|
23b22f71b8 | ||
|
|
fee3671e32 | ||
|
|
26c6be7268 | ||
|
|
01c5bcf2be | ||
|
|
1ab8a5ab98 | ||
|
|
b54aaca28a | ||
|
|
86a29ae000 | ||
|
|
a5dbee93ff | ||
|
|
e0465e6e10 | ||
|
|
7da48b9dd1 | ||
|
|
a64895c3a6 | ||
|
|
21f1a5d4c4 | ||
|
|
d60f79ca33 | ||
|
|
2d5cea5033 | ||
|
|
b0615215fe | ||
|
|
7a0f98b2cb | ||
|
|
cdc1dab4a6 | ||
|
|
431739ab19 | ||
|
|
1780399050 | ||
|
|
eb75d38716 | ||
|
|
06f82d78f4 | ||
|
|
dee4da1c0e | ||
|
|
e341ec7c60 | ||
|
|
9146609e4a | ||
|
|
f90615ca41 | ||
|
|
8a2a6a05ff | ||
|
|
5a787f8ed5 | ||
|
|
a904053002 | ||
|
|
70ecd30dcc | ||
|
|
b0976d7e47 | ||
|
|
bb5e55016c | ||
|
|
abdf285c69 | ||
|
|
fd4da23d4f | ||
|
|
bb8f58c83b | ||
|
|
077da6ae86 | ||
|
|
d5222d7e9a | ||
|
|
01702c127b | ||
|
|
87902cbfb4 | ||
|
|
fcaa393ffe | ||
|
|
18bac6e792 | ||
|
|
9a21efebe3 | ||
|
|
357182ef17 |
@@ -1 +1 @@
|
|||||||
2.5.3
|
2.6.0
|
||||||
|
|||||||
4
.simplecov
Normal file
4
.simplecov
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
SimpleCov.start do
|
||||||
|
add_filter '/spec/'
|
||||||
|
add_filter 'helper'
|
||||||
|
end
|
||||||
@@ -20,10 +20,11 @@ rvm:
|
|||||||
- 2.5.1
|
- 2.5.1
|
||||||
- 2.5.2
|
- 2.5.2
|
||||||
- 2.5.3
|
- 2.5.3
|
||||||
|
- 2.6.0
|
||||||
- ruby-head
|
- ruby-head
|
||||||
before_install:
|
before_install:
|
||||||
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
|
- "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
|
||||||
- "gem update --system"
|
- gem update --system
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- rvm: ruby-head
|
- rvm: ruby-head
|
||||||
|
|||||||
10
LICENSE
10
LICENSE
@@ -1,14 +1,14 @@
|
|||||||
WPScan Public Source License
|
WPScan Public Source License
|
||||||
|
|
||||||
The WPScan software (henceforth referred to simply as "WPScan") is dual-licensed - Copyright 2011-2018 WPScan Team.
|
The WPScan software (henceforth referred to simply as "WPScan") is dual-licensed - Copyright 2011-2019 WPScan Team.
|
||||||
|
|
||||||
Cases that include commercialization of WPScan require a commercial, non-free license. Otherwise, WPScan can be used without charge under the terms set out below.
|
Cases that include commercialization of WPScan require a commercial, non-free license. Otherwise, WPScan can be used without charge under the terms set out below.
|
||||||
|
|
||||||
1. Definitions
|
1. Definitions
|
||||||
|
|
||||||
1.1 “License” means this document.
|
1.1 "License" means this document.
|
||||||
1.2 “Contributor” means each individual or legal entity that creates, contributes to the creation of, or owns WPScan.
|
1.2 "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns WPScan.
|
||||||
1.3 “WPScan Team” means WPScan’s core developers, an updated list of whom can be found within the CREDITS file.
|
1.3 "WPScan Team" means WPScan’s core developers.
|
||||||
|
|
||||||
2. Commercialization
|
2. Commercialization
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ WPScan is provided under an AS-IS basis and without any support, updates or main
|
|||||||
|
|
||||||
8. Disclaimer of Warranty
|
8. Disclaimer of Warranty
|
||||||
|
|
||||||
WPScan is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the WPScan is free of defects, merchantable, fit for a particular purpose or non-infringing.
|
WPScan is provided under this License on an "as is" basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the WPScan is free of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||||
|
|
||||||
9. Limitation of Liability
|
9. Limitation of Liability
|
||||||
|
|
||||||
|
|||||||
79
README.md
79
README.md
@@ -7,23 +7,28 @@
|
|||||||
|
|
||||||
# INSTALL
|
# INSTALL
|
||||||
|
|
||||||
## Prerequisites:
|
## Prerequisites
|
||||||
|
|
||||||
|
- (Optional but highly recommended: [RVM](https://rvm.io/rvm/install))
|
||||||
- Ruby >= 2.3 - Recommended: latest
|
- Ruby >= 2.3 - Recommended: latest
|
||||||
- Curl >= 7.21 - Recommended: latest - FYI the 7.29 has a segfault
|
- Ruby 2.5.0 to 2.5.3 can cause an 'undefined symbol: rmpd_util_str_to_d' error in some systems, see [#1283](https://github.com/wpscanteam/wpscan/issues/1283)
|
||||||
|
- Curl >= 7.21 - Recommended: latest
|
||||||
|
- The 7.29 has a segfault
|
||||||
- RubyGems - Recommended: latest
|
- RubyGems - Recommended: latest
|
||||||
|
|
||||||
### From RubyGems:
|
### From RubyGems (Recommended)
|
||||||
|
|
||||||
```
|
```shell
|
||||||
gem install wpscan
|
gem install wpscan
|
||||||
```
|
```
|
||||||
|
|
||||||
### From sources:
|
On MacOSX, if a ```Gem::FilePermissionError``` is raised due to the Apple's System Integrity Protection (SIP), either install RVM and install wpscan again, or run ```sudo gem install -n /usr/local/bin wpscan``` (see [#1286](https://github.com/wpscanteam/wpscan/issues/1286))
|
||||||
|
|
||||||
|
### From sources (NOT Recommended)
|
||||||
|
|
||||||
Prerequisites: Git
|
Prerequisites: Git
|
||||||
|
|
||||||
```
|
```shell
|
||||||
git clone https://github.com/wpscanteam/wpscan
|
git clone https://github.com/wpscanteam/wpscan
|
||||||
|
|
||||||
cd wpscan/
|
cd wpscan/
|
||||||
@@ -31,19 +36,28 @@ cd wpscan/
|
|||||||
bundle install && rake install
|
bundle install && rake install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Updating
|
||||||
|
|
||||||
|
You can update the local database by using ```wpscan --update```
|
||||||
|
|
||||||
|
Updating WPScan itself is either done via ```gem update wpscan``` or the packages manager (this is quite important for distributions such as in Kali Linux: ```apt-get update && apt-get upgrade```) depending how WPScan was (pre)installed
|
||||||
|
|
||||||
# Docker
|
# Docker
|
||||||
|
|
||||||
Pull the repo with ```docker pull wpscanteam/wpscan```
|
Pull the repo with ```docker pull wpscanteam/wpscan```
|
||||||
|
|
||||||
Enumerating usernames
|
Enumerating usernames
|
||||||
```
|
|
||||||
|
```shell
|
||||||
docker run -it --rm wpscanteam/wpscan --url https://target.tld/ --enumerate u
|
docker run -it --rm wpscanteam/wpscan --url https://target.tld/ --enumerate u
|
||||||
```
|
```
|
||||||
|
|
||||||
Enumerating a range of usernames
|
Enumerating a range of usernames
|
||||||
```
|
|
||||||
|
```shell
|
||||||
docker run -it --rm wpscanteam/wpscan --url https://target.tld/ --enumerate u1-100
|
docker run -it --rm wpscanteam/wpscan --url https://target.tld/ --enumerate u1-100
|
||||||
```
|
```
|
||||||
|
|
||||||
** replace u1-100 with a range of your choice.
|
** replace u1-100 with a range of your choice.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
@@ -57,41 +71,44 @@ The DB is located at ~/.wpscan/db
|
|||||||
|
|
||||||
WPScan can load all options (including the --url) from configuration files, the following locations are checked (order: first to last):
|
WPScan can load all options (including the --url) from configuration files, the following locations are checked (order: first to last):
|
||||||
|
|
||||||
* ~/.wpscan/cli_options.json
|
- ~/.wpscan/cli_options.json
|
||||||
* ~/.wpscan/cli_options.yml
|
- ~/.wpscan/cli_options.yml
|
||||||
* pwd/.wpscan/cli_options.json
|
- pwd/.wpscan/cli_options.json
|
||||||
* pwd/.wpscan/cli_options.yml
|
- pwd/.wpscan/cli_options.yml
|
||||||
|
|
||||||
If those files exist, options from them will be loaded and overridden if found twice.
|
If those files exist, options from them will be loaded and overridden if found twice.
|
||||||
|
|
||||||
e.g:
|
e.g:
|
||||||
|
|
||||||
~/.wpscan/cli_options.yml:
|
~/.wpscan/cli_options.yml:
|
||||||
```
|
|
||||||
|
```yml
|
||||||
proxy: 'http://127.0.0.1:8080'
|
proxy: 'http://127.0.0.1:8080'
|
||||||
verbose: true
|
verbose: true
|
||||||
```
|
```
|
||||||
|
|
||||||
pwd/.wpscan/cli_options.yml:
|
pwd/.wpscan/cli_options.yml:
|
||||||
```
|
|
||||||
|
```yml
|
||||||
proxy: 'socks5://127.0.0.1:9090'
|
proxy: 'socks5://127.0.0.1:9090'
|
||||||
url: 'http://target.tld'
|
url: 'http://target.tld'
|
||||||
```
|
```
|
||||||
|
|
||||||
Running ```wpscan``` in the current directory (pwd), is the same as ```wpscan -v --proxy socks5://127.0.0.1:9090 --url http://target.tld```
|
Running ```wpscan``` in the current directory (pwd), is the same as ```wpscan -v --proxy socks5://127.0.0.1:9090 --url http://target.tld```
|
||||||
|
|
||||||
|
|
||||||
Enumerating usernames
|
Enumerating usernames
|
||||||
```
|
|
||||||
|
```shell
|
||||||
wpscan --url https://target.tld/ --enumerate u
|
wpscan --url https://target.tld/ --enumerate u
|
||||||
```
|
```
|
||||||
|
|
||||||
Enumerating a range of usernames
|
Enumerating a range of usernames
|
||||||
```
|
|
||||||
|
```shell
|
||||||
wpscan --url https://target.tld/ --enumerate u1-100
|
wpscan --url https://target.tld/ --enumerate u1-100
|
||||||
```
|
```
|
||||||
** replace u1-100 with a range of your choice.
|
|
||||||
|
|
||||||
|
** replace u1-100 with a range of your choice.
|
||||||
|
|
||||||
# PROJECT HOME
|
# PROJECT HOME
|
||||||
|
|
||||||
@@ -105,7 +122,7 @@ wpscan --url https://target.tld/ --enumerate u1-100
|
|||||||
|
|
||||||
## WPScan Public Source License
|
## WPScan Public Source License
|
||||||
|
|
||||||
The WPScan software (henceforth referred to simply as "WPScan") is dual-licensed - Copyright 2011-2018 WPScan Team.
|
The WPScan software (henceforth referred to simply as "WPScan") is dual-licensed - Copyright 2011-2019 WPScan Team.
|
||||||
|
|
||||||
Cases that include commercialization of WPScan require a commercial, non-free license. Otherwise, WPScan can be used without charge under the terms set out below.
|
Cases that include commercialization of WPScan require a commercial, non-free license. Otherwise, WPScan can be used without charge under the terms set out below.
|
||||||
|
|
||||||
@@ -115,7 +132,7 @@ Cases that include commercialization of WPScan require a commercial, non-free li
|
|||||||
|
|
||||||
1.2 "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns WPScan.
|
1.2 "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns WPScan.
|
||||||
|
|
||||||
1.3 "WPScan Team" means WPScan’s core developers, an updated list of whom can be found within the CREDITS file.
|
1.3 "WPScan Team" means WPScan’s core developers.
|
||||||
|
|
||||||
### 2. Commercialization
|
### 2. Commercialization
|
||||||
|
|
||||||
@@ -123,30 +140,28 @@ A commercial use is one intended for commercial advantage or monetary compensati
|
|||||||
|
|
||||||
Example cases of commercialization are:
|
Example cases of commercialization are:
|
||||||
|
|
||||||
- Using WPScan to provide commercial managed/Software-as-a-Service services.
|
- Using WPScan to provide commercial managed/Software-as-a-Service services.
|
||||||
- Distributing WPScan as a commercial product or as part of one.
|
- Distributing WPScan as a commercial product or as part of one.
|
||||||
- Using WPScan as a value added service/product.
|
- Using WPScan as a value added service/product.
|
||||||
|
|
||||||
Example cases which do not require a commercial license, and thus fall under the terms set out below, include (but are not limited to):
|
Example cases which do not require a commercial license, and thus fall under the terms set out below, include (but are not limited to):
|
||||||
|
|
||||||
- Penetration testers (or penetration testing organizations) using WPScan as part of their assessment toolkit.
|
- Penetration testers (or penetration testing organizations) using WPScan as part of their assessment toolkit.
|
||||||
- Penetration Testing Linux Distributions including but not limited to Kali Linux, SamuraiWTF, BackBox Linux.
|
- Penetration Testing Linux Distributions including but not limited to Kali Linux, SamuraiWTF, BackBox Linux.
|
||||||
- Using WPScan to test your own systems.
|
- Using WPScan to test your own systems.
|
||||||
- Any non-commercial use of WPScan.
|
- Any non-commercial use of WPScan.
|
||||||
|
|
||||||
If you need to purchase a commercial license or are unsure whether you need to purchase a commercial license contact us - team@wpscan.org.
|
If you need to purchase a commercial license or are unsure whether you need to purchase a commercial license contact us - team@wpscan.org.
|
||||||
|
|
||||||
We may grant commercial licenses at no monetary cost at our own discretion if the commercial usage is deemed by the WPScan Team to significantly benefit WPScan.
|
|
||||||
|
|
||||||
Free-use Terms and Conditions;
|
Free-use Terms and Conditions;
|
||||||
|
|
||||||
### 3. Redistribution
|
### 3. Redistribution
|
||||||
|
|
||||||
Redistribution is permitted under the following conditions:
|
Redistribution is permitted under the following conditions:
|
||||||
|
|
||||||
- Unmodified License is provided with WPScan.
|
- Unmodified License is provided with WPScan.
|
||||||
- Unmodified Copyright notices are provided with WPScan.
|
- Unmodified Copyright notices are provided with WPScan.
|
||||||
- Does not conflict with the commercialization clause.
|
- Does not conflict with the commercialization clause.
|
||||||
|
|
||||||
### 4. Copying
|
### 4. Copying
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ module WPScan
|
|||||||
exit(WPScan::ExitCode::VULNERABLE)
|
exit(WPScan::ExitCode::VULNERABLE)
|
||||||
end
|
end
|
||||||
|
|
||||||
raise NotWordPressError unless target.wordpress? || parsed_options[:force]
|
raise NotWordPressError unless target.wordpress?(parsed_options[:detection_mode]) || parsed_options[:force]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Loads the related server module in the target
|
# Loads the related server module in the target
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ module WPScan
|
|||||||
[
|
[
|
||||||
OptFilePath.new(
|
OptFilePath.new(
|
||||||
['--timthumbs-list FILE-PATH', 'List of timthumbs\' location to use'],
|
['--timthumbs-list FILE-PATH', 'List of timthumbs\' location to use'],
|
||||||
exists: true, default: File.join(DB_DIR, 'timthumbs-v3.txt'), advanced: true
|
exists: true, default: DB_DIR.join('timthumbs-v3.txt').to_s, advanced: true
|
||||||
),
|
),
|
||||||
OptChoice.new(
|
OptChoice.new(
|
||||||
['--timthumbs-detection MODE',
|
['--timthumbs-detection MODE',
|
||||||
@@ -113,7 +113,7 @@ module WPScan
|
|||||||
[
|
[
|
||||||
OptFilePath.new(
|
OptFilePath.new(
|
||||||
['--config-backups-list FILE-PATH', 'List of config backups\' filenames to use'],
|
['--config-backups-list FILE-PATH', 'List of config backups\' filenames to use'],
|
||||||
exists: true, default: File.join(DB_DIR, 'config_backups.txt'), advanced: true
|
exists: true, default: DB_DIR.join('config_backups.txt').to_s, advanced: true
|
||||||
),
|
),
|
||||||
OptChoice.new(
|
OptChoice.new(
|
||||||
['--config-backups-detection MODE',
|
['--config-backups-detection MODE',
|
||||||
@@ -128,7 +128,7 @@ module WPScan
|
|||||||
[
|
[
|
||||||
OptFilePath.new(
|
OptFilePath.new(
|
||||||
['--db-exports-list FILE-PATH', 'List of DB exports\' paths to use'],
|
['--db-exports-list FILE-PATH', 'List of DB exports\' paths to use'],
|
||||||
exists: true, default: File.join(DB_DIR, 'db_exports.txt'), advanced: true
|
exists: true, default: DB_DIR.join('db_exports.txt').to_s, advanced: true
|
||||||
),
|
),
|
||||||
OptChoice.new(
|
OptChoice.new(
|
||||||
['--db-exports-detection MODE',
|
['--db-exports-detection MODE',
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ module WPScan
|
|||||||
# Enumeration Methods
|
# Enumeration Methods
|
||||||
class Enumeration < CMSScanner::Controller::Base
|
class Enumeration < CMSScanner::Controller::Base
|
||||||
# @param [ String ] type (plugins or themes)
|
# @param [ String ] type (plugins or themes)
|
||||||
|
# @param [ Symbol ] detection_mode
|
||||||
#
|
#
|
||||||
# @return [ String ] The related enumration message depending on the parsed_options and type supplied
|
# @return [ String ] The related enumration message depending on the parsed_options and type supplied
|
||||||
def enum_message(type)
|
def enum_message(type, detection_mode)
|
||||||
return unless %w[plugins themes].include?(type)
|
return unless %w[plugins themes].include?(type)
|
||||||
|
|
||||||
details = if parsed_options[:enumerate][:"vulnerable_#{type}"]
|
details = if parsed_options[:enumerate][:"vulnerable_#{type}"]
|
||||||
@@ -16,7 +17,20 @@ module WPScan
|
|||||||
'Most Popular'
|
'Most Popular'
|
||||||
end
|
end
|
||||||
|
|
||||||
"Enumerating #{details} #{type.capitalize}"
|
"Enumerating #{details} #{type.capitalize} #{enum_detection_message(detection_mode)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [ Symbol ] detection_mode
|
||||||
|
#
|
||||||
|
# @return [ String ]
|
||||||
|
def enum_detection_message(detection_mode)
|
||||||
|
detection_method = if detection_mode == :mixed
|
||||||
|
'Passive and Aggressive'
|
||||||
|
else
|
||||||
|
detection_mode.to_s.capitalize
|
||||||
|
end
|
||||||
|
|
||||||
|
"(via #{detection_method} Methods)"
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ String ] type (plugins, themes etc)
|
# @param [ String ] type (plugins, themes etc)
|
||||||
@@ -49,12 +63,15 @@ module WPScan
|
|||||||
sort: true
|
sort: true
|
||||||
)
|
)
|
||||||
|
|
||||||
output('@info', msg: enum_message('plugins')) if user_interaction?
|
output('@info', msg: enum_message('plugins', opts[:mode])) if user_interaction?
|
||||||
# Enumerate the plugins & find their versions to avoid doing that when #version
|
# Enumerate the plugins & find their versions to avoid doing that when #version
|
||||||
# is called in the view
|
# is called in the view
|
||||||
plugins = target.plugins(opts)
|
plugins = target.plugins(opts)
|
||||||
|
|
||||||
output('@info', msg: 'Checking Plugin Versions') if user_interaction? && !plugins.empty?
|
if user_interaction? && !plugins.empty?
|
||||||
|
output('@info',
|
||||||
|
msg: "Checking Plugin Versions #{enum_detection_message(opts[:version_detection][:mode])}")
|
||||||
|
end
|
||||||
|
|
||||||
plugins.each(&:version)
|
plugins.each(&:version)
|
||||||
|
|
||||||
@@ -92,12 +109,15 @@ module WPScan
|
|||||||
sort: true
|
sort: true
|
||||||
)
|
)
|
||||||
|
|
||||||
output('@info', msg: enum_message('themes')) if user_interaction?
|
output('@info', msg: enum_message('themes', opts[:mode])) if user_interaction?
|
||||||
# Enumerate the themes & find their versions to avoid doing that when #version
|
# Enumerate the themes & find their versions to avoid doing that when #version
|
||||||
# is called in the view
|
# is called in the view
|
||||||
themes = target.themes(opts)
|
themes = target.themes(opts)
|
||||||
|
|
||||||
output('@info', msg: 'Checking Theme Versions') if user_interaction? && !themes.empty?
|
if user_interaction? && !themes.empty?
|
||||||
|
output('@info',
|
||||||
|
msg: "Checking Theme Versions #{enum_detection_message(opts[:version_detection][:mode])}")
|
||||||
|
end
|
||||||
|
|
||||||
themes.each(&:version)
|
themes.each(&:version)
|
||||||
|
|
||||||
@@ -125,21 +145,21 @@ module WPScan
|
|||||||
def enum_timthumbs
|
def enum_timthumbs
|
||||||
opts = default_opts('timthumbs').merge(list: parsed_options[:timthumbs_list])
|
opts = default_opts('timthumbs').merge(list: parsed_options[:timthumbs_list])
|
||||||
|
|
||||||
output('@info', msg: 'Enumerating Timthumbs') if user_interaction?
|
output('@info', msg: "Enumerating Timthumbs #{enum_detection_message(opts[:mode])}") if user_interaction?
|
||||||
output('timthumbs', timthumbs: target.timthumbs(opts))
|
output('timthumbs', timthumbs: target.timthumbs(opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def enum_config_backups
|
def enum_config_backups
|
||||||
opts = default_opts('config_backups').merge(list: parsed_options[:config_backups_list])
|
opts = default_opts('config_backups').merge(list: parsed_options[:config_backups_list])
|
||||||
|
|
||||||
output('@info', msg: 'Enumerating Config Backups') if user_interaction?
|
output('@info', msg: "Enumerating Config Backups #{enum_detection_message(opts[:mode])}") if user_interaction?
|
||||||
output('config_backups', config_backups: target.config_backups(opts))
|
output('config_backups', config_backups: target.config_backups(opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def enum_db_exports
|
def enum_db_exports
|
||||||
opts = default_opts('db_exports').merge(list: parsed_options[:db_exports_list])
|
opts = default_opts('db_exports').merge(list: parsed_options[:db_exports_list])
|
||||||
|
|
||||||
output('@info', msg: 'Enumerating DB Exports') if user_interaction?
|
output('@info', msg: "Enumerating DB Exports #{enum_detection_message(opts[:mode])}") if user_interaction?
|
||||||
output('db_exports', db_exports: target.db_exports(opts))
|
output('db_exports', db_exports: target.db_exports(opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -147,7 +167,9 @@ module WPScan
|
|||||||
opts = default_opts('medias').merge(range: parsed_options[:enumerate][:medias])
|
opts = default_opts('medias').merge(range: parsed_options[:enumerate][:medias])
|
||||||
|
|
||||||
if user_interaction?
|
if user_interaction?
|
||||||
output('@info', msg: 'Enumerating Medias (Permalink setting must be set to "Plain" for those to be detected)')
|
output('@info',
|
||||||
|
msg: "Enumerating Medias #{enum_detection_message(opts[:mode])} "\
|
||||||
|
'(Permalink setting must be set to "Plain" for those to be detected)')
|
||||||
end
|
end
|
||||||
|
|
||||||
output('medias', medias: target.medias(opts))
|
output('medias', medias: target.medias(opts))
|
||||||
@@ -166,7 +188,7 @@ module WPScan
|
|||||||
list: parsed_options[:users_list]
|
list: parsed_options[:users_list]
|
||||||
)
|
)
|
||||||
|
|
||||||
output('@info', msg: 'Enumerating Users') if user_interaction?
|
output('@info', msg: "Enumerating Users #{enum_detection_message(opts[:mode])}") if user_interaction?
|
||||||
output('users', users: target.users(opts))
|
output('users', users: target.users(opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -65,8 +65,12 @@ module WPScan
|
|||||||
when :wp_login
|
when :wp_login
|
||||||
WPScan::Finders::Passwords::WpLogin.new(target)
|
WPScan::Finders::Passwords::WpLogin.new(target)
|
||||||
when :xmlrpc
|
when :xmlrpc
|
||||||
|
raise XMLRPCNotDetected unless xmlrpc
|
||||||
|
|
||||||
WPScan::Finders::Passwords::XMLRPC.new(xmlrpc)
|
WPScan::Finders::Passwords::XMLRPC.new(xmlrpc)
|
||||||
when :xmlrpc_multicall
|
when :xmlrpc_multicall
|
||||||
|
raise XMLRPCNotDetected unless xmlrpc
|
||||||
|
|
||||||
WPScan::Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
|
WPScan::Finders::Passwords::XMLRPCMulticall.new(xmlrpc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
require_relative 'interesting_findings/readme'
|
require_relative 'interesting_findings/readme'
|
||||||
|
require_relative 'interesting_findings/wp_cron'
|
||||||
require_relative 'interesting_findings/multisite'
|
require_relative 'interesting_findings/multisite'
|
||||||
require_relative 'interesting_findings/debug_log'
|
require_relative 'interesting_findings/debug_log'
|
||||||
require_relative 'interesting_findings/backup_db'
|
require_relative 'interesting_findings/backup_db'
|
||||||
@@ -23,7 +24,7 @@ module WPScan
|
|||||||
%w[
|
%w[
|
||||||
Readme DebugLog FullPathDisclosure BackupDB DuplicatorInstallerLog
|
Readme DebugLog FullPathDisclosure BackupDB DuplicatorInstallerLog
|
||||||
Multisite MuPlugins Registration UploadDirectoryListing TmmDbMigrate
|
Multisite MuPlugins Registration UploadDirectoryListing TmmDbMigrate
|
||||||
UploadSQLDump EmergencyPwdResetScript
|
UploadSQLDump EmergencyPwdResetScript WPCron
|
||||||
].each do |f|
|
].each do |f|
|
||||||
finders << InterestingFindings.const_get(f).new(target)
|
finders << InterestingFindings.const_get(f).new(target)
|
||||||
end
|
end
|
||||||
|
|||||||
31
app/finders/interesting_findings/wp_cron.rb
Normal file
31
app/finders/interesting_findings/wp_cron.rb
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
module WPScan
|
||||||
|
module Finders
|
||||||
|
module InterestingFindings
|
||||||
|
# wp-cron.php finder
|
||||||
|
class WPCron < CMSScanner::Finders::Finder
|
||||||
|
# @return [ InterestingFinding ]
|
||||||
|
def aggressive(_opts = {})
|
||||||
|
res = Browser.get(wp_cron_url)
|
||||||
|
|
||||||
|
return unless res.code == 200
|
||||||
|
|
||||||
|
WPScan::WPCron.new(
|
||||||
|
wp_cron_url,
|
||||||
|
confidence: 60,
|
||||||
|
found_by: DIRECT_ACCESS,
|
||||||
|
references: {
|
||||||
|
url: [
|
||||||
|
'https://www.iplocation.net/defend-wordpress-from-ddos',
|
||||||
|
'https://github.com/wpscanteam/wpscan/issues/1299'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def wp_cron_url
|
||||||
|
@wp_cron_url ||= target.url('wp-cron.php')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -4,20 +4,29 @@ module WPScan
|
|||||||
# WP JSON API
|
# WP JSON API
|
||||||
#
|
#
|
||||||
# Since 4.7 - Need more investigation as it seems WP 4.7.1 reduces the exposure, see https://github.com/wpscanteam/wpscan/issues/1038)
|
# Since 4.7 - Need more investigation as it seems WP 4.7.1 reduces the exposure, see https://github.com/wpscanteam/wpscan/issues/1038)
|
||||||
|
# For the pagination, see https://github.com/wpscanteam/wpscan/issues/1285
|
||||||
#
|
#
|
||||||
class WpJsonApi < CMSScanner::Finders::Finder
|
class WpJsonApi < CMSScanner::Finders::Finder
|
||||||
|
MAX_PER_PAGE = 100 # See https://developer.wordpress.org/rest-api/using-the-rest-api/pagination/
|
||||||
|
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
#
|
#
|
||||||
# @return [ Array<User> ]
|
# @return [ Array<User> ]
|
||||||
def aggressive(_opts = {})
|
def aggressive(_opts = {})
|
||||||
found = []
|
found = []
|
||||||
|
current_page = 0
|
||||||
|
|
||||||
JSON.parse(Browser.get(api_url).body)&.each do |user|
|
loop do
|
||||||
found << CMSScanner::User.new(user['slug'],
|
current_page += 1
|
||||||
id: user['id'],
|
|
||||||
found_by: found_by,
|
res = Typhoeus.get(api_url, params: { per_page: MAX_PER_PAGE, page: current_page })
|
||||||
confidence: 100,
|
|
||||||
interesting_entries: [api_url])
|
total_pages ||= res.headers['X-WP-TotalPages'].to_i
|
||||||
|
|
||||||
|
users_in_page = users_from_response(res)
|
||||||
|
found += users_in_page
|
||||||
|
|
||||||
|
break if current_page >= total_pages || users_in_page.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
@@ -25,6 +34,23 @@ module WPScan
|
|||||||
found
|
found
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @param [ Typhoeus::Response ] response
|
||||||
|
#
|
||||||
|
# @return [ Array<User> ] The users from the response
|
||||||
|
def users_from_response(response)
|
||||||
|
found = []
|
||||||
|
|
||||||
|
JSON.parse(response.body)&.each do |user|
|
||||||
|
found << CMSScanner::User.new(user['slug'],
|
||||||
|
id: user['id'],
|
||||||
|
found_by: found_by,
|
||||||
|
confidence: 100,
|
||||||
|
interesting_entries: [response.effective_url])
|
||||||
|
end
|
||||||
|
|
||||||
|
found
|
||||||
|
end
|
||||||
|
|
||||||
# @return [ String ] The URL of the API listing the Users
|
# @return [ String ] The URL of the API listing the Users
|
||||||
def api_url
|
def api_url
|
||||||
@api_url ||= target.url('wp-json/wp/v2/users/')
|
@api_url ||= target.url('wp-json/wp/v2/users/')
|
||||||
|
|||||||
@@ -42,4 +42,7 @@ module WPScan
|
|||||||
|
|
||||||
class UploadSQLDump < InterestingFinding
|
class UploadSQLDump < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class WPCron < InterestingFinding
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ module WPScan
|
|||||||
include CMSScanner
|
include CMSScanner
|
||||||
|
|
||||||
APP_DIR = Pathname.new(__FILE__).dirname.join('..', 'app').expand_path
|
APP_DIR = Pathname.new(__FILE__).dirname.join('..', 'app').expand_path
|
||||||
DB_DIR = File.join(Dir.home, '.wpscan', 'db')
|
DB_DIR = Pathname.new(Dir.home).join('.wpscan', 'db')
|
||||||
|
|
||||||
# Override, otherwise it would be returned as 'wp_scan'
|
# Override, otherwise it would be returned as 'wp_scan'
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module WPScan
|
|||||||
|
|
||||||
# @return [ String ] The path to the user agents list
|
# @return [ String ] The path to the user agents list
|
||||||
def user_agents_list
|
def user_agents_list
|
||||||
@user_agents_list ||= File.join(DB_DIR, 'user-agents.txt')
|
@user_agents_list ||= DB_DIR.join('user-agents.txt').to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module WPScan
|
|||||||
class Base
|
class Base
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
def self.db_file
|
def self.db_file
|
||||||
@db_file ||= File.join(DB_DIR, 'dynamic_finders.yml')
|
@db_file ||= DB_DIR.join('dynamic_finders.yml').to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Hash ]
|
# @return [ Hash ]
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ module WPScan
|
|||||||
|
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
def self.wp_fingerprints_path
|
def self.wp_fingerprints_path
|
||||||
@wp_fingerprints_path ||= File.join(DB_DIR, 'wp_fingerprints.json')
|
@wp_fingerprints_path ||= DB_DIR.join('wp_fingerprints.json').to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Hash ]
|
# @return [ Hash ]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module WPScan
|
|||||||
class Plugin < WpItem
|
class Plugin < WpItem
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
def self.db_file
|
def self.db_file
|
||||||
@db_file ||= File.join(DB_DIR, 'plugins.json')
|
@db_file ||= DB_DIR.join('plugins.json').to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module WPScan
|
|||||||
class Theme < WpItem
|
class Theme < WpItem
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
def self.db_file
|
def self.db_file
|
||||||
@db_file ||= File.join(DB_DIR, 'themes.json')
|
@db_file ||= DB_DIR.join('themes.json').to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ module WPScan
|
|||||||
attr_reader :repo_directory
|
attr_reader :repo_directory
|
||||||
|
|
||||||
def initialize(repo_directory)
|
def initialize(repo_directory)
|
||||||
@repo_directory = repo_directory
|
@repo_directory = Pathname.new(repo_directory).expand_path
|
||||||
|
|
||||||
FileUtils.mkdir_p(repo_directory) unless Dir.exist?(repo_directory)
|
FileUtils.mkdir_p(repo_directory.to_s) unless Dir.exist?(repo_directory.to_s)
|
||||||
|
|
||||||
raise "#{repo_directory} is not writable" unless Pathname.new(repo_directory).writable?
|
raise "#{repo_directory} is not writable" unless repo_directory.writable?
|
||||||
|
|
||||||
delete_old_files
|
delete_old_files
|
||||||
end
|
end
|
||||||
@@ -41,7 +41,7 @@ module WPScan
|
|||||||
|
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
def last_update_file
|
def last_update_file
|
||||||
@last_update_file ||= File.join(repo_directory, '.last_update')
|
@last_update_file ||= repo_directory.join('.last_update').to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Boolean ]
|
# @return [ Boolean ]
|
||||||
@@ -54,7 +54,7 @@ module WPScan
|
|||||||
# @return [ Boolean ]
|
# @return [ Boolean ]
|
||||||
def missing_files?
|
def missing_files?
|
||||||
FILES.each do |file|
|
FILES.each do |file|
|
||||||
return true unless File.exist?(File.join(repo_directory, file))
|
return true unless File.exist?(repo_directory.join(file))
|
||||||
end
|
end
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
@@ -85,16 +85,18 @@ module WPScan
|
|||||||
res.body.chomp
|
res.body.chomp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [ String ]
|
||||||
def local_file_path(filename)
|
def local_file_path(filename)
|
||||||
File.join(repo_directory, filename.to_s)
|
repo_directory.join(filename.to_s).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def local_file_checksum(filename)
|
def local_file_checksum(filename)
|
||||||
Digest::SHA512.file(local_file_path(filename)).hexdigest
|
Digest::SHA512.file(local_file_path(filename)).hexdigest
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @return [ String ]
|
||||||
def backup_file_path(filename)
|
def backup_file_path(filename)
|
||||||
File.join(repo_directory, "#{filename}.back")
|
repo_directory.join("#{filename}.back").to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_backup(filename)
|
def create_backup(filename)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module WPScan
|
|||||||
class Version < WpItem
|
class Version < WpItem
|
||||||
# @return [ String ]
|
# @return [ String ]
|
||||||
def self.db_file
|
def self.db_file
|
||||||
@db_file ||= File.join(DB_DIR, 'wordpresses.json')
|
@db_file ||= DB_DIR.join('wordpresses.json').to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ end
|
|||||||
require_relative 'errors/http'
|
require_relative 'errors/http'
|
||||||
require_relative 'errors/update'
|
require_relative 'errors/update'
|
||||||
require_relative 'errors/wordpress'
|
require_relative 'errors/wordpress'
|
||||||
|
require_relative 'errors/xmlrpc'
|
||||||
|
|||||||
8
lib/wpscan/errors/xmlrpc.rb
Normal file
8
lib/wpscan/errors/xmlrpc.rb
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module WPScan
|
||||||
|
# XML-RPC Not Detected
|
||||||
|
class XMLRPCNotDetected < Error
|
||||||
|
def to_s
|
||||||
|
'The XML-RPC Interface was not detected.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -18,10 +18,10 @@ module WPScan
|
|||||||
alias registration_enabled? registration_enabled
|
alias registration_enabled? registration_enabled
|
||||||
alias mu_plugins? mu_plugins
|
alias mu_plugins? mu_plugins
|
||||||
|
|
||||||
|
# @param [ Symbol ] detection_mode
|
||||||
|
#
|
||||||
# @return [ Boolean ]
|
# @return [ Boolean ]
|
||||||
def wordpress?
|
def wordpress?(detection_mode)
|
||||||
# res = Browser.get(url)
|
|
||||||
|
|
||||||
in_scope_urls(homepage_res) do |url|
|
in_scope_urls(homepage_res) do |url|
|
||||||
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
|
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
|
||||||
end
|
end
|
||||||
@@ -32,6 +32,14 @@ module WPScan
|
|||||||
|
|
||||||
return true unless comments_from_page(/wordpress/i, homepage_res).empty?
|
return true unless comments_from_page(/wordpress/i, homepage_res).empty?
|
||||||
|
|
||||||
|
if %i[mixed aggressive].include?(detection_mode)
|
||||||
|
%w[wp-admin/install.php wp-login.php].each do |path|
|
||||||
|
in_scope_urls(Browser.get_and_follow_location(url(path))).each do |url|
|
||||||
|
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Version
|
# Version
|
||||||
module WPScan
|
module WPScan
|
||||||
VERSION = '3.4.2'.freeze
|
VERSION = '3.4.5'.freeze
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Controller::Aliases do
|
describe WPScan::Controller::Aliases do
|
||||||
subject(:controller) { described_class.new }
|
subject(:controller) { described_class.new }
|
||||||
let(:target_url) { 'http://ex.lo/' }
|
let(:target_url) { 'http://ex.lo/' }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Controller::Core do
|
describe WPScan::Controller::Core do
|
||||||
subject(:core) { described_class.new }
|
subject(:core) { described_class.new }
|
||||||
let(:target_url) { 'http://ex.lo/' }
|
let(:target_url) { 'http://ex.lo/' }
|
||||||
@@ -167,7 +165,7 @@ describe WPScan::Controller::Core do
|
|||||||
|
|
||||||
before do
|
before do
|
||||||
expect(core).to receive(:load_server_module)
|
expect(core).to receive(:load_server_module)
|
||||||
expect(core.target).to receive(:wordpress?).and_return(true)
|
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls the formatter when started and finished to update the db' do
|
it 'calls the formatter when started and finished to update the db' do
|
||||||
@@ -210,7 +208,7 @@ describe WPScan::Controller::Core do
|
|||||||
|
|
||||||
context 'when wordpress' do
|
context 'when wordpress' do
|
||||||
it 'does not raise an error' do
|
it 'does not raise an error' do
|
||||||
expect(core.target).to receive(:wordpress?).and_return(true)
|
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
|
||||||
|
|
||||||
expect { core.before_scan }.to_not raise_error
|
expect { core.before_scan }.to_not raise_error
|
||||||
end
|
end
|
||||||
@@ -218,7 +216,7 @@ describe WPScan::Controller::Core do
|
|||||||
|
|
||||||
context 'when not wordpress' do
|
context 'when not wordpress' do
|
||||||
it 'raises an error' do
|
it 'raises an error' do
|
||||||
expect(core.target).to receive(:wordpress?).and_return(false)
|
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
|
||||||
|
|
||||||
expect { core.before_scan }.to raise_error(WPScan::NotWordPressError)
|
expect { core.before_scan }.to raise_error(WPScan::NotWordPressError)
|
||||||
end
|
end
|
||||||
@@ -239,7 +237,7 @@ describe WPScan::Controller::Core do
|
|||||||
context 'when wordpress' do
|
context 'when wordpress' do
|
||||||
before do
|
before do
|
||||||
expect(core).to receive(:load_server_module)
|
expect(core).to receive(:load_server_module)
|
||||||
expect(core.target).to receive(:wordpress?).and_return(true)
|
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not raise any error' do
|
it 'does not raise any error' do
|
||||||
@@ -250,7 +248,7 @@ describe WPScan::Controller::Core do
|
|||||||
context 'when not wordpress' do
|
context 'when not wordpress' do
|
||||||
before do
|
before do
|
||||||
expect(core).to receive(:load_server_module)
|
expect(core).to receive(:load_server_module)
|
||||||
expect(core.target).to receive(:wordpress?).and_return(false)
|
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when no --force' do
|
context 'when no --force' do
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Controller::CustomDirectories do
|
describe WPScan::Controller::CustomDirectories do
|
||||||
subject(:controller) { described_class.new }
|
subject(:controller) { described_class.new }
|
||||||
let(:target_url) { 'http://ex.lo/' }
|
let(:target_url) { 'http://ex.lo/' }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Controller::Enumeration do
|
describe WPScan::Controller::Enumeration do
|
||||||
subject(:controller) { described_class.new }
|
subject(:controller) { described_class.new }
|
||||||
let(:target_url) { 'http://wp.lab/' }
|
let(:target_url) { 'http://wp.lab/' }
|
||||||
@@ -16,10 +14,11 @@ describe WPScan::Controller::Enumeration do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#enum_message' do
|
describe '#enum_message' do
|
||||||
after { expect(controller.enum_message(type)).to eql @expected }
|
after { expect(controller.enum_message(type, detection_mode)).to eql @expected }
|
||||||
|
|
||||||
context 'when type argument is incorrect' do
|
context 'when type argument is incorrect' do
|
||||||
let(:type) { 'spec' }
|
let(:type) { 'spec' }
|
||||||
|
let(:detection_mode) { :mixed }
|
||||||
|
|
||||||
it 'returns nil' do
|
it 'returns nil' do
|
||||||
@expected = nil
|
@expected = nil
|
||||||
@@ -29,28 +28,31 @@ describe WPScan::Controller::Enumeration do
|
|||||||
%w[plugins themes].each do |t|
|
%w[plugins themes].each do |t|
|
||||||
context "type = #{t}" do
|
context "type = #{t}" do
|
||||||
let(:type) { t }
|
let(:type) { t }
|
||||||
|
let(:detection_mode) { :mixed }
|
||||||
|
|
||||||
context 'when vulnerable' do
|
context 'when vulnerable' do
|
||||||
let(:cli_args) { "#{super()} -e v#{type[0]}" }
|
let(:cli_args) { "#{super()} -e v#{type[0]}" }
|
||||||
|
|
||||||
it 'returns the expected string' do
|
it 'returns the expected string' do
|
||||||
@expected = "Enumerating Vulnerable #{type.capitalize}"
|
@expected = "Enumerating Vulnerable #{type.capitalize} (via Passive and Aggressive Methods)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when all' do
|
context 'when all' do
|
||||||
let(:cli_args) { "#{super()} -e a#{type[0]}" }
|
let(:cli_args) { "#{super()} -e a#{type[0]}" }
|
||||||
|
let(:detection_mode) { :passive }
|
||||||
|
|
||||||
it 'returns the expected string' do
|
it 'returns the expected string' do
|
||||||
@expected = "Enumerating All #{type.capitalize}"
|
@expected = "Enumerating All #{type.capitalize} (via Passive Methods)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when most popular' do
|
context 'when most popular' do
|
||||||
let(:cli_args) { "#{super()} -e #{type[0]}" }
|
let(:cli_args) { "#{super()} -e #{type[0]}" }
|
||||||
|
let(:detection_mode) { :aggressive }
|
||||||
|
|
||||||
it 'returns the expected string' do
|
it 'returns the expected string' do
|
||||||
@expected = "Enumerating Most Popular #{type.capitalize}"
|
@expected = "Enumerating Most Popular #{type.capitalize} (via Aggressive Methods)"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Controller::PasswordAttack do
|
describe WPScan::Controller::PasswordAttack do
|
||||||
subject(:controller) { described_class.new }
|
subject(:controller) { described_class.new }
|
||||||
let(:target_url) { 'http://ex.lo/' }
|
let(:target_url) { 'http://ex.lo/' }
|
||||||
@@ -68,6 +66,29 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when xmlrpc' do
|
context 'when xmlrpc' do
|
||||||
|
context 'when xmlrpc not detected on target' do
|
||||||
|
before do
|
||||||
|
expect(controller.target).to receive(:xmlrpc).and_return(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when single xmlrpc' do
|
||||||
|
let(:attack) { 'xmlrpc' }
|
||||||
|
|
||||||
|
it 'raises an error' do
|
||||||
|
expect { controller.attacker }.to raise_error(WPScan::XMLRPCNotDetected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when xmlrpc-multicall' do
|
||||||
|
let(:attack) { 'xmlrpc-multicall' }
|
||||||
|
|
||||||
|
it 'raises an error' do
|
||||||
|
expect { controller.attacker }.to raise_error(WPScan::XMLRPCNotDetected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when xmlrpc detected on target' do
|
||||||
before do
|
before do
|
||||||
expect(controller.target).to receive(:xmlrpc).and_return(WPScan::XMLRPC.new("#{target_url}/xmlrpc.php"))
|
expect(controller.target).to receive(:xmlrpc).and_return(WPScan::XMLRPC.new("#{target_url}/xmlrpc.php"))
|
||||||
end
|
end
|
||||||
@@ -91,6 +112,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when automatic detection' do
|
context 'when automatic detection' do
|
||||||
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) }
|
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
def it_calls_the_formatter_with_the_correct_parameter(version)
|
def it_calls_the_formatter_with_the_correct_parameter(version)
|
||||||
it 'calls the formatter with the correct parameter' do
|
it 'calls the formatter with the correct parameter' do
|
||||||
expect(controller.formatter).to receive(:output)
|
expect(controller.formatter).to receive(:output)
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::ConfigBackups::KnownFilenames do
|
describe WPScan::Finders::ConfigBackups::KnownFilenames do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'config_backups') }
|
let(:fixtures) { FINDERS_FIXTURES.join('config_backups') }
|
||||||
let(:opts) { { list: File.join(WPScan::DB_DIR, 'config_backups.txt') } }
|
let(:opts) { { list: WPScan::DB_DIR.join('config_backups.txt').to_s } }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
before do
|
before do
|
||||||
@@ -25,7 +23,7 @@ describe WPScan::Finders::ConfigBackups::KnownFilenames do
|
|||||||
|
|
||||||
context 'when some files exist' do
|
context 'when some files exist' do
|
||||||
let(:files) { ['%23wp-config.php%23', 'wp-config.bak'] }
|
let(:files) { ['%23wp-config.php%23', 'wp-config.bak'] }
|
||||||
let(:config_backup) { File.read(File.join(fixtures, 'wp-config.php')) }
|
let(:config_backup) { File.read(fixtures.join('wp-config.php')) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::ConfigBackups::Base do
|
describe WPScan::Finders::ConfigBackups::Base do
|
||||||
subject(:config_backups) { described_class.new(target) }
|
subject(:config_backups) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::DbExports::KnownLocations do
|
describe WPScan::Finders::DbExports::KnownLocations do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/aa/' }
|
let(:url) { 'http://ex.lo/aa/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'db_exports') }
|
let(:fixtures) { FINDERS_FIXTURES.join('db_exports') }
|
||||||
let(:opts) { { list: File.join(WPScan::DB_DIR, 'db_exports.txt') } }
|
let(:opts) { { list: WPScan::DB_DIR.join('db_exports.txt').to_s } }
|
||||||
|
|
||||||
describe '#potential_urls' do
|
describe '#potential_urls' do
|
||||||
before do
|
before do
|
||||||
@@ -42,7 +40,7 @@ describe WPScan::Finders::DbExports::KnownLocations do
|
|||||||
|
|
||||||
context 'when some files exist' do
|
context 'when some files exist' do
|
||||||
let(:files) { %w[ex.sql backups/db_backup.sql] }
|
let(:files) { %w[ex.sql backups/db_backup.sql] }
|
||||||
let(:db_export) { File.read(File.join(fixtures, 'dump.sql')) }
|
let(:db_export) { File.read(fixtures.join('dump.sql')) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::DbExports::Base do
|
describe WPScan::Finders::DbExports::Base do
|
||||||
subject(:db_exports) { described_class.new(target) }
|
subject(:db_exports) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::BackupDB do
|
describe WPScan::Finders::InterestingFindings::BackupDB do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'backup_db') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'backup_db') }
|
||||||
let(:wp_content) { 'wp-content' }
|
let(:wp_content) { 'wp-content' }
|
||||||
let(:dir_url) { target.url("#{wp_content}/backup-db/") }
|
let(:dir_url) { target.url("#{wp_content}/backup-db/") }
|
||||||
|
|
||||||
@@ -53,7 +51,7 @@ describe WPScan::Finders::InterestingFindings::BackupDB do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when directory listing enabled' do
|
context 'when directory listing enabled' do
|
||||||
let(:body) { File.read(File.join(fixtures, 'dir_listing.html')) }
|
let(:body) { File.read(fixtures.join('dir_listing.html')) }
|
||||||
|
|
||||||
it 'returns the expected interesting_findings attribute' do
|
it 'returns the expected interesting_findings attribute' do
|
||||||
@expected_entries = %w[sqldump.sql test.txt]
|
@expected_entries = %w[sqldump.sql test.txt]
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::DebugLog do
|
describe WPScan::Finders::InterestingFindings::DebugLog do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'debug_log') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'debug_log') }
|
||||||
let(:wp_content) { 'wp-content' }
|
let(:wp_content) { 'wp-content' }
|
||||||
let(:log_url) { target.url("#{wp_content}/debug.log") }
|
let(:log_url) { target.url("#{wp_content}/debug.log") }
|
||||||
|
|
||||||
@@ -20,7 +18,7 @@ describe WPScan::Finders::InterestingFindings::DebugLog do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when a log file' do
|
context 'when a log file' do
|
||||||
let(:body) { File.read(File.join(fixtures, 'debug.log')) }
|
let(:body) { File.read(fixtures.join('debug.log')) }
|
||||||
|
|
||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
expect(finder.aggressive).to eql WPScan::DebugLog.new(
|
expect(finder.aggressive).to eql WPScan::DebugLog.new(
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
|
describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'duplicator_installer_log') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'duplicator_installer_log') }
|
||||||
let(:filename) { 'installer-log.txt' }
|
let(:filename) { 'installer-log.txt' }
|
||||||
let(:log_url) { target.url(filename) }
|
let(:log_url) { target.url(filename) }
|
||||||
|
|
||||||
@@ -21,7 +19,7 @@ describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when the body matches' do
|
context 'when the body matches' do
|
||||||
let(:body) { File.read(File.join(fixtures, filename)) }
|
let(:body) { File.read(fixtures.join(filename)) }
|
||||||
|
|
||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
expect(finder.aggressive).to eql WPScan::DuplicatorInstallerLog.new(
|
expect(finder.aggressive).to eql WPScan::DuplicatorInstallerLog.new(
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::EmergencyPwdResetScript do
|
describe WPScan::Finders::InterestingFindings::EmergencyPwdResetScript do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'emergency_pwd_reset_script') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'emergency_pwd_reset_script') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::FullPathDisclosure do
|
describe WPScan::Finders::InterestingFindings::FullPathDisclosure do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'fpd') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'fpd') }
|
||||||
let(:file_url) { target.url('wp-includes/rss-functions.php') }
|
let(:file_url) { target.url('wp-includes/rss-functions.php') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
@@ -20,7 +18,7 @@ describe WPScan::Finders::InterestingFindings::FullPathDisclosure do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when a log file' do
|
context 'when a log file' do
|
||||||
let(:body) { File.read(File.join(fixtures, 'rss_functions.php')) }
|
let(:body) { File.read(fixtures.join('rss_functions.php')) }
|
||||||
|
|
||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
found = finder.aggressive
|
found = finder.aggressive
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::MuPlugins do
|
describe WPScan::Finders::InterestingFindings::MuPlugins do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'mu_plugins') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'mu_plugins') }
|
||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::Multisite do
|
describe WPScan::Finders::InterestingFindings::Multisite do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'multisite') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'multisite') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::Readme do
|
describe WPScan::Finders::InterestingFindings::Readme do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'readme') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'readme') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
before do
|
before do
|
||||||
@@ -22,7 +20,7 @@ describe WPScan::Finders::InterestingFindings::Readme do
|
|||||||
# TODO: case when multiple files are present ? (should return only the first one found)
|
# TODO: case when multiple files are present ? (should return only the first one found)
|
||||||
context 'when a file exists' do
|
context 'when a file exists' do
|
||||||
let(:file) { finder.potential_files.sample }
|
let(:file) { finder.potential_files.sample }
|
||||||
let(:readme) { File.read(File.join(fixtures, 'readme-3.9.2.html')) }
|
let(:readme) { File.read(fixtures.join('readme-3.9.2.html')) }
|
||||||
|
|
||||||
before { stub_request(:get, target.url(file)).to_return(body: readme) }
|
before { stub_request(:get, target.url(file)).to_return(body: readme) }
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::Registration do
|
describe WPScan::Finders::InterestingFindings::Registration do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'registration') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'registration') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::TmmDbMigrate do
|
describe WPScan::Finders::InterestingFindings::TmmDbMigrate do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'tmm_db_migrate') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'tmm_db_migrate') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::UploadDirectoryListing do
|
describe WPScan::Finders::InterestingFindings::UploadDirectoryListing do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'upload_directory_listing') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'upload_directory_listing') }
|
||||||
let(:wp_content) { 'wp-content' }
|
let(:wp_content) { 'wp-content' }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'upload_sql_dump') }
|
let(:fixtures) { FINDERS_FIXTURES.join('interesting_findings', 'upload_sql_dump') }
|
||||||
let(:wp_content) { 'wp-content' }
|
let(:wp_content) { 'wp-content' }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
@@ -23,7 +21,7 @@ describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
|||||||
context 'when a 200' do
|
context 'when a 200' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, finder.dump_url)
|
stub_request(:get, finder.dump_url)
|
||||||
.to_return(status: 200, body: File.read(File.join(fixtures, fixture)))
|
.to_return(status: 200, body: File.read(fixtures.join(fixture)))
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the body does not match a SQL dump' do
|
context 'when the body does not match a SQL dump' do
|
||||||
|
|||||||
30
spec/app/finders/interesting_findings/wp_cron_spec.rb
Normal file
30
spec/app/finders/interesting_findings/wp_cron_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
describe WPScan::Finders::InterestingFindings::WPCron do
|
||||||
|
subject(:finder) { described_class.new(target) }
|
||||||
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
let(:url) { 'http://ex.lo/' }
|
||||||
|
let(:wp_content) { 'wp-content' }
|
||||||
|
|
||||||
|
before { expect(target).to receive(:sub_dir).at_least(1).and_return(false) }
|
||||||
|
|
||||||
|
describe '#aggressive' do
|
||||||
|
before { stub_request(:get, finder.wp_cron_url).to_return(status: status) }
|
||||||
|
|
||||||
|
context 'when 200' do
|
||||||
|
let(:status) { 200 }
|
||||||
|
|
||||||
|
it 'returns the InterestingFinding' do
|
||||||
|
expect(finder.aggressive).to eql WPScan::WPCron.new(
|
||||||
|
finder.wp_cron_url,
|
||||||
|
confidence: 60,
|
||||||
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'otherwise' do
|
||||||
|
let(:status) { 403 }
|
||||||
|
|
||||||
|
its(:aggressive) { should be_nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::InterestingFindings::Base do
|
describe WPScan::Finders::InterestingFindings::Base do
|
||||||
subject(:files) { described_class.new(target) }
|
subject(:files) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::MainTheme::CssStyle do
|
describe WPScan::Finders::MainTheme::CssStyle do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'css_style') }
|
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'css_style') }
|
||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
after do
|
after do
|
||||||
stub_request(:get, url).to_return(body: File.read(File.join(fixtures, fixture)))
|
stub_request(:get, url).to_return(body: File.read(fixtures.join(fixture)))
|
||||||
expect(finder.passive).to eql @expected
|
expect(finder.passive).to eql @expected
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::MainTheme::UrlsInHomepage do
|
describe WPScan::Finders::MainTheme::UrlsInHomepage do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'urls_in_homepage') }
|
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'urls_in_homepage') }
|
||||||
|
|
||||||
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
||||||
let(:type) { 'themes' }
|
let(:type) { 'themes' }
|
||||||
@@ -17,7 +15,7 @@ describe WPScan::Finders::MainTheme::UrlsInHomepage do
|
|||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /.*.css/)
|
stub_request(:get, /.*.css/)
|
||||||
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, 'found.html')))
|
stub_request(:get, target.url).to_return(body: File.read(fixtures.join('found.html')))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the expected Themes' do
|
it 'returns the expected Themes' do
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::MainTheme::WooFrameworkMetaGenerator do
|
describe WPScan::Finders::MainTheme::WooFrameworkMetaGenerator do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'woo_framework_meta_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('main_theme', 'woo_framework_meta_generator') }
|
||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
after do
|
after do
|
||||||
stub_request(:get, url).to_return(body: File.read(File.join(fixtures, @file)))
|
stub_request(:get, url).to_return(body: File.read(fixtures.join(@file)))
|
||||||
|
|
||||||
expect(finder.passive).to eql @expected
|
expect(finder.passive).to eql @expected
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::MainTheme::Base do
|
describe WPScan::Finders::MainTheme::Base do
|
||||||
subject(:main_theme) { described_class.new(target) }
|
subject(:main_theme) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Medias::AttachmentBruteForcing do
|
describe WPScan::Finders::Medias::AttachmentBruteForcing do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'medias', 'attachment_brute_forcing') }
|
let(:fixtures) { FINDERS_FIXTURES.join('medias', 'attachment_brute_forcing') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Medias::Base do
|
describe WPScan::Finders::Medias::Base do
|
||||||
subject(:media) { described_class.new(target) }
|
subject(:media) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::PluginVersion::Readme do
|
describe WPScan::Finders::PluginVersion::Readme do
|
||||||
subject(:finder) { described_class.new(plugin) }
|
subject(:finder) { described_class.new(plugin) }
|
||||||
let(:plugin) { WPScan::Plugin.new('spec', target) }
|
let(:plugin) { WPScan::Plugin.new('spec', target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugin_version', 'readme') }
|
let(:fixtures) { FINDERS_FIXTURES.join('plugin_version', 'readme') }
|
||||||
|
|
||||||
def version(number, found_by, confidence)
|
def version(number, found_by, confidence)
|
||||||
WPScan::Version.new(
|
WPScan::Version.new(
|
||||||
@@ -28,7 +26,7 @@ describe WPScan::Finders::PluginVersion::Readme do
|
|||||||
|
|
||||||
after do
|
after do
|
||||||
stub_request(:get, /.*/).to_return(status: 404)
|
stub_request(:get, /.*/).to_return(status: 404)
|
||||||
stub_request(:get, readme_url).to_return(body: File.read(File.join(fixtures, @file)))
|
stub_request(:get, readme_url).to_return(body: File.read(fixtures.join(@file)))
|
||||||
|
|
||||||
expect(finder.aggressive).to eql @expected
|
expect(finder.aggressive).to eql @expected
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
|
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
|
||||||
# constants not being intilialized. This is due to the Dynamic Finders.
|
# constants not being intilialized. This is due to the Dynamic Finders.
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::BodyPattern do
|
describe WPScan::Finders::Plugins::BodyPattern do
|
||||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Plugin }
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::Comment do
|
describe WPScan::Finders::Plugins::Comment do
|
||||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Plugin }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::ConfigParser do
|
describe WPScan::Finders::Plugins::ConfigParser do
|
||||||
xit
|
xit
|
||||||
|
|
||||||
@@ -7,7 +5,7 @@ describe WPScan::Finders::Plugins::ConfigParser do
|
|||||||
# subject(:finder) { described_class.new(target) }
|
# subject(:finder) { described_class.new(target) }
|
||||||
# let(:target) { WPScan::Target.new(url) }
|
# let(:target) { WPScan::Target.new(url) }
|
||||||
# let(:url) { 'http://wp.lab/' }
|
# let(:url) { 'http://wp.lab/' }
|
||||||
# let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
# let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
#
|
#
|
||||||
# let(:expected_all) { df_expected_all['plugins'] }
|
# let(:expected_all) { df_expected_all['plugins'] }
|
||||||
# let(:item_class) { WPScan::Plugin }
|
# let(:item_class) { WPScan::Plugin }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::HeaderPattern do
|
describe WPScan::Finders::Plugins::HeaderPattern do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
def plugin(slug)
|
def plugin(slug)
|
||||||
WPScan::Plugin.new(slug, target)
|
WPScan::Plugin.new(slug, target)
|
||||||
@@ -31,7 +29,7 @@ describe WPScan::Finders::Plugins::HeaderPattern do
|
|||||||
context 'when headers' do
|
context 'when headers' do
|
||||||
before { expect(target).to receive(:content_dir).and_return('wp-content') }
|
before { expect(target).to receive(:content_dir).and_return('wp-content') }
|
||||||
|
|
||||||
let(:headers) { JSON.parse(File.read(File.join(fixtures, 'header_pattern_passive_all.html'))) }
|
let(:headers) { JSON.parse(File.read(fixtures.join('header_pattern_passive_all.html'))) }
|
||||||
|
|
||||||
it 'returns the expected plugins' do
|
it 'returns the expected plugins' do
|
||||||
@expected = []
|
@expected = []
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::JavascriptVar do
|
describe WPScan::Finders::Plugins::JavascriptVar do
|
||||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Plugin }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::KnownLocations do
|
describe WPScan::Finders::Plugins::KnownLocations do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugins', 'known_locations') }
|
let(:fixtures) { FINDERS_FIXTURES.join('plugins', 'known_locations') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::QueryParameter do
|
describe WPScan::Finders::Plugins::QueryParameter do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
its(:passive) { should be nil }
|
its(:passive) { should be nil }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::UrlsInHomepage do
|
describe WPScan::Finders::Plugins::UrlsInHomepage do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugins', 'urls_in_homepage') }
|
let(:fixtures) { FINDERS_FIXTURES.join('plugins', 'urls_in_homepage') }
|
||||||
|
|
||||||
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
||||||
let(:type) { 'plugins' }
|
let(:type) { 'plugins' }
|
||||||
@@ -17,7 +15,7 @@ describe WPScan::Finders::Plugins::UrlsInHomepage do
|
|||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, finder.target.url)
|
stub_request(:get, finder.target.url)
|
||||||
.to_return(body: File.read(File.join(fixtures, 'found.html')))
|
.to_return(body: File.read(fixtures.join('found.html')))
|
||||||
|
|
||||||
expect(finder.target).to receive(:content_dir).at_least(1).and_return('wp-content')
|
expect(finder.target).to receive(:content_dir).at_least(1).and_return('wp-content')
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::Xpath do
|
describe WPScan::Finders::Plugins::Xpath do
|
||||||
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Plugin }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Plugins::Base do
|
describe WPScan::Finders::Plugins::Base do
|
||||||
subject(:plugins) { described_class.new(target) }
|
subject(:plugins) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::ThemeVersion::Style do
|
describe WPScan::Finders::ThemeVersion::Style do
|
||||||
subject(:finder) { described_class.new(theme) }
|
subject(:finder) { described_class.new(theme) }
|
||||||
let(:theme) { WPScan::Theme.new('spec', target) }
|
let(:theme) { WPScan::Theme.new('spec', target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'theme_version', 'style') }
|
let(:fixtures) { FINDERS_FIXTURES.join('theme_version', 'style') }
|
||||||
|
|
||||||
before :all do
|
before :all do
|
||||||
Typhoeus::Config.cache = WPScan::Cache::Typhoeus.new(File.join(SPECS, 'cache'))
|
Typhoeus::Config.cache = WPScan::Cache::Typhoeus.new(SPECS.join('cache'))
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
@@ -79,7 +77,7 @@ describe WPScan::Finders::ThemeVersion::Style do
|
|||||||
'no_version' => nil
|
'no_version' => nil
|
||||||
}.each do |file, expected_version|
|
}.each do |file, expected_version|
|
||||||
context "when #{file}" do
|
context "when #{file}" do
|
||||||
let(:style_body) { File.new(File.join(fixtures, "#{file}.css")) }
|
let(:style_body) { File.new(fixtures.join("#{file}.css")) }
|
||||||
|
|
||||||
it 'returns the expected version' do
|
it 'returns the expected version' do
|
||||||
expected = if expected_version
|
expected = if expected_version
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
||||||
subject(:finder) { described_class.new(theme) }
|
subject(:finder) { described_class.new(theme) }
|
||||||
let(:theme) { WPScan::Theme.new(slug, target) }
|
let(:theme) { WPScan::Theme.new(slug, target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'theme_version', 'woo_framework_meta_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('theme_version', 'woo_framework_meta_generator') }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
expect(target).to receive(:content_dir).and_return('wp-content')
|
expect(target).to receive(:content_dir).and_return('wp-content')
|
||||||
@@ -13,7 +11,7 @@ describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
|||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
after do
|
after do
|
||||||
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, 'editorial-1.3.5.html')))
|
stub_request(:get, target.url).to_return(body: File.read(fixtures.join('editorial-1.3.5.html')))
|
||||||
|
|
||||||
expect(finder.passive).to eql @expected
|
expect(finder.passive).to eql @expected
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::ThemeVersion::Base do
|
describe WPScan::Finders::ThemeVersion::Base do
|
||||||
subject(:theme_version) { described_class.new(theme) }
|
subject(:theme_version) { described_class.new(theme) }
|
||||||
let(:theme) { WPScan::Plugin.new(slug, target) }
|
let(:theme) { WPScan::Plugin.new(slug, target) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Themes::KnownLocations do
|
describe WPScan::Finders::Themes::KnownLocations do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'themes', 'known_locations') }
|
let(:fixtures) { FINDERS_FIXTURES.join('themes', 'known_locations') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Themes::UrlsInHomepage do
|
describe WPScan::Finders::Themes::UrlsInHomepage do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'themes', 'urls_in_homepage') }
|
let(:fixtures) { FINDERS_FIXTURES.join('themes', 'urls_in_homepage') }
|
||||||
|
|
||||||
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
|
||||||
let(:type) { 'themes' }
|
let(:type) { 'themes' }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Themes::Base do
|
describe WPScan::Finders::Themes::Base do
|
||||||
subject(:themes) { described_class.new(target) }
|
subject(:themes) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::TimthumbVersion::BadRequest do
|
describe WPScan::Finders::TimthumbVersion::BadRequest do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Timthumb.new(url) }
|
let(:target) { WPScan::Timthumb.new(url) }
|
||||||
let(:url) { 'http://ex.lo/timthumb.php' }
|
let(:url) { 'http://ex.lo/timthumb.php' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'timthumb_version', 'bad_request') }
|
let(:fixtures) { FINDERS_FIXTURES.join('timthumb_version', 'bad_request') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
before { stub_request(:get, url).to_return(body: File.read(File.join(fixtures, file))) }
|
before { stub_request(:get, url).to_return(body: File.read(fixtures.join(file))) }
|
||||||
after { expect(finder.aggressive).to eql @expected }
|
after { expect(finder.aggressive).to eql @expected }
|
||||||
|
|
||||||
context 'when no version' do
|
context 'when no version' do
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::TimthumbVersion::Base do
|
describe WPScan::Finders::TimthumbVersion::Base do
|
||||||
subject(:timthumb_version) { described_class.new(target) }
|
subject(:timthumb_version) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Timthumb.new(url) }
|
let(:target) { WPScan::Timthumb.new(url) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Timthumbs::KnownLocations do
|
describe WPScan::Finders::Timthumbs::KnownLocations do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'timthumbs', 'known_locations') }
|
let(:fixtures) { FINDERS_FIXTURES.join('timthumbs', 'known_locations') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Timthumbs::Base do
|
describe WPScan::Finders::Timthumbs::Base do
|
||||||
subject(:timthumb) { described_class.new(target) }
|
subject(:timthumb) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::AuthorIdBruteForcing do
|
describe WPScan::Finders::Users::AuthorIdBruteForcing do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'author_id_brute_forcing') }
|
let(:fixtures) { FINDERS_FIXTURES.join('users', 'author_id_brute_forcing') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
@@ -26,7 +24,7 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
|
|||||||
'2.9.2', '2.9.2-permalink'
|
'2.9.2', '2.9.2-permalink'
|
||||||
].each do |file|
|
].each do |file|
|
||||||
it "returns 'admin' from #{file}.html" do
|
it "returns 'admin' from #{file}.html" do
|
||||||
body = File.read(File.join(fixtures, "#{file}.html"))
|
body = File.read(fixtures.join("#{file}.html"))
|
||||||
res = Typhoeus::Response.new(body: body)
|
res = Typhoeus::Response.new(body: body)
|
||||||
|
|
||||||
expect(finder.username_from_response(res)).to eql 'admin'
|
expect(finder.username_from_response(res)).to eql 'admin'
|
||||||
@@ -42,7 +40,7 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
|
|||||||
'2.9.2', '2.9.2-permalink'
|
'2.9.2', '2.9.2-permalink'
|
||||||
].each do |file|
|
].each do |file|
|
||||||
it "returns 'admin display_name' from #{file}.html" do
|
it "returns 'admin display_name' from #{file}.html" do
|
||||||
body = File.read(File.join(fixtures, "#{file}.html"))
|
body = File.read(fixtures.join("#{file}.html"))
|
||||||
|
|
||||||
expect(finder.display_name_from_body(body)).to eql 'admin display_name'
|
expect(finder.display_name_from_body(body)).to eql 'admin display_name'
|
||||||
end
|
end
|
||||||
@@ -52,7 +50,7 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
|
|||||||
context 'when no display_name' do
|
context 'when no display_name' do
|
||||||
['4.1.1', '3.0', '2.9.2'].each do |file|
|
['4.1.1', '3.0', '2.9.2'].each do |file|
|
||||||
it "returns nil for #{file}-empty.html" do
|
it "returns nil for #{file}-empty.html" do
|
||||||
body = File.read(File.join(fixtures, "#{file}-empty.html"))
|
body = File.read(fixtures.join("#{file}-empty.html"))
|
||||||
|
|
||||||
expect(finder.display_name_from_body(body)).to eql nil
|
expect(finder.display_name_from_body(body)).to eql nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::AuthorPosts do
|
describe WPScan::Finders::Users::AuthorPosts do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'author_posts') }
|
let(:fixtures) { FINDERS_FIXTURES.join('users', 'author_posts') }
|
||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
xit
|
xit
|
||||||
@@ -12,7 +10,7 @@ describe WPScan::Finders::Users::AuthorPosts do
|
|||||||
|
|
||||||
describe '#potential_usernames' do
|
describe '#potential_usernames' do
|
||||||
it 'returns the expected usernames' do
|
it 'returns the expected usernames' do
|
||||||
res = Typhoeus::Response.new(body: File.read(File.join(fixtures, 'potential_usernames.html')))
|
res = Typhoeus::Response.new(body: File.read(fixtures.join('potential_usernames.html')))
|
||||||
|
|
||||||
results = finder.potential_usernames(res)
|
results = finder.potential_usernames(res)
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::LoginErrorMessages do
|
describe WPScan::Finders::Users::LoginErrorMessages do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'login_error_messages') }
|
let(:fixtures) { FINDERS_FIXTURES.join('users', 'login_error_messages') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
xit
|
xit
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::OembedApi do
|
describe WPScan::Finders::Users::OembedApi do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'oembed_api') }
|
let(:fixtures) { FINDERS_FIXTURES.join('users', 'oembed_api') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
before do
|
before do
|
||||||
@@ -20,14 +18,14 @@ describe WPScan::Finders::Users::OembedApi do
|
|||||||
|
|
||||||
context 'when a JSON response' do
|
context 'when a JSON response' do
|
||||||
context 'when 404' do
|
context 'when 404' do
|
||||||
let(:body) { File.read(File.join(fixtures, '404.json')) }
|
let(:body) { File.read(fixtures.join('404.json')) }
|
||||||
|
|
||||||
its(:aggressive) { should eql([]) }
|
its(:aggressive) { should eql([]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when 200' do
|
context 'when 200' do
|
||||||
context 'when author_url present' do
|
context 'when author_url present' do
|
||||||
let(:body) { File.read(File.join(fixtures, '200_author_url.json')) }
|
let(:body) { File.read(fixtures.join('200_author_url.json')) }
|
||||||
|
|
||||||
it 'returns the expected array of users' do
|
it 'returns the expected array of users' do
|
||||||
users = finder.aggressive
|
users = finder.aggressive
|
||||||
@@ -44,7 +42,7 @@ describe WPScan::Finders::Users::OembedApi do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when author_url not present but author_name' do
|
context 'when author_url not present but author_name' do
|
||||||
let(:body) { File.read(File.join(fixtures, '200_author_name.json')) }
|
let(:body) { File.read(fixtures.join('200_author_name.json')) }
|
||||||
|
|
||||||
it 'returns the expected array of users' do
|
it 'returns the expected array of users' do
|
||||||
users = finder.aggressive
|
users = finder.aggressive
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::RSSGenerator do
|
describe WPScan::Finders::Users::RSSGenerator do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { Pathname.new(FINDERS_FIXTURES).join('users', 'rss_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('users', 'rss_generator') }
|
||||||
let(:rss_fixture) { File.read(fixtures.join('feed.xml')) }
|
let(:rss_fixture) { File.read(fixtures.join('feed.xml')) }
|
||||||
|
|
||||||
describe '#passive, #aggressive' do
|
describe '#passive, #aggressive' do
|
||||||
@@ -41,7 +39,7 @@ describe WPScan::Finders::Users::RSSGenerator do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when RSS link in homepage' do
|
context 'when RSS link in homepage' do
|
||||||
let(:homepage_fixture) { File.join(fixtures, 'homepage_links.html') }
|
let(:homepage_fixture) { fixtures.join('homepage_links.html') }
|
||||||
|
|
||||||
it 'returns the expected from #passive' do
|
it 'returns the expected from #passive' do
|
||||||
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::WpJsonApi do
|
describe WPScan::Finders::Users::WpJsonApi do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
let(:url) { 'http://wp.lab/' }
|
let(:url) { 'http://wp.lab/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'wp_json_api') }
|
let(:fixtures) { FINDERS_FIXTURES.join('users', 'wp_json_api') }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
|
before { allow(target).to receive(:sub_dir).and_return(false) }
|
||||||
|
|
||||||
|
context 'when only one page of results' do
|
||||||
before do
|
before do
|
||||||
allow(target).to receive(:sub_dir).and_return(false)
|
stub_request(:get, finder.api_url)
|
||||||
stub_request(:get, finder.api_url).to_return(body: body)
|
.with(query: { page: 1, per_page: 100 })
|
||||||
|
.to_return(body: body, headers: {})
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when not a JSON response' do
|
context 'when not a JSON response' do
|
||||||
@@ -20,13 +22,13 @@ describe WPScan::Finders::Users::WpJsonApi do
|
|||||||
|
|
||||||
context 'when a JSON response' do
|
context 'when a JSON response' do
|
||||||
context 'when unauthorised' do
|
context 'when unauthorised' do
|
||||||
let(:body) { File.read(File.join(fixtures, '401.json')) }
|
let(:body) { File.read(fixtures.join('401.json')) }
|
||||||
|
|
||||||
its(:aggressive) { should eql([]) }
|
its(:aggressive) { should eql([]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when limited exposure (WP >= 4.7.1)' do
|
context 'when limited exposure (WP >= 4.7.1)' do
|
||||||
let(:body) { File.read(File.join(fixtures, '4.7.2.json')) }
|
let(:body) { File.read(fixtures.join('4.7.2.json')) }
|
||||||
|
|
||||||
it 'returns the expected array of users' do
|
it 'returns the expected array of users' do
|
||||||
users = finder.aggressive
|
users = finder.aggressive
|
||||||
@@ -38,9 +40,42 @@ describe WPScan::Finders::Users::WpJsonApi do
|
|||||||
expect(user.id).to eql 1
|
expect(user.id).to eql 1
|
||||||
expect(user.username).to eql 'admin'
|
expect(user.username).to eql 'admin'
|
||||||
expect(user.confidence).to eql 100
|
expect(user.confidence).to eql 100
|
||||||
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/wp/v2/users/']
|
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/wp/v2/users/?page=1&per_page=100']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when multiple pages of results' do
|
||||||
|
before do
|
||||||
|
stub_request(:get, finder.api_url)
|
||||||
|
.with(query: { page: 1, per_page: 100 })
|
||||||
|
.to_return(body: File.read(fixtures.join('4.7.2.json')), headers: { 'X-WP-TotalPages' => 2 })
|
||||||
|
|
||||||
|
stub_request(:get, finder.api_url)
|
||||||
|
.with(query: { page: 2, per_page: 100 })
|
||||||
|
.to_return(body: File.read(fixtures.join('4.7.2-2.json')), headers: { 'X-WP-TotalPages' => 2 })
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the expected array of users' do
|
||||||
|
users = finder.aggressive
|
||||||
|
|
||||||
|
expect(users.size).to eql 2
|
||||||
|
|
||||||
|
user = users.first
|
||||||
|
|
||||||
|
expect(user.id).to eql 1
|
||||||
|
expect(user.username).to eql 'admin'
|
||||||
|
expect(user.confidence).to eql 100
|
||||||
|
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/wp/v2/users/?page=1&per_page=100']
|
||||||
|
|
||||||
|
user = users.second
|
||||||
|
|
||||||
|
expect(user.id).to eql 20
|
||||||
|
expect(user.username).to eql 'user'
|
||||||
|
expect(user.confidence).to eql 100
|
||||||
|
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/wp/v2/users/?page=2&per_page=100']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::YoastSeoAuthorSitemap do
|
describe WPScan::Finders::Users::YoastSeoAuthorSitemap do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::Users::Base do
|
describe WPScan::Finders::Users::Base do
|
||||||
subject(:user) { described_class.new(target) }
|
subject(:user) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url) }
|
let(:target) { WPScan::Target.new(url) }
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::WpVersion::AtomGenerator do
|
describe WPScan::Finders::WpVersion::AtomGenerator do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { Pathname.new(FINDERS_FIXTURES).join('wp_version', 'atom_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('wp_version', 'atom_generator') }
|
||||||
let(:atom_fixture) { File.read(fixtures.join('feed', 'atom')) }
|
let(:atom_fixture) { File.read(fixtures.join('feed', 'atom')) }
|
||||||
|
|
||||||
describe '#passive, #aggressive' do
|
describe '#passive, #aggressive' do
|
||||||
@@ -38,7 +36,7 @@ describe WPScan::Finders::WpVersion::AtomGenerator do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when atom links in homepage' do
|
context 'when atom links in homepage' do
|
||||||
let(:homepage_fixture) { File.join(fixtures, 'links.html') }
|
let(:homepage_fixture) { fixtures.join('links.html') }
|
||||||
|
|
||||||
it 'returns the expected from #passive' do
|
it 'returns the expected from #passive' do
|
||||||
stub_request(:get, target.url('?feed=atom')).to_return(body: atom_fixture)
|
stub_request(:get, target.url('?feed=atom')).to_return(body: atom_fixture)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::WpVersion::RDFGenerator do
|
describe WPScan::Finders::WpVersion::RDFGenerator do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'rdf_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('wp_version', 'rdf_generator') }
|
||||||
|
|
||||||
xit
|
xit
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::WpVersion::Readme do
|
describe WPScan::Finders::WpVersion::Readme do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'readme') }
|
let(:fixtures) { FINDERS_FIXTURES.join('wp_version', 'readme') }
|
||||||
let(:readme_url) { url + 'readme.html' }
|
let(:readme_url) { url + 'readme.html' }
|
||||||
|
|
||||||
describe '#aggressive' do
|
describe '#aggressive' do
|
||||||
before { stub_request(:get, readme_url).to_return(body: File.read(File.join(fixtures, file))) }
|
before { stub_request(:get, readme_url).to_return(body: File.read(fixtures.join(file))) }
|
||||||
|
|
||||||
after do
|
after do
|
||||||
expect(target).to receive(:sub_dir).and_return(false)
|
expect(target).to receive(:sub_dir).and_return(false)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::WpVersion::RSSGenerator do
|
describe WPScan::Finders::WpVersion::RSSGenerator do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'rss_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('wp_version', 'rss_generator') }
|
||||||
|
|
||||||
xit
|
xit
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Finders::WpVersion::UniqueFingerprinting do
|
describe WPScan::Finders::WpVersion::UniqueFingerprinting do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
|
||||||
let(:url) { 'http://ex.lo/' }
|
let(:url) { 'http://ex.lo/' }
|
||||||
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'unique_fingerprinting') }
|
let(:fixtures) { FINDERS_FIXTURES.join('wp_version', 'unique_fingerprinting') }
|
||||||
|
|
||||||
xit
|
xit
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
|
# If this file is tested alone (rspec path-to-this-file), then there will be an error about
|
||||||
# constants not being intilialized. This is due to the Dynamic Finders.
|
# constants not being intilialized. This is due to the Dynamic Finders.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::InterestingFinding do
|
describe WPScan::InterestingFinding do
|
||||||
it_behaves_like WPScan::References do
|
it_behaves_like WPScan::References do
|
||||||
subject(:finding) { described_class.new('http://e.org/file.php', opts) }
|
subject(:finding) { described_class.new('http://e.org/file.php', opts) }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Media do
|
describe WPScan::Media do
|
||||||
subject(:media) { described_class.new(url) }
|
subject(:media) { described_class.new(url) }
|
||||||
let(:url) { 'http://e.oeg/?attachment_id=2' }
|
let(:url) { 'http://e.oeg/?attachment_id=2' }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Plugin do
|
describe WPScan::Plugin do
|
||||||
subject(:plugin) { described_class.new(slug, blog, opts) }
|
subject(:plugin) { described_class.new(slug, blog, opts) }
|
||||||
let(:slug) { 'spec' }
|
let(:slug) { 'spec' }
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Theme do
|
describe WPScan::Theme do
|
||||||
subject(:theme) { described_class.new(slug, blog, opts) }
|
subject(:theme) { described_class.new(slug, blog, opts) }
|
||||||
let(:slug) { 'spec' }
|
let(:slug) { 'spec' }
|
||||||
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:opts) { {} }
|
let(:opts) { {} }
|
||||||
let(:fixtures) { File.join(FIXTURES, 'models', 'theme') }
|
let(:fixtures) { FIXTURES.join('models', 'theme') }
|
||||||
|
|
||||||
before { expect(blog).to receive(:content_dir).at_least(1).and_return('wp-content') }
|
before { expect(blog).to receive(:content_dir).at_least(1).and_return('wp-content') }
|
||||||
|
|
||||||
describe '#new' do
|
describe '#new' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /.*\.css\z/)
|
stub_request(:get, /.*\.css\z/)
|
||||||
.to_return(body: File.read(File.join(fixtures, 'style.css')))
|
.to_return(body: File.read(fixtures.join('style.css')))
|
||||||
end
|
end
|
||||||
|
|
||||||
its(:url) { should eql 'http://wp.lab/wp-content/themes/spec/' }
|
its(:url) { should eql 'http://wp.lab/wp-content/themes/spec/' }
|
||||||
@@ -39,7 +37,7 @@ describe WPScan::Theme do
|
|||||||
describe '#version' do
|
describe '#version' do
|
||||||
after do
|
after do
|
||||||
stub_request(:get, /.*\.css\z/)
|
stub_request(:get, /.*\.css\z/)
|
||||||
.to_return(body: File.read(File.join(fixtures, 'style.css')))
|
.to_return(body: File.read(fixtures.join('style.css')))
|
||||||
|
|
||||||
expect(WPScan::Finders::ThemeVersion::Base).to receive(:find).with(theme, @expected_opts)
|
expect(WPScan::Finders::ThemeVersion::Base).to receive(:find).with(theme, @expected_opts)
|
||||||
theme.version(version_opts)
|
theme.version(version_opts)
|
||||||
@@ -93,7 +91,7 @@ describe WPScan::Theme do
|
|||||||
describe '#parent_theme' do
|
describe '#parent_theme' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, blog.url('wp-content/themes/spec/style.css'))
|
stub_request(:get, blog.url('wp-content/themes/spec/style.css'))
|
||||||
.to_return(body: File.read(File.join(fixtures, main_theme)))
|
.to_return(body: File.read(fixtures.join(main_theme)))
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when no template' do
|
context 'when no template' do
|
||||||
@@ -110,7 +108,7 @@ describe WPScan::Theme do
|
|||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, parent_url)
|
stub_request(:get, parent_url)
|
||||||
.to_return(body: File.read(File.join(fixtures, 'style.css')))
|
.to_return(body: File.read(fixtures.join('style.css')))
|
||||||
end
|
end
|
||||||
|
|
||||||
%w[child_style windows_line_endings].each do |fixture|
|
%w[child_style windows_line_endings].each do |fixture|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::Timthumb do
|
describe WPScan::Timthumb do
|
||||||
subject(:timthumb) { described_class.new(url, opts) }
|
subject(:timthumb) { described_class.new(url, opts) }
|
||||||
let(:url) { 'http://wp.lab/wp-content/timthumb.php' }
|
let(:url) { 'http://wp.lab/wp-content/timthumb.php' }
|
||||||
let(:fixtures) { File.join(FIXTURES, 'models', 'timthumb') }
|
let(:fixtures) { FIXTURES.join('models', 'timthumb') }
|
||||||
let(:opts) { {} }
|
let(:opts) { {} }
|
||||||
|
|
||||||
describe '#new' do
|
describe '#new' do
|
||||||
@@ -61,7 +59,7 @@ describe WPScan::Timthumb do
|
|||||||
describe '#webshot_enabled?' do
|
describe '#webshot_enabled?' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /#{timthumb.url}\?src=.*&webshot=1/i)
|
stub_request(:get, /#{timthumb.url}\?src=.*&webshot=1/i)
|
||||||
.to_return(body: File.read(File.join(fixtures, fixture)))
|
.to_return(body: File.read(fixtures.join(fixture)))
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when enabled' do
|
context 'when enabled' do
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::WpItem do
|
describe WPScan::WpItem do
|
||||||
subject(:wp_item) { described_class.new(slug, blog, opts) }
|
subject(:wp_item) { described_class.new(slug, blog, opts) }
|
||||||
let(:slug) { 'test_item' }
|
let(:slug) { 'test_item' }
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::WpVersion do
|
describe WPScan::WpVersion do
|
||||||
describe '#new' do
|
describe '#new' do
|
||||||
context 'when invalid number' do
|
context 'when invalid number' do
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe WPScan::XMLRPC do
|
describe WPScan::XMLRPC do
|
||||||
subject(:xml_rpc) { described_class.new('http//e.org/xmlrpc.php') }
|
subject(:xml_rpc) { described_class.new('http//e.org/xmlrpc.php') }
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user