Compare commits
327 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a661088bb | ||
|
|
91659a32af | ||
|
|
5f8cd7e5c4 | ||
|
|
bc3f62a766 | ||
|
|
92faedb4a5 | ||
|
|
6f7008dd91 | ||
|
|
447589541f | ||
|
|
45f5f50262 | ||
|
|
f77a27ecc3 | ||
|
|
09de2eb194 | ||
|
|
7747a5665b | ||
|
|
aa617b5106 | ||
|
|
8038e2e01a | ||
|
|
212b068a8d | ||
|
|
2bcea0b566 | ||
|
|
512d4f2fb9 | ||
|
|
b524546e9c | ||
|
|
f91e287207 | ||
|
|
0fcf0a6a88 | ||
|
|
f9f3d74a3b | ||
|
|
2bfd0f2cc0 | ||
|
|
cdeb2eebe5 | ||
|
|
5134516afc | ||
|
|
e14b5d99eb | ||
|
|
a0375f52cf | ||
|
|
69dbcf3947 | ||
|
|
79387730bc | ||
|
|
3e6b019044 | ||
|
|
1886b90be7 | ||
|
|
85421f9b4b | ||
|
|
3749ef8433 | ||
|
|
dfb3e98fec | ||
|
|
a40442c8a9 | ||
|
|
a7396d6bee | ||
|
|
507c4c67ff | ||
|
|
cbdc04e929 | ||
|
|
a6582a1da3 | ||
|
|
3d8f3df8f1 | ||
|
|
7b8dbdedb5 | ||
|
|
53b13eacaa | ||
|
|
fcc76d99ef | ||
|
|
9a2141025a | ||
|
|
bfe3285375 | ||
|
|
5cf9c6e073 | ||
|
|
5e00d77e69 | ||
|
|
a4dfb05d0c | ||
|
|
97a798e357 | ||
|
|
47aafe88f8 | ||
|
|
bc356ab8e5 | ||
|
|
dd5cdfd848 | ||
|
|
de2cb08a6b | ||
|
|
9a2550ad48 | ||
|
|
2f6e4c0736 | ||
|
|
a9c5cbf11f | ||
|
|
facd0d398a | ||
|
|
1b2fc5d403 | ||
|
|
9d290aa533 | ||
|
|
9046291128 | ||
|
|
59131b6b51 | ||
|
|
3725a23c49 | ||
|
|
812c42c89a | ||
|
|
285d7d3265 | ||
|
|
134789602b | ||
|
|
55f49b5f78 | ||
|
|
cd8067285f | ||
|
|
10c09e9375 | ||
|
|
bb70c0733a | ||
|
|
3dad2b31bb | ||
|
|
7844acd70f | ||
|
|
f01b0b3404 | ||
|
|
10fee6e144 | ||
|
|
c4c8a8b703 | ||
|
|
7053a1e42a | ||
|
|
fd3c4261de | ||
|
|
d21e475d12 | ||
|
|
48bdf0b2a9 | ||
|
|
ac1c652854 | ||
|
|
3b286de9db | ||
|
|
cbcb696cfd | ||
|
|
13320ea8cc | ||
|
|
bdf45f6a0b | ||
|
|
667b1e9f99 | ||
|
|
a0f476fb24 | ||
|
|
13c32bfe53 | ||
|
|
a54da059ef | ||
|
|
76fe0def4f | ||
|
|
9a25b747ae | ||
|
|
aeefd3e873 | ||
|
|
f9efdcb654 | ||
|
|
be672cbcba | ||
|
|
c4ca7e471a | ||
|
|
bbce082ec2 | ||
|
|
781214a2f0 | ||
|
|
7942eaf64b | ||
|
|
36cd3c0c42 | ||
|
|
620bccb102 | ||
|
|
3ca79bebc7 | ||
|
|
a1add0cfdb | ||
|
|
dc22ad1ca1 | ||
|
|
010df5a081 | ||
|
|
71e8b22849 | ||
|
|
138c17d4a3 | ||
|
|
bac19b2486 | ||
|
|
dab2001dcc | ||
|
|
5bff9eb4d8 | ||
|
|
e2102bdefa | ||
|
|
2a3e06610f | ||
|
|
d186240cfc | ||
|
|
0f0d4f06bb | ||
|
|
249af325c9 | ||
|
|
a7532f2154 | ||
|
|
1c0a00e9b2 | ||
|
|
b1b8066fe5 | ||
|
|
25c2f3adad | ||
|
|
68e47d70fd | ||
|
|
af3b3f4ee5 | ||
|
|
1b63d514ac | ||
|
|
c6453a6e10 | ||
|
|
3f3f5fdaa0 | ||
|
|
2f72721ee2 | ||
|
|
92d99c6d64 | ||
|
|
f3b26b1101 | ||
|
|
4f0a5bcf15 | ||
|
|
ffb1a8ad84 | ||
|
|
70c07cf731 | ||
|
|
b2d946794b | ||
|
|
90617c5433 | ||
|
|
278dc34b44 | ||
|
|
dcd5d7b534 | ||
|
|
2d48465e1d | ||
|
|
6bda493f6e | ||
|
|
5459b8bb7a | ||
|
|
e410939bde | ||
|
|
047de2d747 | ||
|
|
997f4d35c2 | ||
|
|
ca547f1239 | ||
|
|
c9665773e2 | ||
|
|
eeeea6b735 | ||
|
|
bbd6a2b5d5 | ||
|
|
d33db2a0fe | ||
|
|
1f2588d677 | ||
|
|
f30bad5c5a | ||
|
|
5a5bf77b1c | ||
|
|
22c6597005 | ||
|
|
9761d70f23 | ||
|
|
518135006c | ||
|
|
9327eb7e75 | ||
|
|
13080ade9e | ||
|
|
9c3947a7b1 | ||
|
|
f33cbcaa53 | ||
|
|
2c8fe7971f | ||
|
|
85e10330cb | ||
|
|
a02fd4b6f6 | ||
|
|
9395119749 | ||
|
|
2c0bbe9082 | ||
|
|
b1535864aa | ||
|
|
fd880da057 | ||
|
|
6c62b06e46 | ||
|
|
b44869ec49 | ||
|
|
b3a6251b04 | ||
|
|
80667bc38f | ||
|
|
cff35ea845 | ||
|
|
cb93397ae4 | ||
|
|
c805a8d624 | ||
|
|
3f775c081c | ||
|
|
864b892da0 | ||
|
|
f7773d2113 | ||
|
|
cf471d0f36 | ||
|
|
d14791679c | ||
|
|
f358d34e54 | ||
|
|
7ba3a7dd2f | ||
|
|
196af51e2c | ||
|
|
cbe959da66 | ||
|
|
9512fd4cca | ||
|
|
e2b6853c46 | ||
|
|
2578bfd0ff | ||
|
|
277fff5f2c | ||
|
|
4c72e9d206 | ||
|
|
7a44a303e5 | ||
|
|
e3796045eb | ||
|
|
85ad8d8b9f | ||
|
|
f737c92988 | ||
|
|
5d05ecaee3 | ||
|
|
8cc83a8df9 | ||
|
|
43b0f1bea9 | ||
|
|
a12ee4a61e | ||
|
|
d595a45f2b | ||
|
|
76a6d59837 | ||
|
|
bfe9bf2d5b | ||
|
|
59cac169e7 | ||
|
|
c24ee89b16 | ||
|
|
a73c2d7292 | ||
|
|
97671b3592 | ||
|
|
dd38586ead | ||
|
|
e11de68203 | ||
|
|
97ce286ff2 | ||
|
|
99e4e5a219 | ||
|
|
316b9aa68a | ||
|
|
7318d6615f | ||
|
|
6782b108b0 | ||
|
|
494af0ad23 | ||
|
|
55cff03747 | ||
|
|
599cc7c3af | ||
|
|
bfa7a7a6dc | ||
|
|
b243a5404b | ||
|
|
2e40a7377a | ||
|
|
62e86a0474 | ||
|
|
8c1ee9cf21 | ||
|
|
3afda882de | ||
|
|
69fd90ed3a | ||
|
|
554530dd60 | ||
|
|
2472e5546f | ||
|
|
a7ee4c09f5 | ||
|
|
7effac73b9 | ||
|
|
125924d125 | ||
|
|
00aaac866f | ||
|
|
170299c13c | ||
|
|
ac6f56dbf4 | ||
|
|
09c494c6c5 | ||
|
|
fdd685d20c | ||
|
|
fcff22981b | ||
|
|
7f82a41e66 | ||
|
|
17d12b41db | ||
|
|
2f7d68f7f1 | ||
|
|
dc1c65b418 | ||
|
|
23de013c86 | ||
|
|
a922b00716 | ||
|
|
babe21a3dc | ||
|
|
59ef0b05a1 | ||
|
|
3da7ed76c5 | ||
|
|
bbf0cd7578 | ||
|
|
25be97e65c | ||
|
|
175bb9206e | ||
|
|
68605ad409 | ||
|
|
4500687d47 | ||
|
|
fc38e6f270 | ||
|
|
f1936fea6b | ||
|
|
24bdcf66ed | ||
|
|
8688523ced | ||
|
|
856944e463 | ||
|
|
84f6894bc4 | ||
|
|
9bf33f89a9 | ||
|
|
c0fa7c42cd | ||
|
|
3281a85ae9 | ||
|
|
0db965a95f | ||
|
|
0732ea1162 | ||
|
|
c88497afba | ||
|
|
d4892c19b4 | ||
|
|
3ed25b069d | ||
|
|
e51b1f7643 | ||
|
|
7d07b27d4f | ||
|
|
57fdc90623 | ||
|
|
72bec2ef49 | ||
|
|
58a3805788 | ||
|
|
40f96dd2bd | ||
|
|
fca13d453e | ||
|
|
32e590f398 | ||
|
|
301b44dcae | ||
|
|
e45e91b0bf | ||
|
|
fe31dbca26 | ||
|
|
51fa754ec5 | ||
|
|
2ce10af051 | ||
|
|
c107422353 | ||
|
|
1e1fdee5a7 | ||
|
|
fffcd61cc4 | ||
|
|
2fd11cba15 | ||
|
|
f1ec85aef5 | ||
|
|
4c4b363035 | ||
|
|
8555e0c7e7 | ||
|
|
c07f7390ec | ||
|
|
34f6e15271 | ||
|
|
135f0677e4 | ||
|
|
63ad255f2b | ||
|
|
16ac8ea196 | ||
|
|
0e00773238 | ||
|
|
cf1f676268 | ||
|
|
d2f304b047 | ||
|
|
0a9bb138c5 | ||
|
|
6236391c86 | ||
|
|
78257cb1c0 | ||
|
|
c4cb75668c | ||
|
|
9880bcacd6 | ||
|
|
52aedd0a31 | ||
|
|
c7ce741857 | ||
|
|
bcbf012406 | ||
|
|
ec75b4418b | ||
|
|
716b84f507 | ||
|
|
e95b3a59ef | ||
|
|
9dc179b2cd | ||
|
|
efe1b01936 | ||
|
|
cd26b0c5a9 | ||
|
|
b075f71f11 | ||
|
|
44145ef265 | ||
|
|
82ef21b821 | ||
|
|
5655d7456c | ||
|
|
a7992102af | ||
|
|
ee2cd412ce | ||
|
|
1c34f48c39 | ||
|
|
0c2937936b | ||
|
|
b0c3f6c82a | ||
|
|
e047525be9 | ||
|
|
7f1ad590f6 | ||
|
|
fbf2d827c2 | ||
|
|
72619df02c | ||
|
|
c58d8992cf | ||
|
|
c98177ea20 | ||
|
|
766409e581 | ||
|
|
c076d61cc9 | ||
|
|
92e265ecc9 | ||
|
|
e223df64cf | ||
|
|
629ebf5ff2 | ||
|
|
0019eb70b5 | ||
|
|
e5f1be0b30 | ||
|
|
dd74934638 | ||
|
|
8d4973a9cc | ||
|
|
a49c091cd5 | ||
|
|
7d0268a4ce | ||
|
|
44e53e7225 | ||
|
|
1a1689da1f | ||
|
|
a28802e84e | ||
|
|
2798e71a52 | ||
|
|
e3647092b0 | ||
|
|
117cc13ed7 | ||
|
|
2d39a04575 | ||
|
|
d3e9457532 | ||
|
|
afc737b9bd | ||
|
|
32e597f6a4 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -11,3 +11,4 @@ log.txt
|
||||
.yardoc
|
||||
debug.log
|
||||
wordlist.txt
|
||||
rspec_results.html
|
||||
|
||||
11
.travis.yml
11
.travis.yml
@@ -1,6 +1,11 @@
|
||||
language: ruby
|
||||
rvm:
|
||||
- "1.9.2"
|
||||
- "1.9.3"
|
||||
- "2.0.0"
|
||||
- 1.9.2
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- 2.1.0
|
||||
- 2.1.1
|
||||
script: bundle exec rspec --format documentation
|
||||
notifications:
|
||||
email:
|
||||
- wpscanteam@gmail.com
|
||||
|
||||
129
CHANGELOG.md
129
CHANGELOG.md
@@ -1,9 +1,120 @@
|
||||
# Changelog
|
||||
## Master
|
||||
[Work in progress](https://github.com/wpscanteam/wpscan/compare/2.4...master)
|
||||
|
||||
## Version 2.2
|
||||
## Version 2.4
|
||||
Released: 2014-04-17
|
||||
|
||||
New
|
||||
* '--batch' switch option added - Fix #454
|
||||
* Add random-agent
|
||||
* Added more CLI options
|
||||
* Switch over to nist - Fix #301
|
||||
* New choice added when a redirection is detected - Fix #438
|
||||
|
||||
|
||||
Removed
|
||||
* Removed 'Total WordPress Sites in the World' counter from stats
|
||||
* Old wpscan repo links removed - Fix #440
|
||||
* Fingerprinting Dev script removed
|
||||
* Useless code removed
|
||||
|
||||
General core
|
||||
* Rspecs update
|
||||
* Forcing Travis notify the team
|
||||
* Ruby 2.1.1 added to Travis
|
||||
* Equal output layout for interaction questions
|
||||
* Only output error trace if verbose if enabled
|
||||
* Memory improvements during wp-items enumerations
|
||||
* Fixed broken link checker, fixed some broken links
|
||||
* Couple more 404s fixed
|
||||
* Themes & Plugins list updated
|
||||
|
||||
WordPress Fingerprints
|
||||
* WP 3.8.2 & 3.7.2 Fingerprints added - Fix #448
|
||||
* WP 3.8.3 & 3.7.3 fingerprints
|
||||
* WP 3.9 fingerprints
|
||||
|
||||
Fixed issues
|
||||
* Fix #380 - Redirects in WP 3.6-3.0
|
||||
* Fix #413 - Check the version of the Timthumbs files found
|
||||
* Fix #429 - Error WpScan Cache Browser
|
||||
* Fix #431 - Version number comparison between '2.3.3' and '0.42b'
|
||||
* Fix #439 - Detect if the target goes down during the scan
|
||||
* Fix #451 - Do not rely only on files in wp-content for fingerprinting
|
||||
* Fix #453 - Documentation or inplemention of option parameters
|
||||
* Fix #455 - Fails with a message if the target returns a 403 during the wordpress check
|
||||
|
||||
Vulnerabilities
|
||||
* Update WordPress Vulnerabilities
|
||||
* Fixed some duplicate vulnerabilities
|
||||
|
||||
WPScan Database Statistics:
|
||||
* Total vulnerable versions: 79; 1 is new
|
||||
* Total vulnerable plugins: 748; 55 are new
|
||||
* Total vulnerable themes: 292; 41 are new
|
||||
* Total version vulnerabilities: 617; 326 are new
|
||||
* Total plugin vulnerabilities: 1162; 146 are new
|
||||
* Total theme vulnerabilities: 330; 47 are new
|
||||
|
||||
## Version 2.3
|
||||
Released: 2014-02-11
|
||||
|
||||
New
|
||||
* Brute forcing over https!
|
||||
* Detect and output parent theme!
|
||||
* Complete fingerprint script & hash search
|
||||
* New spell checker!
|
||||
* Added database modification dates in status report
|
||||
* Added 'Total WordPress Sites in the World' statistics
|
||||
* Added separator between Name and Version in Item
|
||||
* Added a "Work in progress" URL in the CHANGELOG
|
||||
|
||||
Removed
|
||||
* Removed "Exiting!" sentence
|
||||
* Removed Backtrack Linux. Not maintained anymore.
|
||||
|
||||
General core
|
||||
* Ruby 2.1.0 added to Travis
|
||||
* Updated the version of WebMock required
|
||||
* Better string concatenation in code (improves speed)
|
||||
* Some modifications in the output of an item
|
||||
* Output cosmetics
|
||||
* rspec-mocks version constraint released
|
||||
* Tabs replaced by spaces
|
||||
* Rspecs update
|
||||
* Indent code cleanup
|
||||
* Themes & Plugins lists regenerated
|
||||
|
||||
Vulnerabilities
|
||||
* Update WordPress Vulnerabilities
|
||||
* Disabled some fake reported vulnerabilities
|
||||
* Fixed some duplicate vulnerabilities
|
||||
|
||||
WPScan Database Statistics:
|
||||
* Total vulnerable versions: 78; 2 are new
|
||||
* Total vulnerable plugins: 693; 83 are new
|
||||
* Total vulnerable themes: 251; 55 are new
|
||||
* Total version vulnerabilities: 291 17 are new
|
||||
* Total plugin vulnerabilities: 1016; 236 are new
|
||||
* Total theme vulnerabilities: 283; 79 are new
|
||||
|
||||
WordPress Fingerprints
|
||||
* Better fingerprints
|
||||
* WP 3.8.1 Fingerprinting
|
||||
* WP 3.8 Fingerprinting
|
||||
|
||||
Fixed issues
|
||||
* Fix #404 - Brute forcing issue over https
|
||||
* Fix #398 - Removed a fake vuln in WP Super Cache
|
||||
* Fix #393 - sudo added to the bundle install cmd for Mac OSX
|
||||
* Fix #228, #327 - Infinite loop when self-redirect
|
||||
* Fix #201 - Incorrect Paramter Parsing when no url was supplied
|
||||
|
||||
## Version 2.2
|
||||
Released: 2013-11-12
|
||||
|
||||
Added
|
||||
New
|
||||
* Output the vulnerability fix if available
|
||||
* Added 'WordPress Version Vulnerability' statistics
|
||||
* Added Kali Linux on the list of pre-installed Linux distributions
|
||||
@@ -82,13 +193,13 @@ Vulnerabilities
|
||||
* Update timthumb due to Secunia #54801
|
||||
* Added WP vuln: 3.4 - 3.5.1 wp-admin/users.php FPD
|
||||
|
||||
WPScan Databse Statistics:
|
||||
* Total vulnerable versions: 76, 4 are new
|
||||
* Total vulnerable plugins: 606, 197 are new
|
||||
* Total vulnerable themes: 194, 45 are new
|
||||
* Total version vulnerabilities: 274, 53 are new
|
||||
* Total plugin vulnerabilities: 764, 270 are new
|
||||
* Total theme vulnerabilities: 198, 46 are new
|
||||
WPScan Database Statistics:
|
||||
* Total vulnerable versions: 76; 4 are new
|
||||
* Total vulnerable plugins: 610; 201 are new
|
||||
* Total vulnerable themes: 196; 47 are new
|
||||
* Total version vulnerabilities: 274; 53 are new
|
||||
* Total plugin vulnerabilities: 780; 286 are new
|
||||
* Total theme vulnerabilities: 204; 52 are new
|
||||
|
||||
Add WP Fingerprints
|
||||
* WP 3.7.1 Fingerprinting
|
||||
|
||||
4
CREDITS
4
CREDITS
@@ -6,7 +6,7 @@ This file is to give credit to WPScan's contributors. If you feel your name shou
|
||||
|
||||
Erwan.LR - @erwan_lr - (Project Developer)
|
||||
Christian Mehlmauer - @_FireFart_ - (Project Developer)
|
||||
Gianluca Brindisi - @gbrindisi (Project Developer)
|
||||
Peter van der Laan - pvdl - (Vuln Hunter and Code Cleaner)
|
||||
Ryan Dewhurst - @ethicalhack3r (Project Lead)
|
||||
|
||||
*Other Contributors*
|
||||
@@ -17,4 +17,4 @@ Callum Pember - Implemented proxy support - callumpember at gmail.com
|
||||
g0tmi1k - Additional timthumb checks + bug reports.
|
||||
Melvin Lammerts - Reported a couple of fake vulnerabilities - melvin at 12k.nl
|
||||
Paolo Perego - @thesp0nge - Basic authentication
|
||||
Peter van der Laan - The Vuln Hunter and Code Cleaner
|
||||
Gianluca Brindisi - @gbrindisi - Project Developer
|
||||
6
Gemfile
6
Gemfile
@@ -1,15 +1,13 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
# Seg fault in Typhoeus 0.6.3 (and ethon > 0.5.11) with rspec
|
||||
gem "typhoeus", ">=0.6.3"
|
||||
gem "typhoeus", "~>0.6.8"
|
||||
gem "nokogiri"
|
||||
gem "json"
|
||||
gem "terminal-table"
|
||||
gem "ruby-progressbar", ">=1.2.0"
|
||||
|
||||
group :test do
|
||||
gem "webmock", ">=1.9.3"
|
||||
gem "webmock", ">=1.17.2"
|
||||
gem "simplecov"
|
||||
gem "rspec", :require => "spec"
|
||||
gem "rspec-mocks", "<=2.14.2" # 2.14.3 just messed around :/
|
||||
end
|
||||
|
||||
17
README
17
README
@@ -32,7 +32,7 @@ ryandewhurst at gmail
|
||||
WPScan comes pre-installed on the following Linux distributions:
|
||||
|
||||
* BackBox Linux
|
||||
* BackTrack Linux
|
||||
* Kali Linux
|
||||
* Pentoo
|
||||
* SamuraiWTF
|
||||
|
||||
@@ -76,13 +76,12 @@ ryandewhurst at gmail
|
||||
|
||||
git clone https://github.com/wpscanteam/wpscan.git
|
||||
cd wpscan
|
||||
sudo gem install bundler && bundle install --without test
|
||||
sudo gem install bundler && sudo bundle install --without test
|
||||
|
||||
==KNOWN ISSUES==
|
||||
|
||||
- Typhoeus segmentation fault:
|
||||
Update cURL to version => 7.21 (may have to install from source)
|
||||
See http://code.google.com/p/wpscan/issues/detail?id=81
|
||||
|
||||
- Proxy not working:
|
||||
Update cURL to version => 7.21.7 (may have to install from source).
|
||||
@@ -142,6 +141,10 @@ ryandewhurst at gmail
|
||||
|
||||
--config-file | -c <config file> Use the specified config file
|
||||
|
||||
--user-agent | -a <User-Agent> Use the specified User-Agent
|
||||
|
||||
--random-agent | -r Use a random User-Agent
|
||||
|
||||
--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not
|
||||
|
||||
--wp-content-dir <wp content dir> WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed
|
||||
@@ -161,6 +164,14 @@ ryandewhurst at gmail
|
||||
|
||||
--username | -U <username> Only brute force the supplied username.
|
||||
|
||||
--cache-ttl <cache-ttl> Typhoeus cache TTL
|
||||
|
||||
--request-timeout <request-timeout> Request Timeout
|
||||
|
||||
--connect-timeout <connect-timeout> Connect Timeout
|
||||
|
||||
--max-threads <max-threads> Maximum Threads
|
||||
|
||||
--help | -h This help screen.
|
||||
|
||||
--verbose | -v Verbose output.
|
||||
|
||||
16
README.md
16
README.md
@@ -27,7 +27,6 @@ ryandewhurst at gmail
|
||||
WPScan comes pre-installed on the following Linux distributions:
|
||||
|
||||
- [BackBox Linux](http://www.backbox.org/)
|
||||
- [BackTrack Linux](http://www.backtrack-linux.org/)
|
||||
- [Kali Linux](http://www.kali.org/)
|
||||
- [Pentoo](http://www.pentoo.ch/)
|
||||
- [SamuraiWTF](http://samurai.inguardians.com/)
|
||||
@@ -84,14 +83,13 @@ Apple Xcode, Command Line Tools and the libffi are needed (to be able to install
|
||||
|
||||
```cd wpscan```
|
||||
|
||||
```sudo gem install bundler && bundle install --without test```
|
||||
```sudo gem install bundler && sudo bundle install --without test```
|
||||
|
||||
#### KNOWN ISSUES
|
||||
|
||||
- Typhoeus segmentation fault
|
||||
|
||||
Update cURL to version => 7.21 (may have to install from source)
|
||||
See http://code.google.com/p/wpscan/issues/detail?id=81
|
||||
|
||||
- Proxy not working
|
||||
|
||||
@@ -157,6 +155,10 @@ Apple Xcode, Command Line Tools and the libffi are needed (to be able to install
|
||||
|
||||
--config-file | -c <config file> Use the specified config file
|
||||
|
||||
--user-agent | -a <User-Agent> Use the specified User-Agent
|
||||
|
||||
--random-agent | -r Use a random User-Agent
|
||||
|
||||
--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not
|
||||
|
||||
--wp-content-dir <wp content dir> WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed
|
||||
@@ -176,6 +178,14 @@ Apple Xcode, Command Line Tools and the libffi are needed (to be able to install
|
||||
|
||||
--username | -U <username> Only brute force the supplied username.
|
||||
|
||||
--cache-ttl <cache-ttl> Typhoeus cache TTL
|
||||
|
||||
--request-timeout <request-timeout> Request Timeout
|
||||
|
||||
--connect-timeout <connect-timeout> Connect Timeout
|
||||
|
||||
--max-threads <max-threads> Maximum Threads
|
||||
|
||||
--help | -h This help screen.
|
||||
|
||||
--verbose | -v Verbose output.
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0",
|
||||
/* Modes :
|
||||
static : will use the defined user_agent for each request
|
||||
semi-static : will randomly choose a user agent into available_user_agents before each scan
|
||||
random : each request will choose a random user agent in available_user_agents
|
||||
*/
|
||||
"user_agent_mode": "static",
|
||||
|
||||
/* Uncomment the "proxy" line to use the proxy
|
||||
SOCKS proxies (4, 4A, 5) are supported, ie : "proxy": "socks5://127.0.0.1:9000"
|
||||
If you do not specify the protocol, http will be used
|
||||
*/
|
||||
//"proxy": "127.0.0.1:3128",
|
||||
//"proxy_auth": "username:password",
|
||||
|
||||
"cache_ttl": 600, // 10 minutes, at this time the cache is cleaned before each scan. If this value is set to 0, the cache will be disabled
|
||||
|
||||
"request_timeout": 2000, // 2s
|
||||
|
||||
"connect_timeout": 1000, // 1s
|
||||
|
||||
"max_threads": 20,
|
||||
|
||||
// Some user_agents can be found there http://techpatterns.com/downloads/firefox/useragentswitcher.xml (thx to Gianluca Brindisi)
|
||||
"available_user_agents":
|
||||
[
|
||||
// Windows
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.24 Safari/535.1",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)",
|
||||
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
|
||||
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1",
|
||||
"Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1",
|
||||
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)",
|
||||
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)",
|
||||
"Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5",
|
||||
|
||||
// MAC
|
||||
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13",
|
||||
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
|
||||
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10",
|
||||
|
||||
// Linux
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24",
|
||||
"Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9",
|
||||
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0",
|
||||
"Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0",
|
||||
"Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00",
|
||||
"Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0"
|
||||
]
|
||||
}
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
<xs:simpleType name="stringtype">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:whiteSpace value="preserve" />
|
||||
<xs:minLength value="1" />
|
||||
<xs:pattern value="[^\s].+[^\s]|[^\s]"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1024
data/plugins.txt
1024
data/plugins.txt
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1503
data/theme_vulns.xml
1503
data/theme_vulns.xml
File diff suppressed because it is too large
Load Diff
262
data/themes.txt
262
data/themes.txt
@@ -1,62 +1,64 @@
|
||||
2013-black-and-white
|
||||
academica
|
||||
accessible-zen
|
||||
aadya
|
||||
abaris
|
||||
adamos
|
||||
adaptive-flat
|
||||
adelle
|
||||
admired
|
||||
adventure
|
||||
adventure-journal
|
||||
advertica-lite
|
||||
albinomouse
|
||||
aldehyde
|
||||
alexandria
|
||||
alhena-lite
|
||||
analytical-lite
|
||||
andrina-lite
|
||||
annotum-base
|
||||
ascetica
|
||||
anarcho-notepad
|
||||
apprise
|
||||
arcade-basic
|
||||
arunachala
|
||||
aspen
|
||||
asteria-lite
|
||||
asteroid
|
||||
atahualpa
|
||||
atheros
|
||||
attitude
|
||||
attorney
|
||||
autofocus
|
||||
base-wp
|
||||
beach
|
||||
birdsite
|
||||
birdtips
|
||||
bearded
|
||||
big-city
|
||||
bizantine
|
||||
bizark
|
||||
bizflare
|
||||
bizkit
|
||||
biznez-lite
|
||||
bizsphere
|
||||
bizstudio-lite
|
||||
bizway
|
||||
black-rider
|
||||
blackbird
|
||||
blain
|
||||
blankslate
|
||||
blogbox
|
||||
blogolife
|
||||
bold-headline
|
||||
blox
|
||||
bluegray
|
||||
boldr-lite
|
||||
book-lite
|
||||
boot-store
|
||||
bota
|
||||
bootstrap-ultimate
|
||||
bouquet
|
||||
bresponzive
|
||||
brightnews
|
||||
bueno
|
||||
business-lite
|
||||
busiprof
|
||||
buzz
|
||||
careta
|
||||
carton
|
||||
capture
|
||||
catch-box
|
||||
catch-everest
|
||||
catch-evolution
|
||||
cazuela
|
||||
celebrate
|
||||
catch-kathmandu
|
||||
celestial-lite
|
||||
central
|
||||
chaostheory
|
||||
cherry-blossom
|
||||
childishly-simple
|
||||
church
|
||||
clean-black
|
||||
cirrus
|
||||
clean-retina
|
||||
cleo
|
||||
coller
|
||||
colorway
|
||||
contango
|
||||
@@ -65,236 +67,232 @@ corpo
|
||||
custom-community
|
||||
customizr
|
||||
cyberchimps
|
||||
cycnus
|
||||
d5-business-line
|
||||
d5-design
|
||||
d5-socialia
|
||||
dailypost
|
||||
dark-tt
|
||||
dazzling
|
||||
decode
|
||||
delicate
|
||||
delighted
|
||||
designfolio
|
||||
desk-mess-mirrored
|
||||
destro
|
||||
deux-milles-douze
|
||||
discover
|
||||
dms
|
||||
drop
|
||||
duena
|
||||
dusk-to-dawn
|
||||
duster
|
||||
dw-minion
|
||||
easel
|
||||
dw-timeline
|
||||
dw-wallpress
|
||||
eclipse
|
||||
elegantwhite
|
||||
emphaino
|
||||
encounters-lite
|
||||
elmax
|
||||
engrave-lite
|
||||
epic
|
||||
esell
|
||||
esplanade
|
||||
espressionista
|
||||
esquire
|
||||
estate
|
||||
evolve
|
||||
expert
|
||||
expound
|
||||
fashionistas
|
||||
family
|
||||
fifteen
|
||||
fine
|
||||
firmasite
|
||||
fluxipress
|
||||
flat
|
||||
focus
|
||||
forever
|
||||
frisco-for-buddypress
|
||||
formation
|
||||
fresh-lite
|
||||
frontier
|
||||
fruitful
|
||||
futuristica
|
||||
gamepress
|
||||
golden-eagle-lite
|
||||
gold
|
||||
govpress
|
||||
graphene
|
||||
greenpage
|
||||
graphy
|
||||
gridbulletin
|
||||
gridiculous
|
||||
gridster-lite
|
||||
hannari
|
||||
hatch
|
||||
hazen
|
||||
heatmap-adaptive
|
||||
hero
|
||||
hiero
|
||||
health-center-lite
|
||||
hemingway
|
||||
highwind
|
||||
hostmarks
|
||||
houston
|
||||
hro
|
||||
hybrid
|
||||
hueman
|
||||
i-transform
|
||||
iconic-one
|
||||
icy
|
||||
ifeature
|
||||
imag-mag
|
||||
impressio-lite
|
||||
impulse
|
||||
imprint
|
||||
independent-publisher
|
||||
infinite
|
||||
infoway
|
||||
innovative
|
||||
inkness
|
||||
inkzine
|
||||
intuition
|
||||
invert-lite
|
||||
irex-lite
|
||||
iribbon
|
||||
kabbo
|
||||
isis
|
||||
itek
|
||||
justwrite
|
||||
kavya
|
||||
klasik
|
||||
koenda
|
||||
lamya
|
||||
landscape
|
||||
leaf
|
||||
litesta
|
||||
lobster
|
||||
local-business
|
||||
lugada
|
||||
leatherdiary
|
||||
lingonberry
|
||||
linia-magazine
|
||||
luminescence-lite
|
||||
magazine
|
||||
magazine-basic
|
||||
lupercalia
|
||||
magazine-style
|
||||
magazino
|
||||
manchester
|
||||
mantra
|
||||
marla
|
||||
market
|
||||
match
|
||||
matheson
|
||||
max-magazine
|
||||
melany
|
||||
maxflat-core
|
||||
meadowhill
|
||||
mesocolumn
|
||||
mh-magazine-lite
|
||||
midnightcity
|
||||
minimatica
|
||||
minimize
|
||||
mixfolio
|
||||
mn-flow
|
||||
modern-estate
|
||||
mon-cahier
|
||||
monaco
|
||||
montezuma
|
||||
multipurpose
|
||||
my-depressive
|
||||
my-world-with-grass-and-dew
|
||||
mystique
|
||||
narga
|
||||
multiloquent
|
||||
mywiki
|
||||
neuro
|
||||
newp
|
||||
newgamer
|
||||
newpro
|
||||
next-saturday
|
||||
nictitate
|
||||
omega
|
||||
one-page
|
||||
onetone
|
||||
openstrap
|
||||
opulus-sombre
|
||||
origami
|
||||
origin
|
||||
oxygen
|
||||
p2
|
||||
p2-categories
|
||||
padhang
|
||||
pagelines
|
||||
parabola
|
||||
parallax
|
||||
parament
|
||||
path
|
||||
phonix
|
||||
photographic
|
||||
photolistic
|
||||
photologger
|
||||
pilcrow
|
||||
pilot-fish
|
||||
pinbin
|
||||
pinboard
|
||||
pink-touch-2
|
||||
pitch
|
||||
platform
|
||||
point
|
||||
portfolio-press
|
||||
pr-news
|
||||
prana
|
||||
preference-lite
|
||||
preus
|
||||
primo-lite
|
||||
promax
|
||||
quark
|
||||
r2d2
|
||||
radiant
|
||||
radiate
|
||||
raindrops
|
||||
rambo
|
||||
raptor
|
||||
raven
|
||||
response
|
||||
redesign
|
||||
responsive
|
||||
restaurante
|
||||
restaurateur
|
||||
retro
|
||||
road-fighter
|
||||
ryu
|
||||
restimpo
|
||||
retention
|
||||
reviewgine-affiliate
|
||||
ridizain
|
||||
sampression-lite
|
||||
semper-fi-lite
|
||||
sensitive
|
||||
sequel
|
||||
serene
|
||||
shprink-one
|
||||
silverclean-lite
|
||||
simple-and-clean
|
||||
shopping
|
||||
simple-catch
|
||||
simpleo
|
||||
simplicity-lite
|
||||
simplify
|
||||
simply-vision
|
||||
singl
|
||||
sixteen
|
||||
skt-full-width
|
||||
sliding-door
|
||||
small-business
|
||||
smpl-skeleton
|
||||
snaps
|
||||
snapshot
|
||||
snowblind
|
||||
socially-awkward
|
||||
sneak-lite
|
||||
socialize-lite
|
||||
spacious
|
||||
spartan
|
||||
spasalon
|
||||
spine
|
||||
sporty
|
||||
spun
|
||||
squirrel
|
||||
startupwp
|
||||
stairway
|
||||
stargazer
|
||||
start-point
|
||||
steira
|
||||
strapvert
|
||||
striker
|
||||
storefront-paper
|
||||
story
|
||||
suevafree
|
||||
suffusion
|
||||
suits
|
||||
sukelius-magazine
|
||||
sugar-and-spice
|
||||
sundance
|
||||
sunny-blue-sky
|
||||
sunrain
|
||||
sunspot
|
||||
superhero
|
||||
supernova
|
||||
surfarama
|
||||
sweet-tech
|
||||
swift-basic
|
||||
tampa
|
||||
target
|
||||
tanzanite
|
||||
teal
|
||||
tempera
|
||||
temptation
|
||||
terrifico
|
||||
tesla
|
||||
the-bootstrap
|
||||
the-newswire
|
||||
thematic
|
||||
themia-lite
|
||||
theron-lite
|
||||
tiga
|
||||
timeturner
|
||||
tiny-forge
|
||||
tonal
|
||||
tonic
|
||||
toolbox
|
||||
travel-blogger
|
||||
travelify
|
||||
tribbiani
|
||||
twentyeleven
|
||||
twentyfourteen
|
||||
twentyten
|
||||
twentythirteen
|
||||
twentytwelve
|
||||
unique
|
||||
typal-makewp005
|
||||
unite
|
||||
untitled
|
||||
uptown
|
||||
uu-2014
|
||||
vantage
|
||||
venom
|
||||
viper
|
||||
virtue
|
||||
vision
|
||||
visitpress
|
||||
visual
|
||||
vortex
|
||||
voyage
|
||||
vryn-restaurant
|
||||
ward
|
||||
weaver-ii
|
||||
wordpost
|
||||
wilson
|
||||
wp-creativix
|
||||
wp-flatthirteen
|
||||
wp-knowledge-base
|
||||
wp-opulus
|
||||
xin-magazine
|
||||
wp-simple
|
||||
wpchimp-countdown
|
||||
writr
|
||||
x2
|
||||
yoko
|
||||
zalive
|
||||
zbench
|
||||
zeebizzcard
|
||||
zeebusiness
|
||||
zeedynamic
|
||||
zeeflow
|
||||
zeefocus
|
||||
zeemagazine
|
||||
zeeminty
|
||||
zeenews
|
||||
zeenoble
|
||||
zeestyle
|
||||
zeesynergie
|
||||
zeetasty
|
||||
zenon-lite
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -115,6 +115,7 @@ $wp-plugins$/islidex/js/timthumb.php
|
||||
$wp-plugins$/islidex/js/timthumb.phpthumb.php
|
||||
$wp-plugins$/islidex/js/timthumb.phptimthumb.php
|
||||
$wp-plugins$/jquery-slider-for-featured-content/scripts/timthumb.php
|
||||
$wp-plugins$/js-multihotel/includes/timthumb.php
|
||||
$wp-plugins$/kc-related-posts-by-category/timthumb.php
|
||||
$wp-plugins$/kino-gallery/timthumb.php
|
||||
$wp-plugins$/lisl-last-image-slider/timthumb.php
|
||||
|
||||
36
data/user-agents.txt
Normal file
36
data/user-agents.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
# Windows
|
||||
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5
|
||||
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.24 Safari/535.1
|
||||
Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E)
|
||||
Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
|
||||
Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1
|
||||
Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0
|
||||
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1
|
||||
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)
|
||||
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
|
||||
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0)
|
||||
Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00
|
||||
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5
|
||||
|
||||
# MAC
|
||||
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13
|
||||
Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15
|
||||
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
|
||||
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3
|
||||
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3
|
||||
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1
|
||||
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10
|
||||
|
||||
# Linux
|
||||
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1
|
||||
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24
|
||||
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9
|
||||
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0
|
||||
Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0
|
||||
Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00
|
||||
Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
<xs:simpleType name="stringtype">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:whiteSpace value="preserve" />
|
||||
<xs:minLength value="1" />
|
||||
<xs:pattern value="[^\s].+[^\s]|[^\s]"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
@@ -38,6 +40,7 @@
|
||||
<xs:enumeration value="CSRF"/>
|
||||
<xs:enumeration value="SSRF"/>
|
||||
<xs:enumeration value="AUTHBYPASS"/>
|
||||
<xs:enumeration value="BYPASS"/>
|
||||
<xs:enumeration value="FPD"/>
|
||||
<xs:enumeration value="XXE"/>
|
||||
</xs:restriction>
|
||||
|
||||
@@ -10,65 +10,104 @@
|
||||
<wp-versions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="wp_versions.xsd">
|
||||
|
||||
<file src="wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js">
|
||||
<hash md5="5d01c0e812cdcd6356b78ee0cb4e5426">
|
||||
<version>3.7.1</version>
|
||||
<file src="readme.html">
|
||||
<hash md5="84b54c54aa48ae72e633685c17e67457">
|
||||
<version>3.9</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/jquery/jquery.form.js">
|
||||
<hash md5="e5afd8e41d2ec22c19932b068cd90a71">
|
||||
<version>3.7</version>
|
||||
<hash md5="c6de8fc70a18be7e5c36198cd0f99a64">
|
||||
<version>3.8.3</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-admin/js/common.js">
|
||||
<hash md5="03eaffeef39119f0523a49c7f9767f3b">
|
||||
<hash md5="e01a2663475f6a7a8363a7c75a73fe23">
|
||||
<version>3.8.2</version>
|
||||
</hash>
|
||||
<hash md5="0d0eb101038124a108f608d419387b92">
|
||||
<version>3.8.1</version>
|
||||
</hash>
|
||||
<hash md5="38ee273095b8f25b9ffd5ce5018fc4f0">
|
||||
<version>3.8</version>
|
||||
</hash>
|
||||
<hash md5="813e06052daa0692036e60d76d7141d3">
|
||||
<version>3.7.3</version>
|
||||
</hash>
|
||||
<hash md5="b3a05c7a344c2f53cb6b680fd65a91e8">
|
||||
<version>3.7.2</version>
|
||||
</hash>
|
||||
<hash md5="e82f4fe7d3c1166afb4c00856b875f16">
|
||||
<version>3.6.1</version>
|
||||
</hash>
|
||||
<hash md5="4516252d47a73630280869994d510180">
|
||||
<version>3.3</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/jquery/jquery.js">
|
||||
<hash md5="9dcde2d5e8aeda556a0c52239fa2f44c">
|
||||
<hash md5="477f1e652f31dae76a38e3559c91deb9">
|
||||
<version>3.6</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/tinymce/tiny_mce.js">
|
||||
<hash md5="eddb5fda74d41dbdac018167536d8d53">
|
||||
<hash md5="caf7946275c3e885419b1d36b22cb5f3">
|
||||
<version>3.5.2</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="6e79ab6d786c5c95920064add33ee599">
|
||||
<hash md5="05d50a04ef19bd4b0a280362469bf22f">
|
||||
<version>3.5.1</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="55cd8e5ceca9c1763b1401164d70df50">
|
||||
<hash md5="066cfc0f9b29ae6d491aa342ebfb1b71">
|
||||
<version>3.5</version>
|
||||
</hash>
|
||||
<hash md5="36b2b72a0f22138a921a38db890d18c1">
|
||||
<version>3.3.3</version>
|
||||
</hash>
|
||||
<hash md5="628419c327ca5ed8685ae3af6f753eb8">
|
||||
<version>3.3.2</version>
|
||||
</hash>
|
||||
<hash md5="c1ed266e26a829b772362d5135966bc3">
|
||||
<version>3.3.1</version>
|
||||
</hash>
|
||||
<hash md5="9ea06ab0184049bf4ea2410bf51ce402">
|
||||
<version>3.0</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/wp-lists.js">
|
||||
<hash md5="46e1341cd4ea49f31046f7d7962adc7f">
|
||||
<file src="wp-includes/css/buttons-rtl.css">
|
||||
<hash md5="d24d1d1eb3a4b9a4998e4df1761f8b9e">
|
||||
<version>3.9</version>
|
||||
</hash>
|
||||
<hash md5="71c13ab1693b45fb3d7712e540c4dfe0">
|
||||
<version>3.8</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/tinymce/wp-tinymce.js.gz">
|
||||
<!-- Note: 3.7.1 has no unique file (the hash below is the same than the 3.7.2) -->
|
||||
<hash md5="44d281b0d84cc494e2b095a6d2202f4d">
|
||||
<version>3.7.1</version>
|
||||
</hash>
|
||||
<hash md5="b0bcf8091516db358ee9c833afd73175">
|
||||
<version>3.7</version>
|
||||
</hash>
|
||||
<hash md5="cf4bbd562430a9bcbe735062be851be1">
|
||||
<version>3.6.1</version>
|
||||
</hash>
|
||||
<hash md5="42ce18e88f1c21d4e991fcd431bcb606">
|
||||
<version>3.6</version>
|
||||
</hash>
|
||||
<hash md5="a58dd12608659503cf087e879e720354">
|
||||
<version>3.5.2</version>
|
||||
</hash>
|
||||
<hash md5="55c80a4794624ce9b94aa3631ad46c0b">
|
||||
<version>3.5.1</version>
|
||||
</hash>
|
||||
<hash md5="8e529a971610d7ebe7851339c5cb3d67">
|
||||
<version>3.5</version>
|
||||
</hash>
|
||||
<hash md5="ff19e44be975f89b647274d85b70f821">
|
||||
<version>3.4.2</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/customize-preview.js">
|
||||
<hash md5="617d9fd858e117c7d1d087be168b5643">
|
||||
<file src="wp-admin/js/customize-controls.js">
|
||||
<hash md5="aa0d38bd6f590ad8c3126074145b1bf1">
|
||||
<version>3.4.1</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/customize-preview.js">
|
||||
<hash md5="da36bc2dfcb13350c799b62de68dfa4b">
|
||||
<version>3.4</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="a8a259fc5197a78ffe62d6be38dc52f8">
|
||||
<version>3.4-beta4</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/js/plupload/plupload.js">
|
||||
@@ -77,27 +116,19 @@
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
|
||||
<file src="$wp-content$/themes/twentyeleven/style.css">
|
||||
|
||||
<!-- same md5 for 3.3.2 -->
|
||||
<hash md5="030d3bac906ba69e9fbc99c5bac54a8e">
|
||||
<version>3.3.1</version>
|
||||
<file src="wp-admin/js/common.js">
|
||||
<hash md5="4516252d47a73630280869994d510180">
|
||||
<version>3.3</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-admin/js/wp-fullscreen.js">
|
||||
|
||||
<hash md5="5675f7793f171b6424bf72f9d7bf4d9a">
|
||||
<version>3.2.1</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="7b423e0b7c9221092737ad5271d09863">
|
||||
<version>3.2</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
<file src="wp-includes/css/admin-bar.css">
|
||||
@@ -106,118 +137,82 @@
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
|
||||
<file src="$wp-content$/themes/twentyten/style.css">
|
||||
|
||||
<hash md5="6211e2ac1463bf99e98f28ab63e47c54">
|
||||
<version>3.0</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="$wp-plugins$/akismet/readme.txt">
|
||||
|
||||
<hash md5="4d5e52da417aa0101054bd41e6243389">
|
||||
<version>2.8.6</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="58e086dea9d24ed074fe84ba87386c69">
|
||||
<version>2.8.5</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="48c52025b5f28731e9a0c864c189c2e7">
|
||||
<version>2.8.2</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-includes/js/wp-ajax-response.js">
|
||||
|
||||
<hash md5="0289d1c13821599764774d55516ab81a">
|
||||
<version>2.7.1</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-includes/js/thickbox/thickbox.css">
|
||||
|
||||
<hash md5="9c2bd2be0893adbe02a0f864526734c2">
|
||||
<version>2.7</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin.js">
|
||||
|
||||
<hash md5="5b140ddf0f08034402ae78b31d8a1a28">
|
||||
<version>2.6</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-includes/js/tinymce/themes/advanced/js/image.js">
|
||||
|
||||
<hash md5="088245408531c58bb52cc092294cc384">
|
||||
<version>2.5.1</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-includes/js/tinymce/themes/advanced/js/link.js">
|
||||
|
||||
<hash md5="19c6f3118728c38eb7779aab4847d2d9">
|
||||
<version>2.5</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-includes/js/wp-ajax.js">
|
||||
|
||||
<hash md5="c5dbce0c3232c477033e0ce486c62755">
|
||||
<version>2.2</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="$wp-content$/themes/default/style.css">
|
||||
|
||||
<hash md5="e44545f529a54de88209ce588676231c">
|
||||
<version>2.0.1</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="f786f66d3a40846aa22dcdfeb44fa562">
|
||||
<version>2.0</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
|
||||
<file src="wp-layout.css">
|
||||
|
||||
<hash md5="7140e06c00ed03d2bb3dad7672557510">
|
||||
<version>1.2.1</version>
|
||||
</hash>
|
||||
|
||||
<hash md5="1bcc9253506c067eb130c9fc4f211a2f">
|
||||
<version>1.2-delta</version>
|
||||
</hash>
|
||||
</file>
|
||||
|
||||
|
||||
<file src="layout2b.css">
|
||||
|
||||
<hash md5="baec6b6ccbf71d8dced9f1bf67c751e1">
|
||||
<version>0.71-gold</version>
|
||||
</hash>
|
||||
|
||||
</file>
|
||||
|
||||
</wp-versions>
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
<xs:simpleType name="stringtype">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:whiteSpace value="preserve" />
|
||||
<xs:minLength value="1" />
|
||||
<xs:pattern value="[^\s].+[^\s]|[^\s]"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
|
||||
2975
data/wp_vulns.xml
2975
data/wp_vulns.xml
File diff suppressed because it is too large
Load Diff
40
dev/pre-commit-hook.rb
Executable file
40
dev/pre-commit-hook.rb
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# ln -sf /Users/xxx/wpscan/dev/pre-commit-hook.rb /Users/xxx/wpscan/.git/hooks/pre-commit
|
||||
|
||||
require 'pty'
|
||||
html_path = 'rspec_results.html'
|
||||
|
||||
begin
|
||||
PTY.spawn( "rspec spec --format h > #{html_path}" ) do |stdin, stdout, pid|
|
||||
begin
|
||||
stdin.each { |line| print line }
|
||||
rescue Errno::EIO => e
|
||||
puts "Error: #{e.to.s}"
|
||||
return 1
|
||||
end
|
||||
end
|
||||
rescue PTY::ChildExited
|
||||
puts 'Child process exit!'
|
||||
end
|
||||
|
||||
# find out if there were any errors
|
||||
html = open(html_path).read
|
||||
examples = html.match(/(\d+) examples/)[0].to_i rescue 0
|
||||
errors = html.match(/(\d+) errors/)[0].to_i rescue 0
|
||||
if errors == 0 then
|
||||
errors = html.match(/(\d+) failure/)[0].to_i rescue 0
|
||||
end
|
||||
pending = html.match(/(\d+) pending/)[0].to_i rescue 0
|
||||
|
||||
if errors.zero?
|
||||
puts "0 failed! #{examples} run, #{pending} pending"
|
||||
sleep 1
|
||||
exit 0
|
||||
else
|
||||
puts "\aCOMMIT FAILED!!"
|
||||
puts "View your rspec results at #{File.expand_path(html_path)}"
|
||||
puts
|
||||
puts "#{errors} failed! #{examples} run, #{pending} pending"
|
||||
exit 1
|
||||
end
|
||||
18
example.conf.json
Normal file
18
example.conf.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0",
|
||||
|
||||
/* Uncomment the "proxy" line to use the proxy
|
||||
SOCKS proxies (4, 4A, 5) are supported, ie : "proxy": "socks5://127.0.0.1:9000"
|
||||
If you do not specify the protocol, http will be used
|
||||
*/
|
||||
//"proxy": "127.0.0.1:3128",
|
||||
//"proxy_auth": "username:password",
|
||||
|
||||
"cache_ttl": 600, // 10 minutes, at this time the cache is cleaned before each scan. If this value is set to 0, the cache will be disabled
|
||||
|
||||
"request_timeout": 2000, // 2s
|
||||
|
||||
"connect_timeout": 1000, // 1s
|
||||
|
||||
"max_threads": 20
|
||||
}
|
||||
@@ -9,12 +9,10 @@ class Browser
|
||||
include Browser::Options
|
||||
|
||||
OPTIONS = [
|
||||
:available_user_agents,
|
||||
:basic_auth,
|
||||
:cache_ttl,
|
||||
:max_threads,
|
||||
:user_agent,
|
||||
:user_agent_mode,
|
||||
:proxy,
|
||||
:proxy_auth,
|
||||
:request_timeout,
|
||||
@@ -23,16 +21,22 @@ class Browser
|
||||
|
||||
@@instance = nil
|
||||
|
||||
attr_reader :hydra, :config_file, :cache_dir
|
||||
attr_reader :hydra, :cache_dir
|
||||
|
||||
attr_accessor :referer
|
||||
|
||||
# @param [ Hash ] options
|
||||
#
|
||||
# @return [ Browser ]
|
||||
def initialize(options = {})
|
||||
@config_file = options[:config_file] || CONF_DIR + '/browser.conf.json'
|
||||
@cache_dir = options[:cache_dir] || CACHE_DIR + '/browser'
|
||||
|
||||
load_config
|
||||
# sets browser defaults
|
||||
browser_defaults
|
||||
# load config file
|
||||
conf = options[:config_file]
|
||||
load_config(conf) if conf
|
||||
# overrides defaults with user supplied values (overwrite values from config)
|
||||
override_config(options)
|
||||
|
||||
unless @hydra
|
||||
@@ -61,6 +65,20 @@ class Browser
|
||||
@@instance = nil
|
||||
end
|
||||
|
||||
#
|
||||
# sets browser default values
|
||||
#
|
||||
def browser_defaults
|
||||
@max_threads = 20
|
||||
# 10 minutes, at this time the cache is cleaned before each scan. If this value is set to 0, the cache will be disabled
|
||||
@cache_ttl = 600
|
||||
# 2s
|
||||
@request_timeout = 2000
|
||||
# 1s
|
||||
@connect_timeout = 1000
|
||||
@user_agent = "WPScan v#{WPSCAN_VERSION} (http://wpscan.org)"
|
||||
end
|
||||
|
||||
#
|
||||
# If an option was set but is not in the new config_file
|
||||
# it's value is kept
|
||||
@@ -69,21 +87,20 @@ class Browser
|
||||
#
|
||||
# @return [ void ]
|
||||
def load_config(config_file = nil)
|
||||
@config_file = config_file || @config_file
|
||||
|
||||
if File.symlink?(@config_file)
|
||||
if File.symlink?(config_file)
|
||||
raise '[ERROR] Config file is a symlink.'
|
||||
else
|
||||
data = JSON.parse(File.read(@config_file))
|
||||
data = JSON.parse(File.read(config_file))
|
||||
end
|
||||
|
||||
OPTIONS.each do |option|
|
||||
option_name = option.to_s
|
||||
|
||||
unless data[option_name].nil?
|
||||
self.send(:"#{option_name}=", data[option_name])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# @param [ String ] url
|
||||
@@ -101,7 +118,7 @@ class Browser
|
||||
params = Browser.append_params_header_field(
|
||||
params,
|
||||
'User-Agent',
|
||||
self.user_agent
|
||||
@user_agent
|
||||
)
|
||||
|
||||
if @proxy
|
||||
@@ -120,18 +137,15 @@ class Browser
|
||||
)
|
||||
end
|
||||
|
||||
if @request_timeout
|
||||
params = params.merge(timeout: @request_timeout)
|
||||
end
|
||||
|
||||
if @connect_timeout
|
||||
params = params.merge(connecttimeout: @connect_timeout)
|
||||
end
|
||||
params.merge!(referer: referer)
|
||||
params.merge!(timeout: @request_timeout) if @request_timeout
|
||||
params.merge!(connecttimeout: @connect_timeout) if @connect_timeout
|
||||
|
||||
# Used to enable the cache system if :cache_ttl > 0
|
||||
unless params.has_key?(:cache_ttl)
|
||||
params = params.merge(cache_ttl: @cache_ttl)
|
||||
end
|
||||
params.merge!(cache_ttl: @cache_ttl) unless params.has_key?(:cache_ttl)
|
||||
|
||||
# Prevent infinite self redirection
|
||||
params.merge!(maxredirs: 3) unless params.has_key?(:maxredirs)
|
||||
|
||||
# Disable SSL-Certificate checks
|
||||
params.merge!(ssl_verifypeer: false)
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
class Browser
|
||||
module Options
|
||||
|
||||
USER_AGENT_MODES = %w{ static semi-static random }
|
||||
|
||||
attr_accessor :available_user_agents, :cache_ttl, :request_timeout, :connect_timeout
|
||||
attr_reader :basic_auth, :user_agent_mode, :proxy, :proxy_auth
|
||||
attr_accessor :cache_ttl, :request_timeout, :connect_timeout
|
||||
attr_reader :basic_auth, :proxy, :proxy_auth
|
||||
attr_writer :user_agent
|
||||
|
||||
# Sets the Basic Authentification credentials
|
||||
@@ -41,42 +39,6 @@ class Browser
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the user_agent_mode, which can be one of the following:
|
||||
# static: The UA is defined by the user, and will be the same in each requests
|
||||
# semi-static: The UA is randomly chosen at the first request, and will not change
|
||||
# random: UA randomly chosen each request
|
||||
#
|
||||
# UA are from @available_user_agents
|
||||
#
|
||||
# @param [ String ] ua_mode
|
||||
#
|
||||
# @return [ void ]
|
||||
def user_agent_mode=(ua_mode)
|
||||
ua_mode ||= 'static'
|
||||
|
||||
if USER_AGENT_MODES.include?(ua_mode)
|
||||
@user_agent_mode = ua_mode
|
||||
# For semi-static user agent mode, the user agent has to
|
||||
# be nil the first time (it will be set with the getter)
|
||||
@user_agent = nil if ua_mode === 'semi-static'
|
||||
else
|
||||
raise "Unknow user agent mode : '#{ua_mode}'"
|
||||
end
|
||||
end
|
||||
|
||||
# @return [ String ] The user agent, according to the user_agent_mode
|
||||
def user_agent
|
||||
case @user_agent_mode
|
||||
when 'semi-static'
|
||||
unless @user_agent
|
||||
@user_agent = @available_user_agents.sample
|
||||
end
|
||||
when 'random'
|
||||
@user_agent = @available_user_agents.sample
|
||||
end
|
||||
@user_agent
|
||||
end
|
||||
|
||||
# Sets the proxy
|
||||
# Accepted format:
|
||||
# [protocol://]host:post
|
||||
|
||||
@@ -18,8 +18,8 @@ class CacheFileStore
|
||||
# YAML is Human Readable, contrary to Marshal which store in a binary format
|
||||
# Marshal does not need any "require"
|
||||
def initialize(storage_path, serializer = Marshal)
|
||||
@storage_path = File.expand_path(storage_path)
|
||||
@serializer = serializer
|
||||
@storage_path = File.expand_path(storage_path + '/' + storage_dir)
|
||||
@serializer = serializer
|
||||
|
||||
# File.directory? for ruby <= 1.9 otherwise,
|
||||
# it makes more sense to do Dir.exist? :/
|
||||
@@ -58,4 +58,11 @@ class CacheFileStore
|
||||
File::join(@storage_path, key)
|
||||
end
|
||||
|
||||
def storage_dir
|
||||
time = Time.now
|
||||
random = (0...8).map { (65 + rand(26)).chr }.join
|
||||
|
||||
Digest::MD5.hexdigest("#{time}#{random}")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
class Vulnerabilities < Array
|
||||
module Output
|
||||
|
||||
def output
|
||||
def output(verbose = false)
|
||||
self.each do |v|
|
||||
v.output
|
||||
v.output(verbose)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ class WpItems < Array
|
||||
hydra = browser.hydra
|
||||
targets = targets_items(wp_target, options)
|
||||
progress_bar = progress_bar(targets.size, options)
|
||||
queue_count = 0
|
||||
exist_options = {
|
||||
error_404_hash: wp_target.error_404_hash,
|
||||
homepage_hash: wp_target.homepage_hash,
|
||||
@@ -43,8 +44,16 @@ class WpItems < Array
|
||||
end
|
||||
|
||||
hydra.queue(request)
|
||||
queue_count += 1
|
||||
|
||||
if queue_count >= browser.max_threads
|
||||
hydra.run
|
||||
queue_count = 0
|
||||
puts "Sent #{browser.max_threads} requests ..." if options[:verbose]
|
||||
end
|
||||
end
|
||||
|
||||
# run the remaining requests
|
||||
hydra.run
|
||||
results.sort!
|
||||
results # can't just return results.sort because the #sort returns an array, and we want a WpItems
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
class WpItems < Array
|
||||
module Output
|
||||
|
||||
def output
|
||||
self.each { |item| item.output }
|
||||
def output(verbose = false)
|
||||
self.each { |item| item.output(verbose) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -32,8 +32,9 @@ LOCAL_FILES_FILE = DATA_DIR + '/local_vulnerable_files.xml'
|
||||
VULNS_XSD = DATA_DIR + '/vuln.xsd'
|
||||
WP_VERSIONS_XSD = DATA_DIR + '/wp_versions.xsd'
|
||||
LOCAL_FILES_XSD = DATA_DIR + '/local_vulnerable_files.xsd'
|
||||
USER_AGENTS_FILE = DATA_DIR + '/user-agents.txt'
|
||||
|
||||
WPSCAN_VERSION = '2.2'
|
||||
WPSCAN_VERSION = '2.4'
|
||||
|
||||
$LOAD_PATH.unshift(LIB_DIR)
|
||||
$LOAD_PATH.unshift(WPSCAN_LIB_DIR)
|
||||
@@ -63,6 +64,14 @@ end
|
||||
|
||||
require_files_from_directory(COMMON_LIB_DIR, '**/*.rb')
|
||||
|
||||
# Hook to check if the target if down during the scan
|
||||
# The target is considered down after 10 requests with status = 0
|
||||
down = 0
|
||||
Typhoeus.on_complete do |response|
|
||||
down += 1 if response.code == 0
|
||||
fail 'The target seems to be down' if down >= 10
|
||||
end
|
||||
|
||||
# Add protocol
|
||||
def add_http_protocol(url)
|
||||
url =~ /^https?:/ ? url : "http://#{url}"
|
||||
@@ -97,13 +106,14 @@ def banner
|
||||
puts ' \\/ \\/ |_| |_____/ \\___|\\__,_|_| |_|'
|
||||
puts
|
||||
puts ' WordPress Security Scanner by the WPScan Team '
|
||||
# Alignment of the version (w & w/o the Revision)
|
||||
if REVISION
|
||||
puts " Version #{version}"
|
||||
else
|
||||
puts " Version #{version}"
|
||||
end
|
||||
puts ' Sponsored by the RandomStorm Open Source Initiative'
|
||||
puts ' @_WPScan_, @ethicalhack3r, @erwan_lr, @gbrindisi, @_FireFart_'
|
||||
puts ' @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_'
|
||||
puts '_______________________________________________________________'
|
||||
puts
|
||||
end
|
||||
@@ -177,3 +187,28 @@ end
|
||||
def count_file_lines(file)
|
||||
`wc -l #{file.shellescape}`.split[0].to_i
|
||||
end
|
||||
|
||||
# Truncates a string to a specific length and adds ... at the end
|
||||
def truncate(input, size, trailing = '...')
|
||||
size = size.to_i
|
||||
trailing ||= ''
|
||||
return input if input.nil? or size <= 0 or input.length <= size or
|
||||
trailing.length >= input.length or size-trailing.length-1 >= input.length
|
||||
return "#{input[0..size-trailing.length-1]}#{trailing}"
|
||||
end
|
||||
|
||||
# Gets a random User-Agent
|
||||
#
|
||||
# @return [ String ] A random user-agent from data/user-agents.txt
|
||||
def get_random_user_agent
|
||||
user_agents = []
|
||||
f = File.open(USER_AGENTS_FILE, 'r')
|
||||
f.each_line do |line|
|
||||
# ignore comments
|
||||
next if line.empty? or line =~ /^\s*(#|\/\/)/
|
||||
user_agents << line.strip
|
||||
end
|
||||
f.close
|
||||
# return ransom user-agent
|
||||
user_agents.sample
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ require 'vulnerability/urls'
|
||||
|
||||
class Vulnerability
|
||||
include Vulnerability::Output
|
||||
include Vulnerability::Urls
|
||||
include Vulnerability::Urls
|
||||
|
||||
attr_accessor :title, :references, :type, :fixed_in
|
||||
|
||||
@@ -41,16 +41,16 @@ class Vulnerability
|
||||
#
|
||||
# @return [ Vulnerability ]
|
||||
def self.load_from_xml_node(xml_node)
|
||||
references = {}
|
||||
refs = xml_node.search('references')
|
||||
if refs
|
||||
references[:url] = refs.search('url').map(&:text)
|
||||
references[:cve] = refs.search('cve').map(&:text)
|
||||
references[:secunia] = refs.search('secunia').map(&:text)
|
||||
references[:osvdb] = refs.search('osvdb').map(&:text)
|
||||
references[:metasploit] = refs.search('metasploit').map(&:text)
|
||||
references[:exploitdb] = refs.search('exploitdb').map(&:text)
|
||||
end
|
||||
references = {}
|
||||
refs = xml_node.search('references')
|
||||
if refs
|
||||
references[:url] = refs.search('url').map(&:text)
|
||||
references[:cve] = refs.search('cve').map(&:text)
|
||||
references[:secunia] = refs.search('secunia').map(&:text)
|
||||
references[:osvdb] = refs.search('osvdb').map(&:text)
|
||||
references[:metasploit] = refs.search('metasploit').map(&:text)
|
||||
references[:exploitdb] = refs.search('exploitdb').map(&:text)
|
||||
end
|
||||
new(
|
||||
xml_node.search('title').text,
|
||||
xml_node.search('type').text,
|
||||
|
||||
@@ -4,16 +4,16 @@ class Vulnerability
|
||||
module Output
|
||||
|
||||
# output the vulnerability
|
||||
def output
|
||||
def output(verbose = false)
|
||||
puts ' |'
|
||||
puts ' | ' + red("* Title: #{title}")
|
||||
references.each do |key, urls|
|
||||
methodname = "url_#{key}"
|
||||
urls.each do |u|
|
||||
url = send(methodname, u)
|
||||
puts ' | ' + red("* Reference: #{url}") if url
|
||||
end
|
||||
end
|
||||
methodname = "url_#{key}"
|
||||
urls.each do |u|
|
||||
url = send(methodname, u)
|
||||
puts ' | ' + red("* Reference: #{url}") if url
|
||||
end
|
||||
end
|
||||
if !fixed_in.empty?
|
||||
puts " | * Fixed in: #{fixed_in}"
|
||||
end
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class Vulnerability
|
||||
module Urls
|
||||
# @return [ String ] The url to the metasploit module page
|
||||
def url_metasploit(module_path)
|
||||
# remove leading slash
|
||||
module_path = module_path.sub(/^\//, '')
|
||||
"http://www.metasploit.com/modules/#{module_path}"
|
||||
end
|
||||
module Urls
|
||||
# @return [ String ] The url to the metasploit module page
|
||||
def url_metasploit(module_path)
|
||||
# remove leading slash
|
||||
module_path = module_path.sub(/^\//, '')
|
||||
"http://www.metasploit.com/modules/#{module_path}"
|
||||
end
|
||||
|
||||
def url_url(url)
|
||||
url
|
||||
end
|
||||
def url_url(url)
|
||||
url
|
||||
end
|
||||
|
||||
def url_cve(cve)
|
||||
"http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-#{cve}"
|
||||
end
|
||||
def url_cve(cve)
|
||||
"http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-#{cve}"
|
||||
end
|
||||
|
||||
def url_osvdb(id)
|
||||
"http://osvdb.org/#{id}"
|
||||
end
|
||||
def url_osvdb(id)
|
||||
"http://osvdb.org/#{id}"
|
||||
end
|
||||
|
||||
def url_secunia(id)
|
||||
"http://secunia.com/advisories/#{id}"
|
||||
end
|
||||
def url_secunia(id)
|
||||
"http://secunia.com/advisories/#{id}"
|
||||
end
|
||||
|
||||
def url_exploitdb(id)
|
||||
"http://www.exploit-db.com/exploits/#{id}/"
|
||||
end
|
||||
def url_exploitdb(id)
|
||||
"http://www.exploit-db.com/exploits/#{id}/"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,7 +29,10 @@ class WpItem
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def exists_from_response?(response, options = {})
|
||||
if [200, 401, 403].include?(response.code)
|
||||
# 301 included as some items do a self-redirect
|
||||
# Redirects to the 404 and homepage should be ignored (unless dynamic content is used)
|
||||
# by the page hashes (error_404_hash & homepage_hash)
|
||||
if [200, 401, 403, 301].include?(response.code)
|
||||
if response.has_valid_hash?(options[:error_404_hash], options[:homepage_hash])
|
||||
if options[:exclude_content]
|
||||
unless response.body.match(options[:exclude_content])
|
||||
|
||||
@@ -4,21 +4,19 @@ class WpItem
|
||||
module Output
|
||||
|
||||
# @return [ Void ]
|
||||
def output
|
||||
def output(verbose = false)
|
||||
puts
|
||||
puts " | Name: #{self}" #this will also output the version number if detected
|
||||
puts " | Location: #{url}"
|
||||
#puts " | WordPress: #{wordpress_url}" if wordpress_org_item?
|
||||
puts ' | Directory listing enabled: Yes' if has_directory_listing?
|
||||
puts " | Readme: #{readme_url}" if has_readme?
|
||||
puts " | Changelog: #{changelog_url}" if has_changelog?
|
||||
puts " | " + red('[!]') + " Directory listing is enabled: #{url}" if has_directory_listing?
|
||||
puts " | " + red('[!]') + " An error_log file has been found: #{error_log_url}" if has_error_log?
|
||||
|
||||
additional_output(verbose) if respond_to?(:additional_output)
|
||||
|
||||
vulnerabilities.output
|
||||
|
||||
if has_error_log?
|
||||
puts ' | ' + red('[!]') + " An error_log file has been found : #{error_log_url}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ class WpItem
|
||||
# @return [ String ]
|
||||
def to_s
|
||||
item_version = self.version
|
||||
"#@name#{' v' + item_version.strip if item_version}"
|
||||
"#@name#{' - v' + item_version.strip if item_version}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,16 +3,28 @@
|
||||
require 'wp_theme/findable'
|
||||
require 'wp_theme/versionable'
|
||||
require 'wp_theme/vulnerable'
|
||||
require 'wp_theme/info'
|
||||
require 'wp_theme/output'
|
||||
require 'wp_theme/childtheme'
|
||||
|
||||
class WpTheme < WpItem
|
||||
extend WpTheme::Findable
|
||||
include WpTheme::Versionable
|
||||
include WpTheme::Vulnerable
|
||||
include WpTheme::Info
|
||||
include WpTheme::Output
|
||||
include WpTheme::Childtheme
|
||||
|
||||
attr_writer :style_url
|
||||
|
||||
def allowed_options; super << :style_url end
|
||||
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
|
||||
parse_style
|
||||
end
|
||||
|
||||
# Sets the @uri
|
||||
#
|
||||
# @param [ URI ] target_base_uri The URI of the wordpress blog
|
||||
|
||||
33
lib/common/models/wp_theme/childtheme.rb
Normal file
33
lib/common/models/wp_theme/childtheme.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpTheme < WpItem
|
||||
module Childtheme
|
||||
|
||||
def is_child_theme?
|
||||
return true unless @theme_template.nil?
|
||||
false
|
||||
end
|
||||
|
||||
def get_parent_theme_style_url
|
||||
if is_child_theme?
|
||||
return style_url.sub("/#{name}/style.css", "/#@theme_template/style.css")
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def get_parent_theme
|
||||
if is_child_theme?
|
||||
base_url = @uri.clone
|
||||
base_url.path = base_url.path.sub(/(?<url>.*\/)#{Regexp.escape(@wp_content_dir)}\/.+/, '\k<url>')
|
||||
return WpTheme.new(base_url,
|
||||
{
|
||||
name: @theme_template,
|
||||
style_url: get_parent_theme_style_url,
|
||||
wp_content_dir: @wp_content_dir
|
||||
})
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -43,8 +43,6 @@ class WpTheme < WpItem
|
||||
end
|
||||
end
|
||||
|
||||
# http://code.google.com/p/wpscan/issues/detail?id=141
|
||||
#
|
||||
# @param [ URI ] target_uri
|
||||
#
|
||||
# @return [ WpTheme ]
|
||||
|
||||
34
lib/common/models/wp_theme/info.rb
Normal file
34
lib/common/models/wp_theme/info.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpTheme < WpItem
|
||||
module Info
|
||||
|
||||
attr_reader :theme_name, :theme_uri, :theme_description,
|
||||
:theme_author, :theme_author_uri, :theme_template,
|
||||
:theme_license, :theme_license_uri, :theme_tags,
|
||||
:theme_text_domain
|
||||
|
||||
def parse_style
|
||||
style = Browser.get(style_url).body
|
||||
@theme_name = parse_style_tag(style, 'Theme Name')
|
||||
@theme_uri = parse_style_tag(style, 'Theme URI')
|
||||
@theme_description = parse_style_tag(style, 'Description')
|
||||
@theme_author = parse_style_tag(style, 'Author')
|
||||
@theme_author_uri = parse_style_tag(style, 'Author URI')
|
||||
@theme_template = parse_style_tag(style, 'Template')
|
||||
@theme_license = parse_style_tag(style, 'License')
|
||||
@theme_license_uri = parse_style_tag(style, 'License URI')
|
||||
@theme_tags = parse_style_tag(style, 'Tags')
|
||||
@theme_text_domain = parse_style_tag(style, 'Text Domain')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse_style_tag(style, tag)
|
||||
value = style[/^\s*#{Regexp.escape(tag)}:\s*(.*)/i, 1]
|
||||
return value.strip if value
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
23
lib/common/models/wp_theme/output.rb
Normal file
23
lib/common/models/wp_theme/output.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpTheme
|
||||
module Output
|
||||
|
||||
# @return [ Void ]
|
||||
def additional_output(verbose = false)
|
||||
puts " | Style URL: #{style_url}"
|
||||
puts " | Theme Name: #@theme_name" if @theme_name
|
||||
puts " | Theme URI: #@theme_uri" if @theme_uri
|
||||
theme_desc = verbose ? @theme_description : truncate(@theme_description, 100)
|
||||
puts " | Description: #{theme_desc}"
|
||||
puts " | Author: #@theme_author" if @theme_author
|
||||
puts " | Author URI: #@theme_author_uri" if @theme_author_uri
|
||||
puts " | Template: #@theme_template" if @theme_template and verbose
|
||||
puts " | License: #@theme_license" if @theme_license and verbose
|
||||
puts " | License URI: #@theme_license_uri" if @theme_license_uri and verbose
|
||||
puts " | Tags: #@theme_tags" if @theme_tags and verbose
|
||||
puts " | Text Domain: #@theme_text_domain" if @theme_text_domain and verbose
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,7 @@ class WpTheme < WpItem
|
||||
|
||||
def version
|
||||
unless @version
|
||||
@version = Browser.get(style_url).body[%r{Version:\s([^\s]+)}i, 1]
|
||||
@version = Browser.get(style_url).body[%r{Version:\s*([^\s]+)}i, 1]
|
||||
|
||||
# Get Version from readme.txt
|
||||
@version ||= super
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
require 'wp_timthumb/versionable'
|
||||
require 'wp_timthumb/existable'
|
||||
require 'wp_timthumb/output'
|
||||
require 'wp_timthumb/vulnerable'
|
||||
|
||||
class WpTimthumb < WpItem
|
||||
include WpTimthumb::Versionable
|
||||
include WpTimthumb::Existable
|
||||
include WpTimthumb::Output
|
||||
include WpTimthumb::Vulnerable
|
||||
|
||||
# @param [ WpTimthumb ] other
|
||||
#
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
class WpTimthumb < WpItem
|
||||
module Output
|
||||
|
||||
def output
|
||||
puts ' | ' + red('[!]') + " #{self}"
|
||||
def output(verbose = false)
|
||||
puts " | #{vulnerable? ? red('[!] Vulnerable') : green('[i] Not Vulnerable')} #{self}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
9
lib/common/models/wp_timthumb/vulnerable.rb
Normal file
9
lib/common/models/wp_timthumb/vulnerable.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpTimthumb < WpItem
|
||||
module Vulnerable
|
||||
def vulnerable?
|
||||
VersionCompare.is_newer_or_same?(version, '1.34')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,7 +12,7 @@ class WpUser < WpItem
|
||||
# @return [ Array<Symbol> ]
|
||||
def allowed_options; [:id, :login, :display_name, :password] end
|
||||
|
||||
# @return [ URI ] The uri to the auhor page
|
||||
# @return [ URI ] The uri to the author page
|
||||
def uri
|
||||
if id
|
||||
return @uri.merge("?author=#{id}")
|
||||
@@ -23,14 +23,39 @@ class WpUser < WpItem
|
||||
|
||||
# @return [ String ]
|
||||
def login_url
|
||||
@uri.merge('wp-login.php').to_s
|
||||
unless @login_url
|
||||
@login_url = @uri.merge('wp-login.php').to_s
|
||||
|
||||
# Let's check if the login url is redirected (to https url for example)
|
||||
if redirection = redirection(@login_url)
|
||||
@login_url = redirection
|
||||
end
|
||||
end
|
||||
|
||||
@login_url
|
||||
end
|
||||
|
||||
def redirection(url)
|
||||
redirection = nil
|
||||
response = Browser.get(url)
|
||||
|
||||
if response.code == 301 || response.code == 302
|
||||
redirection = response.headers_hash['location']
|
||||
|
||||
# Let's check if there is a redirection in the redirection
|
||||
if other_redirection = redirection(redirection)
|
||||
redirection = other_redirection
|
||||
end
|
||||
end
|
||||
|
||||
redirection
|
||||
end
|
||||
|
||||
# @return [ String ]
|
||||
def to_s
|
||||
s = "#{id}"
|
||||
s += " | #{login}" if login
|
||||
s += " | #{display_name}" if display_name
|
||||
s << " | #{login}" if login
|
||||
s << " | #{display_name}" if display_name
|
||||
s
|
||||
end
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class WpVersion < WpItem
|
||||
#
|
||||
# @return [ WpVersion ]
|
||||
def find(target_uri, wp_content_dir, wp_plugins_dir, versions_xml)
|
||||
methods.grep(/find_from_/).each do |method|
|
||||
methods.grep(/^find_from_/).each do |method|
|
||||
|
||||
if method === :find_from_advanced_fingerprinting
|
||||
version = send(method, target_uri, wp_content_dir, wp_plugins_dir, versions_xml)
|
||||
@@ -190,8 +190,6 @@ class WpVersion < WpItem
|
||||
|
||||
# Attempts to find the WordPress version from the sitemap.xml file.
|
||||
#
|
||||
# See: http://code.google.com/p/wpscan/issues/detail?id=109
|
||||
#
|
||||
# @param [ URI ] target_uri
|
||||
#
|
||||
# @return [ String ] The version number
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
class WpVersion < WpItem
|
||||
module Output
|
||||
|
||||
def output
|
||||
def output(verbose = false)
|
||||
puts
|
||||
puts green('[+]') + " WordPress version #{self.number} identified from #{self.found_from}"
|
||||
|
||||
vulnerabilities = self.vulnerabilities
|
||||
|
||||
unless vulnerabilities.empty?
|
||||
puts
|
||||
puts red('[!]') + " #{vulnerabilities.size} vulnerabilities identified from the version number:"
|
||||
puts red('[!]') + " #{vulnerabilities.size} vulnerabilities identified from the version number"
|
||||
|
||||
vulnerabilities.output
|
||||
end
|
||||
|
||||
@@ -2,25 +2,14 @@
|
||||
|
||||
require 'common/cache_file_store'
|
||||
|
||||
# Implementaion of a cache_key (Typhoeus::Request#hash has too many options)
|
||||
module Typhoeus
|
||||
class Request
|
||||
module Cacheable
|
||||
def cache_key
|
||||
Digest::SHA2.hexdigest("#{url}-#{options[:body]}-#{options[:method]}")[0..32]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TyphoeusCache < CacheFileStore
|
||||
|
||||
def get(request)
|
||||
read_entry(request.cache_key)
|
||||
read_entry(request.hash.to_s)
|
||||
end
|
||||
|
||||
def set(request, response)
|
||||
write_entry(request.cache_key, response, request.cache_ttl)
|
||||
write_entry(request.hash.to_s, response, request.cache_ttl)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -22,5 +22,5 @@ class VersionCompare
|
||||
raise
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ class WebSite
|
||||
|
||||
def has_xml_rpc?
|
||||
response = Browser.get_and_follow_location(xml_rpc_url)
|
||||
response.body =~ %r{XML-RPC server accepts POST requests only}i
|
||||
response.body =~ %r{XML-RPC server accepts POST requests only}i
|
||||
end
|
||||
|
||||
# See http://www.hixie.ch/specs/pingback/pingback-1.0#TOC2.3
|
||||
@@ -71,7 +71,7 @@ class WebSite
|
||||
#
|
||||
# @return [ String ] The MD5 hash of the page
|
||||
def self.page_hash(page)
|
||||
page = Browser.get(page) unless page.is_a?(Typhoeus::Response)
|
||||
page = Browser.get(page, { followlocation: true, cache_ttl: 0 }) unless page.is_a?(Typhoeus::Response)
|
||||
|
||||
Digest::MD5.hexdigest(page.body.gsub(/<!--.*?-->/m, ''))
|
||||
end
|
||||
|
||||
@@ -29,6 +29,7 @@ class WpTarget < WebSite
|
||||
@multisite = nil
|
||||
|
||||
Browser.instance(options.merge(:max_threads => options[:threads]))
|
||||
Browser.instance.referer = url
|
||||
end
|
||||
|
||||
# check if the target website is
|
||||
@@ -38,6 +39,11 @@ class WpTarget < WebSite
|
||||
|
||||
response = Browser.get_and_follow_location(@uri.to_s)
|
||||
|
||||
# Note: in the future major WPScan version, change the user-agent to see
|
||||
# if the response is a 200 ?
|
||||
fail "The target is responding with a 403, this might be due to a WAF or a plugin\n" \
|
||||
'You should try to supply a valid user-agent via the --user-agent option' if response.code == 403
|
||||
|
||||
if response.body =~ /["'][^"']*\/wp-content\/[^"']*["']/i
|
||||
wordpress = true
|
||||
else
|
||||
@@ -93,7 +99,7 @@ class WpTarget < WebSite
|
||||
end
|
||||
# :nocov:
|
||||
|
||||
# The version is not yet considerated
|
||||
# The version is not yet considered
|
||||
#
|
||||
# @param [ String ] name
|
||||
# @param [ String ] version
|
||||
@@ -120,7 +126,7 @@ class WpTarget < WebSite
|
||||
end
|
||||
|
||||
# Script for replacing strings in wordpress databases
|
||||
# reveals databse credentials after hitting submit
|
||||
# reveals database credentials after hitting submit
|
||||
# http://interconnectit.com/124/search-and-replace-for-wordpress-databases/
|
||||
#
|
||||
# @return [ String ]
|
||||
|
||||
@@ -12,7 +12,6 @@ class WpTarget < WebSite
|
||||
end
|
||||
|
||||
# Checks if a login protection plugin is enabled
|
||||
# http://code.google.com/p/wpscan/issues/detail?id=111
|
||||
# return a WpPlugin object or nil if no one is found
|
||||
def login_protection_plugin
|
||||
unless @login_protection_plugin
|
||||
|
||||
@@ -83,6 +83,8 @@ def help
|
||||
puts '--exclude-content-based "<regexp or string>" Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied'
|
||||
puts ' You do not need to provide the regexp delimiters, but you must write the quotes (simple or double)'
|
||||
puts '--config-file | -c <config file> Use the specified config file'
|
||||
puts '--user-agent | -a <User-Agent> Use the specified User-Agent'
|
||||
puts '--random-agent | -r Use a random User-Agent'
|
||||
puts '--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not'
|
||||
puts '--wp-content-dir <wp content dir> WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed'
|
||||
puts '--wp-plugins-dir <wp plugins dir> Same thing than --wp-content-dir but for the plugins directory. If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed'
|
||||
@@ -93,7 +95,12 @@ def help
|
||||
puts '--wordlist | -w <wordlist> Supply a wordlist for the password bruter and do the brute.'
|
||||
puts '--threads | -t <number of threads> The number of threads to use when multi-threading requests. (will override the value from conf/browser.conf.json)'
|
||||
puts '--username | -U <username> Only brute force the supplied username.'
|
||||
puts '--cache-ttl <cache-ttl> Typhoeus cache TTL'
|
||||
puts '--request-timeout <request-timeout> Request Timeout'
|
||||
puts '--connect-timeout <connect-timeout> Connect Timeout'
|
||||
puts '--max-threads <max-threads> Maximum Threads'
|
||||
puts '--help | -h This help screen.'
|
||||
puts '--verbose | -v Verbose output.'
|
||||
puts '--batch Never ask for user input, use the default behaviour.'
|
||||
puts
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
class WpscanOptions
|
||||
|
||||
ACCESSOR_OPTIONS = [
|
||||
:batch,
|
||||
:enumerate_plugins,
|
||||
:enumerate_only_vulnerable_plugins,
|
||||
:enumerate_all_plugins,
|
||||
@@ -30,7 +31,13 @@ class WpscanOptions
|
||||
:exclude_content_based,
|
||||
:basic_auth,
|
||||
:debug_output,
|
||||
:version
|
||||
:version,
|
||||
:user_agent,
|
||||
:random_agent,
|
||||
:cache_ttl,
|
||||
:request_timeout,
|
||||
:connect_timeout,
|
||||
:max_threads
|
||||
]
|
||||
|
||||
attr_accessor *ACCESSOR_OPTIONS
|
||||
@@ -136,6 +143,10 @@ class WpscanOptions
|
||||
!to_h.empty?
|
||||
end
|
||||
|
||||
def random_agent=(useless)
|
||||
@user_agent = get_random_user_agent
|
||||
end
|
||||
|
||||
# return Hash
|
||||
def to_h
|
||||
options = {}
|
||||
@@ -227,6 +238,8 @@ class WpscanOptions
|
||||
['--wordlist', '-w', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--threads', '-t', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--force', '-f', GetoptLong::NO_ARGUMENT],
|
||||
['--user-agent', '-a', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--random-agent', '-r', GetoptLong::NO_ARGUMENT],
|
||||
['--help', '-h', GetoptLong::NO_ARGUMENT],
|
||||
['--verbose', '-v', GetoptLong::NO_ARGUMENT],
|
||||
['--proxy', GetoptLong::REQUIRED_ARGUMENT],
|
||||
@@ -239,7 +252,12 @@ class WpscanOptions
|
||||
['--exclude-content-based', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--basic-auth', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--debug-output', GetoptLong::NO_ARGUMENT],
|
||||
['--version', GetoptLong::NO_ARGUMENT]
|
||||
['--version', GetoptLong::NO_ARGUMENT],
|
||||
['--cache-ttl', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--request-timeout', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--connect-timeout', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--max-threads', GetoptLong::REQUIRED_ARGUMENT],
|
||||
['--batch', GetoptLong::NO_ARGUMENT]
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -32,10 +32,12 @@ class CheckerPlugin < Plugin
|
||||
xml = xml(vuln_ref_file)
|
||||
|
||||
urls = []
|
||||
xml.xpath('//reference').each { |node| urls << node.text }
|
||||
xml.xpath('//references/url').each { |node| urls << node.text }
|
||||
|
||||
urls.uniq!
|
||||
|
||||
puts "[!] No URLs found in #{vuln_ref_file}!" if urls.empty?
|
||||
|
||||
dead_urls = []
|
||||
queue_count = 0
|
||||
request_count = 0
|
||||
|
||||
91
lib/wpstools/plugins/checker/checker_spelling.rb
Normal file
91
lib/wpstools/plugins/checker/checker_spelling.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class CheckerSpelling < Plugin
|
||||
|
||||
def initialize
|
||||
super(author: 'WPScanTeam - @ethicalhack3r')
|
||||
|
||||
register_options(['--spellcheck', '--sc', 'Check all files for common spelling mistakes.'])
|
||||
end
|
||||
|
||||
def run(options = {})
|
||||
spellcheck if options[:spellcheck]
|
||||
end
|
||||
|
||||
def spellcheck
|
||||
mistakes = 0
|
||||
|
||||
puts '[+] Checking for spelling mistakes'
|
||||
puts
|
||||
|
||||
files.each do |file_name|
|
||||
if File.exists?(file_name)
|
||||
file = File.open(file_name, 'r')
|
||||
|
||||
misspellings.each_key do |misspelling|
|
||||
begin
|
||||
file.read.scan(/#{misspelling}/).each do |match|
|
||||
mistakes += 1
|
||||
puts "[MISSPELLING] File: #{file_name} Bad: #{match} Good: #{misspellings[misspelling]}"
|
||||
end
|
||||
rescue => e
|
||||
puts "Error in #{file_name} #{e}"
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
file.close
|
||||
end
|
||||
end
|
||||
|
||||
puts
|
||||
puts "[+] Found #{mistakes} spelling mistakes"
|
||||
|
||||
mistakes
|
||||
end
|
||||
|
||||
def misspellings
|
||||
{
|
||||
/databse/i => 'database',
|
||||
/whith/i => 'with',
|
||||
/wich/i => 'which',
|
||||
/verions/i => 'versions',
|
||||
/vulnerabilitiy/i => 'vulnerability',
|
||||
/unkown/i => 'unknown',
|
||||
/recieved/i => 'received',
|
||||
/acheive/i => 'achieve',
|
||||
/wierd/i => 'weird',
|
||||
/untill/i => 'until',
|
||||
/alot/i => 'a lot',
|
||||
/randomstorm/ => 'RandomStorm',
|
||||
/wpscan/ => 'WPScan',
|
||||
/Wordpress/ => 'WordPress'
|
||||
}
|
||||
end
|
||||
|
||||
def files
|
||||
files = Dir['**/*'].reject {|fn| File.directory?(fn) }
|
||||
|
||||
ignore.each do |ignore|
|
||||
files.delete_if { |data| data.match(ignore) }
|
||||
end
|
||||
|
||||
files
|
||||
end
|
||||
|
||||
def ignore
|
||||
ignore = []
|
||||
|
||||
ignore << File.basename(__FILE__)
|
||||
ignore << 'spec/cache/'
|
||||
ignore << 'spec/spec_session/'
|
||||
ignore << 'cache/'
|
||||
ignore << 'coverage/'
|
||||
ignore << 'wordlist-iso-8859-1'
|
||||
ignore << 'log.txt'
|
||||
ignore << 'debug.log'
|
||||
ignore << 'wordlist.txt'
|
||||
|
||||
ignore
|
||||
end
|
||||
end
|
||||
@@ -12,17 +12,33 @@ class StatsPlugin < Plugin
|
||||
|
||||
def run(options = {})
|
||||
if options[:stats]
|
||||
puts 'Wpscan Databse Statistics:'
|
||||
puts '--------------------------'
|
||||
puts "[#] Total vulnerable versions: #{vuln_core_count}"
|
||||
puts "[#] Total vulnerable plugins: #{vuln_plugin_count}"
|
||||
puts "[#] Total vulnerable themes: #{vuln_theme_count}"
|
||||
puts "[#] Total version vulnerabilities: #{version_vulns_count}"
|
||||
puts "[#] Total plugin vulnerabilities: #{plugin_vulns_count}"
|
||||
puts "[#] Total theme vulnerabilities: #{theme_vulns_count}"
|
||||
puts "[#] Total plugins to enumerate: #{total_plugins}"
|
||||
puts "[#] Total themes to enumerate: #{total_themes}"
|
||||
date_wp = File.mtime(WP_VULNS_FILE)
|
||||
date_plugins = File.mtime(PLUGINS_VULNS_FILE)
|
||||
date_themes = File.mtime(THEMES_VULNS_FILE)
|
||||
date_plugins_full = File.mtime(PLUGINS_FULL_FILE)
|
||||
date_themes_full = File.mtime(THEMES_FULL_FILE)
|
||||
|
||||
puts "WPScan Database Statistics:"
|
||||
puts "---------------------------"
|
||||
puts
|
||||
puts "[#] Total vulnerable versions: #{vuln_core_count}"
|
||||
puts "[#] Total vulnerable plugins: #{vuln_plugin_count}"
|
||||
puts "[#] Total vulnerable themes: #{vuln_theme_count}"
|
||||
puts
|
||||
puts "[#] Total version vulnerabilities: #{version_vulns_count}"
|
||||
puts "[#] Total plugin vulnerabilities: #{plugin_vulns_count}"
|
||||
puts "[#] Total theme vulnerabilities: #{theme_vulns_count}"
|
||||
puts
|
||||
puts "[#] Total plugins to enumerate: #{total_plugins}"
|
||||
puts "[#] Total themes to enumerate: #{total_themes}"
|
||||
puts
|
||||
puts "[+] WordPress DB modified: #{date_wp.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
puts "[+] Plugins DB modified: #{date_plugins.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
puts "[+] Themes DB modified: #{date_themes.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
puts "[+] Enumeration plugins: #{date_plugins_full.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
puts "[+] Enumeration themes: #{date_themes_full.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
puts
|
||||
puts "[+] Report generated: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ describe Browser do
|
||||
it_behaves_like 'Browser::Actions'
|
||||
it_behaves_like 'Browser::Options'
|
||||
|
||||
CONFIG_FILE_WITHOUT_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json'
|
||||
CONFIG_FILE_WITH_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf_proxy.json'
|
||||
#CONFIG_FILE_WITH_PROXY_AND_AUTH = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf_proxy_auth.json'
|
||||
CONFIG_FILE_WITHOUT_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser.conf.json'
|
||||
CONFIG_FILE_WITH_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser.conf_proxy.json'
|
||||
#CONFIG_FILE_WITH_PROXY_AND_AUTH = SPEC_FIXTURES_CONF_DIR + '/browser.conf_proxy_auth.json'
|
||||
|
||||
subject(:browser) {
|
||||
Browser.reset
|
||||
@@ -16,14 +16,13 @@ describe Browser do
|
||||
}
|
||||
let(:options) { {} }
|
||||
let(:instance_vars_to_check) {
|
||||
['user_agent', 'user_agent_mode', 'available_user_agents', 'proxy',
|
||||
'max_threads', 'cache_ttl', 'request_timeout', 'connect_timeout']
|
||||
['proxy', 'max_threads', 'cache_ttl', 'request_timeout', 'connect_timeout']
|
||||
}
|
||||
let(:json_config_without_proxy) { JSON.parse(File.read(CONFIG_FILE_WITHOUT_PROXY)) }
|
||||
let(:json_config_with_proxy) { JSON.parse(File.read(CONFIG_FILE_WITH_PROXY)) }
|
||||
|
||||
def check_instance_variables(browser, json_expected_vars)
|
||||
json_expected_vars['max_threads'] ||= 1 # max_thread can not be nil
|
||||
json_expected_vars['max_threads'] ||= 20 # max_thread can not be nil
|
||||
|
||||
instance_vars_to_check.each do |variable_name|
|
||||
browser.send(:"#{variable_name}").should === json_expected_vars[variable_name]
|
||||
@@ -39,12 +38,6 @@ describe Browser do
|
||||
describe '::instance' do
|
||||
after { check_instance_variables(browser, @json_expected_vars) }
|
||||
|
||||
context "when default config_file = #{CONFIG_FILE_WITHOUT_PROXY}" do
|
||||
it 'will check the instance vars' do
|
||||
@json_expected_vars = json_config_without_proxy
|
||||
end
|
||||
end
|
||||
|
||||
context "when :config_file = #{CONFIG_FILE_WITH_PROXY}" do
|
||||
let(:options) { { config_file: CONFIG_FILE_WITH_PROXY } }
|
||||
|
||||
@@ -137,12 +130,14 @@ describe Browser do
|
||||
headers: { 'User-Agent' => 'SomeUA' },
|
||||
ssl_verifypeer: false, ssl_verifyhost: 0,
|
||||
cookiejar: cookie_jar, cookiefile: cookie_jar,
|
||||
timeout: 2000, connecttimeout: 1000
|
||||
timeout: 2000, connecttimeout: 1000,
|
||||
maxredirs: 3,
|
||||
referer: nil
|
||||
}
|
||||
}
|
||||
|
||||
after :each do
|
||||
browser.stub(user_agent: 'SomeUA')
|
||||
browser.user_agent = 'SomeUA'
|
||||
browser.cache_ttl = 250
|
||||
|
||||
browser.merge_request_params(params).should == @expected
|
||||
@@ -187,6 +182,14 @@ describe Browser do
|
||||
@expected = default_expectation.merge(params)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the maxredirs is alreday set' do
|
||||
let(:params) { { maxredirs: 100 } }
|
||||
|
||||
it 'does not override it' do
|
||||
@expected = default_expectation.merge(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#forge_request' do
|
||||
|
||||
@@ -17,13 +17,13 @@ describe CacheFileStore do
|
||||
|
||||
describe '#storage_path' do
|
||||
it 'returns the storage path given in the #new' do
|
||||
@cache.storage_path.should == cache_dir
|
||||
@cache.storage_path.should match(/#{cache_dir}/)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#serializer' do
|
||||
it 'should return the default serializer : Marshal' do
|
||||
@cache.serializer.should == Marshal
|
||||
@cache.serializer.should == Marshal
|
||||
@cache.serializer.should_not == YAML
|
||||
end
|
||||
end
|
||||
@@ -32,12 +32,12 @@ describe CacheFileStore do
|
||||
it "should remove all files from the cache dir (#{@cache_dir}" do
|
||||
# let's create some files into the directory first
|
||||
(0..5).each do |i|
|
||||
File.new(cache_dir + "/file_#{i}.txt", File::CREAT)
|
||||
File.new(@cache.storage_path + "/file_#{i}.txt", File::CREAT)
|
||||
end
|
||||
|
||||
count_files_in_dir(cache_dir, 'file_*.txt').should == 6
|
||||
count_files_in_dir(@cache.storage_path, 'file_*.txt').should == 6
|
||||
@cache.clean
|
||||
count_files_in_dir(cache_dir).should == 0
|
||||
count_files_in_dir(@cache.storage_path).should == 0
|
||||
end
|
||||
end
|
||||
|
||||
@@ -70,4 +70,16 @@ describe CacheFileStore do
|
||||
|
||||
## TODO write / read for an object
|
||||
end
|
||||
|
||||
describe '#storage_dir' do
|
||||
it 'should create a unique storage dir' do
|
||||
storage_dirs = []
|
||||
|
||||
(1..5).each do |i|
|
||||
storage_dirs << CacheFileStore.new(cache_dir).storage_path
|
||||
end
|
||||
|
||||
storage_dirs.uniq.size.should == 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpThemes do
|
||||
before { stub_request(:get, /.+\/style.css$/).to_return(status: 200) }
|
||||
|
||||
it_behaves_like 'WpItems::Detectable' do
|
||||
subject(:wp_themes) { WpThemes }
|
||||
let(:item_class) { WpTheme }
|
||||
|
||||
@@ -88,4 +88,83 @@ describe 'common_helper' do
|
||||
@expected = @html
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#truncate' do
|
||||
after :each do
|
||||
output = truncate(@input, @length, @trailing)
|
||||
output.should == @expected
|
||||
end
|
||||
|
||||
it 'returns nil on no input' do
|
||||
@input = nil
|
||||
@length = 1
|
||||
@expected = nil
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'returns input when length > input' do
|
||||
@input = '1234567890'
|
||||
@length = 13
|
||||
@expected = @input
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'truncates the input' do
|
||||
@input = '1234567890'
|
||||
@length = 6
|
||||
@expected = '123...'
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'adds own trailing' do
|
||||
@input = '1234567890'
|
||||
@length = 7
|
||||
@expected = '123xxxx'
|
||||
@trailing = 'xxxx'
|
||||
end
|
||||
|
||||
it 'accepts strings as length' do
|
||||
@input = '1234567890'
|
||||
@length = '6'
|
||||
@expected = '123...'
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'checks if trailing is longer than input' do
|
||||
@input = '1234567890'
|
||||
@length = 1
|
||||
@expected = @input
|
||||
@trailing = 'A' * 20
|
||||
end
|
||||
|
||||
it 'returns input on negative length' do
|
||||
@input = '1234567890'
|
||||
@length = -1
|
||||
@expected = @input
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'returns input on length == input.length' do
|
||||
@input = '1234567890'
|
||||
@length = '10'
|
||||
@expected = @input
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'returns cut string on nil trailing' do
|
||||
@input = '1234567890'
|
||||
@length = 9
|
||||
@expected = '123456789'
|
||||
@trailing = nil
|
||||
end
|
||||
|
||||
it 'trailing.length > length' do
|
||||
@input = '1234567890'
|
||||
@length = 1
|
||||
@expected = @input
|
||||
@trailing = 'A' * 20
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -21,10 +21,10 @@ describe Vulnerability do
|
||||
|
||||
context 'with fixed version argument' do
|
||||
let(:fixed_version) { '1.0' }
|
||||
its(:title) { should be title }
|
||||
its(:references) { should be references }
|
||||
its(:type) { should be type }
|
||||
its(:fixed_in) { should be fixed_version }
|
||||
its(:title) { should be title }
|
||||
its(:references) { should be references }
|
||||
its(:type) { should be type }
|
||||
its(:fixed_in) { should be fixed_version }
|
||||
end
|
||||
|
||||
end
|
||||
@@ -35,14 +35,14 @@ describe Vulnerability do
|
||||
xml(MODELS_FIXTURES + '/vulnerability/xml_node.xml').xpath('//vulnerability')
|
||||
}
|
||||
|
||||
expected_refs = {
|
||||
:url=>['Ref 1', 'Ref 2'],
|
||||
:cve=>['2011-001'],
|
||||
:secunia=>['secunia'],
|
||||
:osvdb=>['osvdb'],
|
||||
:metasploit=>['exploit/ex1'],
|
||||
:exploitdb=>['exploitdb']
|
||||
}
|
||||
expected_refs = {
|
||||
:url=>['Ref 1', 'Ref 2'],
|
||||
:cve=>['2011-001'],
|
||||
:secunia=>['secunia'],
|
||||
:osvdb=>['osvdb'],
|
||||
:metasploit=>['exploit/ex1'],
|
||||
:exploitdb=>['exploitdb']
|
||||
}
|
||||
|
||||
its(:title) { should == 'Vuln Title' }
|
||||
its(:type) { should == 'CSRF' }
|
||||
|
||||
@@ -13,14 +13,14 @@ describe WpItem do
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:vulns_file) { MODELS_FIXTURES + '/wp_item/vulnerable/items_vulns.xml' }
|
||||
let(:vulns_xpath) { "//item[@name='neo']/vulnerability" }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new("I'm the one", 'XSS', expected_refs) }
|
||||
end
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@ describe WpPlugin do
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:options) { { name: 'white-rabbit' } }
|
||||
let(:vulns_file) { MODELS_FIXTURES + '/wp_plugin/vulnerable/plugins_vulns.xml' }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('Follow me!', 'REDIRECT', expected_refs) }
|
||||
end
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ describe 'WpTheme::Findable' do
|
||||
let(:uri) { URI.parse('http://example.com/') }
|
||||
|
||||
describe '::find_from_css_link' do
|
||||
before do
|
||||
stub_request(:get, /.+\/style.css$/).to_return(status: 200)
|
||||
end
|
||||
|
||||
after do
|
||||
@body ||= File.new(fixtures_dir + '/css_link/' + @file)
|
||||
stub_request(:get, uri.to_s).to_return(status: 200, body: @body)
|
||||
@@ -51,6 +55,10 @@ describe 'WpTheme::Findable' do
|
||||
end
|
||||
|
||||
describe '::find_from_wooframework' do
|
||||
before do
|
||||
stub_request(:get, /.+\/style.css$/).to_return(status: 200)
|
||||
end
|
||||
|
||||
after do
|
||||
@body ||= File.new(fixtures_dir + '/wooframework/' + @file)
|
||||
stub_request(:get, uri.to_s).to_return(status: 200, body: @body)
|
||||
@@ -119,6 +127,7 @@ describe 'WpTheme::Findable' do
|
||||
context 'when the theme is found' do
|
||||
it 'returns it, with the :found_from set' do
|
||||
stub_all_to_nil()
|
||||
stub_request(:get, /.+\/the-oracle\/style.css$/).to_return(status: 200)
|
||||
expected = WpTheme.new(uri, name: 'the-oracle')
|
||||
|
||||
WpTheme.stub(:find_from_css_link).and_return(expected)
|
||||
|
||||
@@ -3,19 +3,23 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpTheme do
|
||||
before do
|
||||
stub_request(:get, /.+\/style.css$/).to_return(status: 200)
|
||||
end
|
||||
|
||||
it_behaves_like 'WpTheme::Versionable'
|
||||
it_behaves_like 'WpTheme::Vulnerable'
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:options) { { name: 'the-oracle' } }
|
||||
let(:vulns_file) { MODELS_FIXTURES + '/wp_theme/vulnerable/themes_vulns.xml' }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('I see you', 'FPD', expected_refs) }
|
||||
end
|
||||
|
||||
|
||||
@@ -34,10 +34,6 @@ describe WpUser do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#login_url' do
|
||||
its(:login_url) { should == 'http://example.com/wp-login.php' }
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
after do
|
||||
subject.id = 1
|
||||
|
||||
@@ -7,14 +7,14 @@ describe WpVersion do
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:options) { { number: '3.2' } }
|
||||
let(:vulns_file) { MODELS_FIXTURES + '/wp_version/vulnerable/versions_vulns.xml' }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_refs) { {
|
||||
:url => ['Ref 1', 'Ref 2'],
|
||||
:cve => ['2011-001'],
|
||||
:secunia => ['secunia'],
|
||||
:osvdb => ['osvdb'],
|
||||
:metasploit => ['exploit/ex1'],
|
||||
:exploitdb => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('Here I Am', 'SQLI', expected_refs) }
|
||||
end
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ describe 'VersionCompare' do
|
||||
@version1 = '0'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '0.4.2b'
|
||||
@version2 = '2.3.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'version checked is older' do
|
||||
|
||||
@@ -12,7 +12,7 @@ describe 'WebSite' do
|
||||
before :all do
|
||||
Browser::reset
|
||||
Browser.instance(
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json',
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json',
|
||||
cache_ttl: 0
|
||||
)
|
||||
end
|
||||
@@ -28,7 +28,7 @@ describe 'WebSite' do
|
||||
end
|
||||
|
||||
context 'when protocol or trailing slash is missing' do
|
||||
it 'should add the them' do
|
||||
it 'should add them' do
|
||||
@uri = 'example.localhost'
|
||||
@expected = 'http://example.localhost/'
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ describe WpTarget do
|
||||
let(:login_url) { wp_target.uri.merge('wp-login.php').to_s }
|
||||
let(:options) {
|
||||
{
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json',
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json',
|
||||
cache_ttl: 0,
|
||||
wp_content_dir: 'wp-content',
|
||||
wp_plugins_dir: 'wp-content/plugins'
|
||||
@@ -97,6 +97,14 @@ describe WpTarget do
|
||||
wp_target.should_not be_wordpress
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the response is a 403' do
|
||||
before { stub_request(:any, /.*/).to_return(status: 403) }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { wp_target.wordpress? }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wordpress_hosted?' do
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Theme Name: firefart.net
|
||||
Theme URI: http://www.firefart.net/
|
||||
Description: firefart.net Theme
|
||||
Author: Christian Mehlmauer
|
||||
Author URI: http://www.firefart.net%
|
||||
Template: twentytwelve
|
||||
Version: 1.0.0
|
||||
*/
|
||||
|
||||
@import url("../twentytwelve/style.css");
|
||||
7
spec/samples/conf/browser.conf.json
Normal file
7
spec/samples/conf/browser.conf.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0",
|
||||
"cache_ttl": 600,
|
||||
"request_timeout": 2000,
|
||||
"connect_timeout": 1000,
|
||||
"max_threads": 20
|
||||
}
|
||||
7
spec/samples/conf/browser.conf_proxy.json
Normal file
7
spec/samples/conf/browser.conf_proxy.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0",
|
||||
"proxy": "127.0.0.1:3038",
|
||||
"cache_ttl": 300,
|
||||
"request_timeout": 2000,
|
||||
"connect_timeout": 1000
|
||||
}
|
||||
8
spec/samples/conf/browser.conf_proxy_auth.json
Normal file
8
spec/samples/conf/browser.conf_proxy_auth.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0",
|
||||
"proxy": "127.0.0.1:3038",
|
||||
"proxy_auth": "user:pass",
|
||||
"cache_ttl": 300,
|
||||
"request_timeout": 2000,
|
||||
"connect_timeout": 1000
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0",
|
||||
"user_agent_mode": "static",
|
||||
"cache_ttl": 300,
|
||||
"request_timeout": 2000,
|
||||
"connect_timeout": 1000,
|
||||
"max_threads": 5
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0",
|
||||
"user_agent_mode": "static",
|
||||
"proxy": "127.0.0.1:3038",
|
||||
"cache_ttl": 300,
|
||||
"request_timeout": 2000,
|
||||
"connect_timeout": 1000
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0",
|
||||
"user_agent_mode": "static",
|
||||
"proxy": "127.0.0.1:3038",
|
||||
"proxy_auth": "user:pass",
|
||||
"cache_ttl": 300,
|
||||
"request_timeout": 2000,
|
||||
"connect_timeout": 1000
|
||||
}
|
||||
@@ -71,69 +71,6 @@ shared_examples 'Browser::Options' do
|
||||
end
|
||||
end
|
||||
|
||||
describe '#user_agent_mode= & #user_agent_mode' do
|
||||
# Testing all valid modes
|
||||
Browser::USER_AGENT_MODES.each do |user_agent_mode|
|
||||
it "sets & returns #{user_agent_mode}" do
|
||||
browser.user_agent_mode = user_agent_mode
|
||||
browser.user_agent_mode.should === user_agent_mode
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets the mode to "static" if nil is given' do
|
||||
browser.user_agent_mode = nil
|
||||
browser.user_agent_mode.should === 'static'
|
||||
end
|
||||
|
||||
it 'raises an error if the mode is not valid' do
|
||||
expect { browser.user_agent_mode = 'invalid-mode' }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '#user_agent= & #user_agent' do
|
||||
let(:available_user_agents) { %w{ ua-1 ua-2 ua-3 ua-4 ua-6 ua-7 ua-8 ua-9 ua-10 ua-11 ua-12 ua-13 ua-14 ua-15 ua-16 ua-17 } }
|
||||
|
||||
context 'when static mode' do
|
||||
it 'returns the same user agent' do
|
||||
browser.user_agent = 'fake UA'
|
||||
browser.user_agent_mode = 'static'
|
||||
|
||||
(1..3).each do
|
||||
browser.user_agent.should === 'fake UA'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when semi-static mode' do
|
||||
it 'chooses a random user_agent in the available_user_agents array and always return it' do
|
||||
browser.available_user_agents = available_user_agents
|
||||
browser.user_agent = 'Firefox 11.0'
|
||||
browser.user_agent_mode = 'semi-static'
|
||||
|
||||
user_agent = browser.user_agent
|
||||
user_agent.should_not === 'Firefox 11.0'
|
||||
available_user_agents.include?(user_agent).should be_true
|
||||
|
||||
(1..3).each do
|
||||
browser.user_agent.should === user_agent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when random' do
|
||||
it 'returns a random user agent each time' do
|
||||
browser.available_user_agents = available_user_agents
|
||||
browser.user_agent_mode = 'random'
|
||||
|
||||
ua_1 = browser.user_agent
|
||||
ua_2 = browser.user_agent
|
||||
ua_3 = browser.user_agent
|
||||
|
||||
fail if ua_1 === ua_2 and ua_2 === ua_3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'proxy=' do
|
||||
let(:exception) { 'Invalid proxy format. Should be [protocol://]host:port.' }
|
||||
|
||||
@@ -185,7 +122,7 @@ shared_examples 'Browser::Options' do
|
||||
end
|
||||
|
||||
context 'valid format' do
|
||||
it 'sets the auth' do
|
||||
it 'sets the auth' do
|
||||
@proxy_auth = 'username:passwd'
|
||||
@expected = @proxy_auth
|
||||
end
|
||||
|
||||
@@ -53,7 +53,7 @@ shared_examples 'WpItem::Versionable' do
|
||||
context 'when the version exists' do
|
||||
it 'returns the name and the version' do
|
||||
@version = '1.3'
|
||||
@expected = 'some-name v1.3'
|
||||
@expected = 'some-name - v1.3'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,7 +27,6 @@ shared_examples 'WpTarget::WpReadme' do
|
||||
@expected = true
|
||||
end
|
||||
|
||||
# http://code.google.com/p/wpscan/issues/detail?id=108
|
||||
it 'returns true even if the readme.html is not in english' do
|
||||
@stub = { status: 200, body: File.new(fixtures_dir + '/readme-3.3.2-fr.html') }
|
||||
@expected = true
|
||||
|
||||
@@ -55,6 +55,11 @@ shared_examples 'WpTheme::Versionable' do
|
||||
@file = 'twentyeleven-1.3.css'
|
||||
@expected = '1.3'
|
||||
end
|
||||
|
||||
it 'returns the correct version' do
|
||||
@file = 'firefart.net.css'
|
||||
@expected = '1.0.0'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ shared_examples 'WpUser::BruteForcable' do
|
||||
|
||||
describe '#valid_password?' do
|
||||
let(:response) { Typhoeus::Response.new(resp_options) }
|
||||
let(:resp_options) { {} }
|
||||
let(:resp_options) { {} }
|
||||
|
||||
after do
|
||||
wp_user.valid_password?(response, 'password', redirect_url).should == @expected
|
||||
@@ -66,7 +66,8 @@ shared_examples 'WpUser::BruteForcable' do
|
||||
end
|
||||
|
||||
describe '#brute_force' do
|
||||
let(:login) { 'someuser' }
|
||||
let(:login) { 'someuser' }
|
||||
let(:login_url) { uri.merge('wp-login.php').to_s }
|
||||
|
||||
after do
|
||||
[wordlist_utf8, wordlist_iso].each do |wordlist|
|
||||
@@ -78,8 +79,10 @@ shared_examples 'WpUser::BruteForcable' do
|
||||
|
||||
context 'when no password is valid' do
|
||||
before do
|
||||
stub_request(:get, login_url).to_return(status: 200)
|
||||
stub_request(:post, wp_user.login_url).
|
||||
#with(body: { log: login }). # produces an error : undefined method `split' for {:log=>"someuser", :pwd=>"password1"}:Hash
|
||||
# with(body: { log: login }). # produces an error : undefined method `split' for {:log=>"someuser", :pwd=>"password1"}:Hash
|
||||
# Fixed in WebMock 1.17.2, TODO: Modify the specs
|
||||
to_return(body: 'login_error')
|
||||
end
|
||||
|
||||
@@ -92,7 +95,8 @@ shared_examples 'WpUser::BruteForcable' do
|
||||
let(:redirect_url) { nil }
|
||||
|
||||
before do
|
||||
stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => 'wrong-location' } )
|
||||
stub_request(:get, login_url).to_return(status: 200)
|
||||
stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => 'wrong-location' })
|
||||
end
|
||||
|
||||
it 'does not set the @password' do
|
||||
@@ -104,15 +108,32 @@ shared_examples 'WpUser::BruteForcable' do
|
||||
# Due to the error with .with(body: { log: login }) above
|
||||
# We can't use it to stub the request for a specific password
|
||||
# So, the first one will be valid
|
||||
# Fixed in WebMock 1.17.2, TODO: Modify the specs
|
||||
|
||||
before do
|
||||
stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => redirect_url } )
|
||||
stub_request(:get, login_url).to_return(status: 200)
|
||||
stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => redirect_url })
|
||||
end
|
||||
|
||||
it 'sets the @password' do
|
||||
@expected = 'password1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the login url is redirected to https' do
|
||||
let(:https_login_url) { 'https://example.com/wp-login.php' }
|
||||
|
||||
before do
|
||||
stub_request(:any, uri.merge('wp-login.php').to_s).to_return(status: 302, headers: { 'Location' => https_login_url})
|
||||
stub_request(:get, https_login_url).to_return(status: 200)
|
||||
stub_request(:post, https_login_url).with(body: hash_including({ log: 'someuser', pwd: 'root'})).to_return(status: 302, headers: { 'Location' => redirect_url })
|
||||
stub_request(:post, https_login_url).with(body: /pwd=(?!root)/).to_return(body: 'login_error')
|
||||
end
|
||||
|
||||
it 'does not raise any error' do
|
||||
@expected = 'root'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ SPEC_FIXTURES_CONF_DIR = SPEC_FIXTURES_DIR + '/conf' # FIXME Remove it
|
||||
SPEC_FIXTURES_WP_VERSIONS_DIR = SPEC_FIXTURES_DIR + '/wp_versions'
|
||||
|
||||
redefine_constant(:CACHE_DIR, SPEC_DIR + '/cache')
|
||||
redefine_constant(:CONF_DIR, SPEC_FIXTURES_DIR + '/conf/browser') # FIXME Remove the /browser
|
||||
redefine_constant(:CONF_DIR, SPEC_FIXTURES_DIR + '/conf')
|
||||
|
||||
MODELS_FIXTURES = SPEC_FIXTURES_DIR + '/common/models'
|
||||
COLLECTIONS_FIXTURES = SPEC_FIXTURES_DIR + '/common/collections'
|
||||
|
||||
73
stop_user_enumeration_bypass.rb
Executable file
73
stop_user_enumeration_bypass.rb
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env ruby
|
||||
# encoding: UTF-8
|
||||
#
|
||||
#
|
||||
# Script based on http://seclists.org/fulldisclosure/2014/Feb/3
|
||||
|
||||
require File.join(File.dirname(__FILE__), 'lib/wpscan/wpscan_helper')
|
||||
|
||||
@opts = {
|
||||
ids: 1..10,
|
||||
verbose: false,
|
||||
user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0'
|
||||
}
|
||||
|
||||
parser = OptionParser.new('Usage: ./stop_user_enumeration_bypass.rb <Target URL> [options]', 35) do |opts|
|
||||
opts.on('--proxy PROXY', 'Proxy to use') do |proxy|
|
||||
@opts[:proxy] = proxy
|
||||
end
|
||||
|
||||
opts.on('--auth Username:Password', 'Credentials to use if Basic/NTLM auth') do |creds|
|
||||
@opts[:creds] = creds
|
||||
end
|
||||
|
||||
opts.on('--ids START-END', 'The ids to check, default is 1-10') do |ids|
|
||||
@opts[:ids] = Range.new(*ids.split('-').map(&:to_i))
|
||||
end
|
||||
|
||||
opts.on('--user-agent UA', 'The user-agent to use') do |ua|
|
||||
@opts[:user_agent] = ua
|
||||
end
|
||||
|
||||
opts.on('--verbose', '-v', 'Verbose Mode') do
|
||||
@opts[:verbose] = true
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
parser.parse!
|
||||
|
||||
fail "#{red('The target URL must be supplied')}\n\n#{parser}" unless ARGV[0]
|
||||
|
||||
uri = URI.parse(add_trailing_slash(add_http_protocol(ARGV[0])))
|
||||
|
||||
request_params = {
|
||||
proxy: @opts[:proxy],
|
||||
userpwd: @opts[:creds],
|
||||
headers: { 'User-Agent' => @opts[:user_agent] },
|
||||
followlocation: true,
|
||||
ssl_verifypeer: false,
|
||||
ssl_verifyhost: 2
|
||||
}
|
||||
|
||||
detected_users = WpUsers.new
|
||||
|
||||
@opts[:ids].each do |user_id|
|
||||
user = WpUser.new(uri, id: user_id)
|
||||
|
||||
if user.exists_from_response?(Typhoeus.post(uri, request_params.merge(body: { author: user_id })))
|
||||
detected_users << user
|
||||
end
|
||||
end
|
||||
|
||||
puts 'Usernames found:'
|
||||
detected_users.output
|
||||
rescue => e
|
||||
puts e.message
|
||||
|
||||
if @opts[:verbose]
|
||||
puts red('Trace:')
|
||||
puts red(e.backtrace.join("\n"))
|
||||
end
|
||||
exit(1)
|
||||
end
|
||||
137
wpscan.rb
137
wpscan.rb
@@ -44,6 +44,10 @@ def main
|
||||
exit(0)
|
||||
end
|
||||
|
||||
unless wpscan_options.url
|
||||
raise 'The URL is mandatory, please supply it with --url or -u'
|
||||
end
|
||||
|
||||
wp_target = WpTarget.new(wpscan_options.url, wpscan_options.to_h)
|
||||
|
||||
# Remote website up?
|
||||
@@ -59,22 +63,24 @@ def main
|
||||
end
|
||||
end
|
||||
|
||||
redirection = wp_target.redirection
|
||||
if redirection
|
||||
if (redirection = wp_target.redirection)
|
||||
if wpscan_options.follow_redirection
|
||||
puts "Following redirection #{redirection}"
|
||||
puts
|
||||
else
|
||||
puts "The remote host tried to redirect us to: #{redirection}"
|
||||
print 'Do you want follow the redirection ? [y/n] '
|
||||
puts "The remote host redirects to: #{redirection}"
|
||||
puts '[?] Do you want follow the redirection ? [Y]es [N]o [A]bort, default: [N]'
|
||||
end
|
||||
|
||||
if wpscan_options.follow_redirection or Readline.readline =~ /^y/i
|
||||
wpscan_options.url = redirection
|
||||
wp_target = WpTarget.new(redirection, wpscan_options.to_h)
|
||||
else
|
||||
puts 'Scan aborted'
|
||||
exit(0)
|
||||
if wpscan_options.follow_redirection || !wpscan_options.batch
|
||||
if wpscan_options.follow_redirection || (input = Readline.readline) =~ /^y/i
|
||||
wpscan_options.url = redirection
|
||||
wp_target = WpTarget.new(redirection, wpscan_options.to_h)
|
||||
else
|
||||
if input =~ /^a/i
|
||||
puts 'Scan aborted'
|
||||
exit(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,8 +102,8 @@ def main
|
||||
unless wp_target.wp_plugins_dir_exists?
|
||||
puts "The plugins directory '#{wp_target.wp_plugins_dir}' does not exist."
|
||||
puts 'You can specify one per command line option (don\'t forget to include the wp-content directory if needed)'
|
||||
print 'Continue? [y/n] '
|
||||
unless Readline.readline =~ /^y/i
|
||||
puts '[?] Continue? [Y]es [N]o, default: [N]'
|
||||
if wpscan_options.batch || Readline.readline !~ /^y/i
|
||||
exit(0)
|
||||
end
|
||||
end
|
||||
@@ -105,16 +111,16 @@ def main
|
||||
# Output runtime data
|
||||
start_time = Time.now
|
||||
start_memory = get_memory_usage
|
||||
puts "| URL: #{wp_target.url}"
|
||||
puts "| Started: #{start_time.asctime}"
|
||||
puts "#{green('[+]')} URL: #{wp_target.url}"
|
||||
puts "#{green('[+]')} Started: #{start_time.asctime}"
|
||||
puts
|
||||
|
||||
if wp_target.wordpress_hosted?
|
||||
puts "#{red('[!]')} We do not support scanning *.wordpress.com hosted blogs."
|
||||
puts "#{red('[!]')} We do not support scanning *.wordpress.com hosted blogs"
|
||||
end
|
||||
|
||||
if wp_target.has_robots?
|
||||
puts green('[+]') + " robots.txt available under: '#{wp_target.robots_url}'"
|
||||
puts "#{green('[+]')} robots.txt available under: '#{wp_target.robots_url}'"
|
||||
|
||||
wp_target.parse_robots_txt.each do |dir|
|
||||
puts "#{green('[+]')} Interesting entry from robots.txt: #{dir}"
|
||||
@@ -122,15 +128,15 @@ def main
|
||||
end
|
||||
|
||||
if wp_target.has_readme?
|
||||
puts red('[!]') + " The WordPress '#{wp_target.readme_url}' file exists"
|
||||
puts "#{red('[!]')} The WordPress '#{wp_target.readme_url}' file exists"
|
||||
end
|
||||
|
||||
if wp_target.has_full_path_disclosure?
|
||||
puts red('[!]') + " Full Path Disclosure (FPD) in: '#{wp_target.full_path_disclosure_url}'"
|
||||
puts "#{red('[!]')} Full Path Disclosure (FPD) in: '#{wp_target.full_path_disclosure_url}'"
|
||||
end
|
||||
|
||||
if wp_target.has_debug_log?
|
||||
puts red('[!]') + " Debug log file found: #{wp_target.debug_log_url}"
|
||||
puts "#{red('[!]')} Debug log file found: #{wp_target.debug_log_url}"
|
||||
end
|
||||
|
||||
wp_target.config_backup.each do |file_url|
|
||||
@@ -144,7 +150,7 @@ def main
|
||||
wp_target.interesting_headers.each do |header|
|
||||
output = "#{green('[+]')} Interesting header: "
|
||||
|
||||
if header[1].class == Array
|
||||
if header[1].class == Array
|
||||
header[1].each do |value|
|
||||
puts output + "#{header[0]}: #{value}"
|
||||
end
|
||||
@@ -154,20 +160,20 @@ def main
|
||||
end
|
||||
|
||||
if wp_target.multisite?
|
||||
puts green('[+]') + ' This site seems to be a multisite (http://codex.wordpress.org/Glossary#Multisite)'
|
||||
puts "#{green('[+]')} This site seems to be a multisite (http://codex.wordpress.org/Glossary#Multisite)"
|
||||
end
|
||||
|
||||
if wp_target.registration_enabled?
|
||||
puts green('[+]') + ' User registration is enabled'
|
||||
puts "#{green('[+]')} User registration is enabled"
|
||||
end
|
||||
|
||||
if wp_target.has_xml_rpc?
|
||||
puts green('[+]') + " XML-RPC Interface available under: #{wp_target.xml_rpc_url}"
|
||||
puts "#{green('[+]')} XML-RPC Interface available under: #{wp_target.xml_rpc_url}"
|
||||
end
|
||||
|
||||
if wp_target.has_malwares?
|
||||
malwares = wp_target.malwares
|
||||
puts red('[!]') + " #{malwares.size} malware(s) found:"
|
||||
puts "#{red('[!]')} #{malwares.size} malware(s) found:"
|
||||
|
||||
malwares.each do |malware_url|
|
||||
puts
|
||||
@@ -182,34 +188,44 @@ def main
|
||||
}
|
||||
|
||||
if wp_version = wp_target.version(WP_VERSIONS_FILE)
|
||||
wp_version.output
|
||||
wp_version.output(wpscan_options.verbose)
|
||||
end
|
||||
|
||||
if wp_theme = wp_target.theme
|
||||
puts
|
||||
# Theme version is handled in #to_s
|
||||
puts green('[+]') + " WordPress theme in use: #{wp_theme}"
|
||||
wp_theme.output
|
||||
puts "#{green('[+]')} WordPress theme in use: #{wp_theme}"
|
||||
wp_theme.output(wpscan_options.verbose)
|
||||
|
||||
# Check for parent Themes
|
||||
while wp_theme.is_child_theme?
|
||||
parent = wp_theme.get_parent_theme
|
||||
puts
|
||||
puts "#{green('[+]')} Detected parent theme: #{parent}"
|
||||
parent.output(wpscan_options.verbose)
|
||||
wp_theme = parent
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if wpscan_options.enumerate_plugins == nil and wpscan_options.enumerate_only_vulnerable_plugins == nil
|
||||
puts
|
||||
puts green('[+]') + ' Enumerating plugins from passive detection ... '
|
||||
puts "#{green('[+]')} Enumerating plugins from passive detection ..."
|
||||
|
||||
wp_plugins = WpPlugins.passive_detection(wp_target)
|
||||
if !wp_plugins.empty?
|
||||
puts " | #{wp_plugins.size} plugins found:"
|
||||
|
||||
wp_plugins.output
|
||||
wp_plugins.output(wpscan_options.verbose)
|
||||
else
|
||||
puts 'No plugins found'
|
||||
puts "#{green('[+]')} No plugins found"
|
||||
end
|
||||
end
|
||||
|
||||
# Enumerate the installed plugins
|
||||
if wpscan_options.enumerate_plugins or wpscan_options.enumerate_only_vulnerable_plugins or wpscan_options.enumerate_all_plugins
|
||||
puts
|
||||
puts green('[+]') + " Enumerating installed plugins #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_plugins} ..."
|
||||
puts "#{green('[+]')} Enumerating installed plugins #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_plugins} ..."
|
||||
puts
|
||||
|
||||
wp_plugins = WpPlugins.aggressive_detection(wp_target,
|
||||
@@ -220,18 +236,18 @@ def main
|
||||
)
|
||||
puts
|
||||
if !wp_plugins.empty?
|
||||
puts green('[+]') + " We found #{wp_plugins.size} plugins:"
|
||||
puts "#{green('[+]')} We found #{wp_plugins.size} plugins:"
|
||||
|
||||
wp_plugins.output
|
||||
wp_plugins.output(wpscan_options.verbose)
|
||||
else
|
||||
puts 'No plugins found'
|
||||
puts "#{green('[+]')} No plugins found"
|
||||
end
|
||||
end
|
||||
|
||||
# Enumerate installed themes
|
||||
if wpscan_options.enumerate_themes or wpscan_options.enumerate_only_vulnerable_themes or wpscan_options.enumerate_all_themes
|
||||
puts
|
||||
puts green('[+]') + " Enumerating installed themes #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_themes} ..."
|
||||
puts "#{green('[+]')} Enumerating installed themes #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_themes} ..."
|
||||
puts
|
||||
|
||||
wp_themes = WpThemes.aggressive_detection(wp_target,
|
||||
@@ -242,17 +258,17 @@ def main
|
||||
)
|
||||
puts
|
||||
if !wp_themes.empty?
|
||||
puts green('[+]') + " We found #{wp_themes.size} themes:"
|
||||
puts "#{green('[+]')} We found #{wp_themes.size} themes:"
|
||||
|
||||
wp_themes.output
|
||||
wp_themes.output(wpscan_options.verbose)
|
||||
else
|
||||
puts 'No themes found'
|
||||
puts "#{green('[+]')} No themes found"
|
||||
end
|
||||
end
|
||||
|
||||
if wpscan_options.enumerate_timthumbs
|
||||
puts
|
||||
puts green('[+]') + ' Enumerating timthumb files ...'
|
||||
puts "#{green('[+]')} Enumerating timthumb files ..."
|
||||
puts
|
||||
|
||||
wp_timthumbs = WpTimthumbs.aggressive_detection(wp_target,
|
||||
@@ -263,22 +279,27 @@ def main
|
||||
)
|
||||
puts
|
||||
if !wp_timthumbs.empty?
|
||||
puts green('[+]') + " We found #{wp_timthumbs.size} timthumb file/s:"
|
||||
puts "#{green('[+]')} We found #{wp_timthumbs.size} timthumb file/s:"
|
||||
puts
|
||||
|
||||
wp_timthumbs.output
|
||||
wp_timthumbs.output(wpscan_options.verbose)
|
||||
|
||||
puts
|
||||
puts red(' * Reference: http://www.exploit-db.com/exploits/17602/')
|
||||
else
|
||||
puts 'No timthumb files found'
|
||||
puts "#{green('[+]')} No timthumb files found"
|
||||
end
|
||||
end
|
||||
|
||||
# If we haven't been supplied a username, enumerate them...
|
||||
if !wpscan_options.username and wpscan_options.wordlist or wpscan_options.enumerate_usernames
|
||||
puts
|
||||
puts green('[+]') + ' Enumerating usernames ...'
|
||||
puts "#{green('[+]')} Enumerating usernames ..."
|
||||
|
||||
if wp_target.has_plugin?('stop-user-enumeration')
|
||||
puts "#{red('[!]')} Stop User Enumeration plugin detected, results might be empty. " \
|
||||
"However a bypass exists, see stop_user_enumeration_bypass.rb in #{File.expand_path(File.dirname(__FILE__))}"
|
||||
end
|
||||
|
||||
wp_users = WpUsers.aggressive_detection(wp_target,
|
||||
enum_options.merge(
|
||||
@@ -288,7 +309,7 @@ def main
|
||||
)
|
||||
|
||||
if wp_users.empty?
|
||||
puts 'We did not enumerate any usernames'
|
||||
puts "#{green('[+]')} We did not enumerate any usernames"
|
||||
|
||||
if wpscan_options.wordlist
|
||||
puts 'Try supplying your own username with the --username option'
|
||||
@@ -296,7 +317,7 @@ def main
|
||||
exit(1)
|
||||
end
|
||||
else
|
||||
puts green('[+]') + " We found the following #{wp_users.size} user/s:"
|
||||
puts "#{green('[+]')} Identified the following #{wp_users.size} user/s:"
|
||||
wp_users.output(margin_left: ' ' * 4)
|
||||
end
|
||||
|
||||
@@ -313,14 +334,14 @@ def main
|
||||
protection_plugin = wp_target.login_protection_plugin()
|
||||
|
||||
puts
|
||||
puts "The plugin #{protection_plugin.name} has been detected. It might record the IP and timestamp of every failed login and/or prevent brute forcing altogether. Not a good idea for brute forcing!"
|
||||
print '[?] Do you want to start the brute force anyway ? [y/n] '
|
||||
puts "#{red('[!]')} The plugin #{protection_plugin.name} has been detected. It might record the IP and timestamp of every failed login and/or prevent brute forcing altogether. Not a good idea for brute forcing!"
|
||||
puts '[?] Do you want to start the brute force anyway ? [Y]es [N]o, default: [N]'
|
||||
|
||||
bruteforce = false if Readline.readline !~ /^y/i
|
||||
bruteforce = false if wpscan_options.batch || Readline.readline !~ /^y/i
|
||||
end
|
||||
puts
|
||||
|
||||
if bruteforce
|
||||
puts green('[+]') + ' Starting the password brute forcer'
|
||||
puts "#{green('[+]')} Starting the password brute forcer"
|
||||
|
||||
begin
|
||||
wp_users.brute_force(
|
||||
@@ -333,14 +354,14 @@ def main
|
||||
wp_users.output(show_password: true, margin_left: ' ' * 2)
|
||||
end
|
||||
else
|
||||
puts 'Brute forcing aborted'
|
||||
puts "#{red('[!]')} Brute forcing aborted"
|
||||
end
|
||||
end
|
||||
|
||||
stop_time = Time.now
|
||||
elapsed = stop_time - start_time
|
||||
used_memory = get_memory_usage - start_memory
|
||||
|
||||
|
||||
puts
|
||||
puts green("[+] Finished: #{stop_time.asctime}")
|
||||
puts green("[+] Memory used: #{used_memory.bytes_to_human}")
|
||||
@@ -348,12 +369,12 @@ def main
|
||||
exit(0) # must exit!
|
||||
|
||||
rescue SystemExit, Interrupt
|
||||
puts 'Exiting!'
|
||||
|
||||
rescue => e
|
||||
if e.backtrace[0] =~ /main/
|
||||
puts red(e.message)
|
||||
else
|
||||
puts red("[ERROR] #{e.message}")
|
||||
puts
|
||||
puts red(e.message)
|
||||
|
||||
if wpscan_options && wpscan_options.verbose
|
||||
puts red('Trace:')
|
||||
puts red(e.backtrace.join("\n"))
|
||||
end
|
||||
|
||||
@@ -18,7 +18,8 @@ begin
|
||||
plugins.register(
|
||||
CheckerPlugin.new,
|
||||
ListGeneratorPlugin.new,
|
||||
StatsPlugin.new
|
||||
StatsPlugin.new,
|
||||
CheckerSpelling.new
|
||||
)
|
||||
|
||||
options = option_parser.results
|
||||
|
||||
Reference in New Issue
Block a user