Update upstream source from tag 'upstream/0.8.4'
Update to upstream version '0.8.4'
with Debian dir c6a215b7e4b78bc95137ba2d63f0fac51623ff2d
Sophie Brun
4 years ago
0 | name: Build | |
1 | ||
2 | on: [push, pull_request] | |
3 | ||
4 | jobs: | |
5 | build: | |
6 | ||
7 | runs-on: ubuntu-latest | |
8 | ||
9 | strategy: | |
10 | matrix: | |
11 | ruby: [2.4, 2.5, 2.6, 2.7] | |
12 | ||
13 | steps: | |
14 | - name: Checkout code | |
15 | uses: actions/checkout@v1 | |
16 | ||
17 | - name: Set up Ruby ${{ matrix.ruby }} | |
18 | uses: actions/setup-ruby@v1 | |
19 | with: | |
20 | ruby-version: ${{ matrix.ruby }} | |
21 | ||
22 | - name: Restore GEM cache | |
23 | uses: actions/cache@v1 | |
24 | with: | |
25 | path: vendor/bundle | |
26 | key: ${{ runner.os }}-${{ matrix.ruby }}-gem-${{ hashFiles('**/cms_scanner.gemspec') }} | |
27 | restore-keys: | | |
28 | ${{ runner.os }}-${{ matrix.ruby }}-gem- | |
29 | ||
30 | - name: Install GEMs | |
31 | run: | | |
32 | gem install bundler | |
33 | bundle config force_ruby_platform true | |
34 | bundle config path vendor/bundle | |
35 | bundle install --jobs 4 --retry 3 | |
36 | ||
37 | - name: rubocop | |
38 | run: | | |
39 | bundle exec rubocop | |
40 | ||
41 | - name: rspec | |
42 | run: | | |
43 | bundle exec rspec | |
44 | ||
45 | - name: Coveralls | |
46 | uses: coverallsapp/github-action@master | |
47 | with: | |
48 | github-token: ${{ secrets.GITHUB_TOKEN }} |
0 | ||
1 | if ENV['GITHUB_ACTION'] | |
2 | require 'simplecov-lcov' | |
3 | ||
4 | SimpleCov::Formatter::LcovFormatter.config do |c| | |
5 | c.single_report_path = 'coverage/lcov.info' | |
6 | c.report_with_single_file = true | |
7 | end | |
8 | ||
9 | SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter | |
10 | end | |
11 | ||
0 | 12 | SimpleCov.start do |
13 | enable_coverage :branch # Only supported for Ruby >= 2.5 | |
14 | ||
1 | 15 | add_filter '/example/' |
2 | 16 | add_filter '/spec/' |
3 | 17 | add_filter 'helper' |
4 | end⏎ | |
18 | end |
0 | language: ruby | |
1 | sudo: false | |
2 | cache: bundler | |
3 | rvm: | |
4 | - 2.4.1 | |
5 | - 2.4.2 | |
6 | - 2.4.3 | |
7 | - 2.4.4 | |
8 | - 2.4.5 | |
9 | - 2.4.6 | |
10 | - 2.4.7 | |
11 | - 2.4.8 | |
12 | - 2.4.9 | |
13 | - 2.5.0 | |
14 | - 2.5.1 | |
15 | - 2.5.2 | |
16 | - 2.5.3 | |
17 | - 2.5.4 | |
18 | - 2.5.5 | |
19 | - 2.5.6 | |
20 | - 2.5.7 | |
21 | - 2.6.0 | |
22 | - 2.6.1 | |
23 | - 2.6.2 | |
24 | - 2.6.3 | |
25 | - 2.6.4 | |
26 | - 2.6.5 | |
27 | - 2.7.0 | |
28 | script: | |
29 | - bundle exec rubocop | |
30 | - bundle exec rspec | |
31 | notifications: | |
32 | email: | |
33 | - [email protected] |
0 | 0 | # CMSScanner |
1 | 1 | |
2 | 2 | [![Gem Version](https://badge.fury.io/rb/cms_scanner.svg)](https://badge.fury.io/rb/cms_scanner) |
3 | [![Build Status](https://travis-ci.org/wpscanteam/CMSScanner.svg?branch=master)](https://travis-ci.org/wpscanteam/CMSScanner) | |
3 | ![Build](https://github.com/wpscanteam/CMSScanner/workflows/Build/badge.svg) | |
4 | 4 | [![Coverage Status](https://img.shields.io/coveralls/wpscanteam/CMSScanner.svg)](https://coveralls.io/r/wpscanteam/CMSScanner) |
5 | 5 | [![Code Climate](https://api.codeclimate.com/v1/badges/b90b7f9f6982792ef8d6/maintainability)](https://codeclimate.com/github/wpscanteam/CMSScanner/maintainability) |
6 | 6 |
13 | 13 | require_relative 'models/interesting_finding' |
14 | 14 | require_relative 'models/robots_txt' |
15 | 15 | require_relative 'models/fantastico_fileslist' |
16 | require_relative 'models/search_replace_db_2' | |
16 | 17 | require_relative 'models/headers' |
17 | 18 | require_relative 'models/xml_rpc' |
18 | 19 | require_relative 'models/version' |
62 | 62 | @start_time = Time.now |
63 | 63 | @start_memory = NS.start_memory |
64 | 64 | |
65 | output('started', url: target.url, effective_url: target.homepage_url) | |
65 | output('started', url: target.url, ip: target.ip, effective_url: target.homepage_url) | |
66 | 66 | end |
67 | 67 | |
68 | 68 | def after_scan |
10 | 10 | |
11 | 11 | return unless /by interconnect/i.match?(target.head_and_get(path).body) |
12 | 12 | |
13 | NS::Model::InterestingFinding.new(target.url(path), | |
14 | confidence: 100, | |
15 | found_by: found_by, | |
16 | references: references) | |
17 | end | |
18 | ||
19 | def references | |
20 | { url: 'https://interconnectit.com/products/search-and-replace-for-wordpress-databases/' } | |
13 | NS::Model::SearchReplaceDB2.new(target.url(path), confidence: 100, found_by: found_by) | |
21 | 14 | end |
22 | 15 | end |
23 | 16 | end |
34 | 34 | |
35 | 35 | potential_urls << url |
36 | 36 | |
37 | return NS::Model::XMLRPC.new(url, confidence: 30, | |
38 | found_by: 'Link Tag (Passive Detection)') | |
37 | return NS::Model::XMLRPC.new(url, confidence: 30, found_by: 'Link Tag (Passive Detection)') | |
39 | 38 | end |
40 | 39 | nil |
41 | 40 | end |
51 | 50 | |
52 | 51 | next unless /<methodResponse>/i.match?(res&.body) |
53 | 52 | |
54 | return NS::Model::XMLRPC.new(potential_url, | |
55 | confidence: 100, | |
56 | found_by: DIRECT_ACCESS) | |
53 | return NS::Model::XMLRPC.new(potential_url, confidence: 100, found_by: DIRECT_ACCESS) | |
57 | 54 | end |
58 | 55 | nil |
59 | 56 | end |
16 | 16 | end |
17 | 17 | |
18 | 18 | def references |
19 | { url: ['http://www.acunetix.com/vulnerabilities/fantastico-fileslist/'] } | |
19 | @references ||= { url: ['http://www.acunetix.com/vulnerabilities/fantastico-fileslist/'] } | |
20 | 20 | end |
21 | 21 | end |
22 | 22 | end |
33 | 33 | x-webkit-csp x-xss-protection |
34 | 34 | ] |
35 | 35 | end |
36 | ||
37 | # @return [ String ] | |
38 | def to_s | |
39 | @to_s ||= 'Headers' | |
40 | end | |
36 | 41 | end |
37 | 42 | end |
38 | 43 | end |
0 | # frozen_string_literal: true | |
1 | ||
2 | module CMSScanner | |
3 | module Model | |
4 | # SearchReplaceDB2 | |
5 | class SearchReplaceDB2 < InterestingFinding | |
6 | def references | |
7 | @references ||= { url: ['https://interconnectit.com/products/search-and-replace-for-wordpress-databases/'] } | |
8 | end | |
9 | end | |
10 | end | |
11 | end |
3 | 3 | module Model |
4 | 4 | # XML RPC |
5 | 5 | class XMLRPC < InterestingFinding |
6 | # @return [ String ] | |
7 | def to_s | |
8 | @to_s ||= "XML-RPC seems to be enabled: #{url}" | |
9 | end | |
10 | ||
6 | 11 | # @return [ Browser ] |
7 | 12 | def browser |
8 | 13 | @browser ||= NS::Browser.instance |
0 | <%= info_icon %> URL: <%= @url %> | |
0 | <%= info_icon %> URL: <%= @url %> [<%= @ip %>] | |
1 | 1 | <% if @url != @effective_url -%> |
2 | 2 | <%= info_icon %> Effective URL: <%= @effective_url %> |
3 | 3 | <% end -%> |
0 | 0 | "start_time": <%= @start_time.to_i %>, |
1 | 1 | "start_memory": <%= @start_memory.to_i %>, |
2 | 2 | "target_url": <%= @url.to_s.to_json %>, |
3 | "target_ip": <%= @ip.to_s.to_json %>, | |
3 | 4 | "effective_url": <%= @effective_url.to_s.to_json %>,⏎ |
19 | 19 | s.require_paths = ['lib'] |
20 | 20 | |
21 | 21 | s.add_dependency 'get_process_mem', '~> 0.2.5' |
22 | s.add_dependency 'nokogiri', '~> 1.10.4' | |
22 | s.add_dependency 'nokogiri', '~> 1.10.8' | |
23 | 23 | s.add_dependency 'opt_parse_validator', '~> 1.8.1' |
24 | s.add_dependency 'public_suffix', '>= 3.0', '< 4.1' | |
24 | s.add_dependency 'public_suffix', '~> 4.0.3' | |
25 | 25 | s.add_dependency 'ruby-progressbar', '~> 1.10.0' |
26 | 26 | s.add_dependency 'typhoeus', '~> 1.3.0' |
27 | 27 | s.add_dependency 'xmlrpc', '~> 0.3' |
30 | 30 | s.add_dependency 'sys-proctable', '~> 1.2.2' # Required by get_process_mem for Windows OS. |
31 | 31 | |
32 | 32 | s.add_development_dependency 'bundler', '>= 1.6' |
33 | s.add_development_dependency 'coveralls', '~> 0.8.0' | |
34 | 33 | s.add_development_dependency 'rake', '~> 13.0' |
35 | 34 | s.add_development_dependency 'rspec', '~> 3.9.0' |
36 | 35 | s.add_development_dependency 'rspec-its', '~> 1.3.0' |
37 | s.add_development_dependency 'rubocop', '~> 0.78.0' | |
36 | s.add_development_dependency 'rubocop', '~> 0.80.0' | |
38 | 37 | s.add_development_dependency 'rubocop-performance', '~> 1.5.0' |
39 | s.add_development_dependency 'simplecov', '~> 0.16.1' | |
40 | s.add_development_dependency 'webmock', '~> 3.7.0' | |
38 | s.add_development_dependency 'simplecov', '~> 0.18.2' | |
39 | s.add_development_dependency 'simplecov-lcov', '~> 0.8.0' | |
40 | s.add_development_dependency 'webmock', '~> 3.8.0' | |
41 | 41 | end |
37 | 37 | Typhoeus::Request.new(url, request_params(params)) |
38 | 38 | end |
39 | 39 | |
40 | # @return [ Hash ] | |
41 | def typhoeus_to_browser_opts | |
42 | { connecttimeout: :connect_timeout, cache_ttl: :cache_ttl, | |
43 | proxy: :proxy, timeout: :request_timeout, cookiejar: :cookie_jar, | |
44 | cookiefile: :cookie_jar, cookie: :cookie_string } | |
45 | end | |
46 | ||
47 | # @return [ Hash ] | |
48 | def default_request_params | |
49 | params = { | |
50 | headers: { 'User-Agent' => user_agent, 'Referer' => url }.merge(headers || {}), | |
51 | accept_encoding: 'gzip, deflate', | |
52 | method: :get | |
53 | } | |
40 | # @return [ Hash ] The request params used to connect tothe target as well as potential other systems such as API | |
41 | def default_connect_request_params | |
42 | params = {} | |
54 | 43 | |
55 | 44 | if disable_tls_checks |
56 | 45 | # See http://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYHOST.html |
60 | 49 | params[:sslversion] = :tlsv1 |
61 | 50 | end |
62 | 51 | |
63 | typhoeus_to_browser_opts.each do |typhoeus_opt, browser_opt| | |
52 | { | |
53 | connecttimeout: :connect_timeout, cache_ttl: :cache_ttl, | |
54 | proxy: :proxy, timeout: :request_timeout | |
55 | }.each do |typhoeus_opt, browser_opt| | |
56 | attr_value = public_send(browser_opt) | |
57 | params[typhoeus_opt] = attr_value unless attr_value.nil? | |
58 | end | |
59 | ||
60 | params | |
61 | end | |
62 | ||
63 | # @return [ Hash ] | |
64 | # The params are not cached (using @params ||= for example), so that they are set accordingly if updated | |
65 | # by a controller/other piece of code | |
66 | def default_request_params | |
67 | params = default_connect_request_params.merge( | |
68 | headers: { 'User-Agent' => user_agent, 'Referer' => url }.merge(headers || {}), | |
69 | accept_encoding: 'gzip, deflate', | |
70 | method: :get | |
71 | ) | |
72 | ||
73 | { cookiejar: :cookie_jar, cookiefile: :cookie_jar, cookie: :cookie_string }.each do |typhoeus_opt, browser_opt| | |
64 | 74 | attr_value = public_send(browser_opt) |
65 | 75 | params[typhoeus_opt] = attr_value unless attr_value.nil? |
66 | 76 | end |
24 | 24 | # @yield [ Addressable::URI, Nokogiri::XML::Element ] The in scope url and its associated tag |
25 | 25 | # |
26 | 26 | # @return [ Array<Addressable::URI> ] The in scope absolute URIs detected in the response's body |
27 | # | |
28 | # @note It is highly recommended to use the xpath parameter to focus on the uris needed, as this method can be quite | |
29 | # time consuming when there are a lof of uris to check | |
27 | 30 | def in_scope_uris(res, xpath = '//@href|//@src|//@data-src') |
28 | 31 | found = [] |
29 | 32 |
91 | 91 | # @yield [ Addressable::URI, Nokogiri::XML::Element ] The url and its associated tag |
92 | 92 | # |
93 | 93 | # @return [ Array<Addressable::URI> ] The absolute URIs detected in the response's body from the HTML tags |
94 | # | |
95 | # @note It is highly recommended to use the xpath parameter to focus on the uris needed, as this method can be quite | |
96 | # time consuming when there are a lof of uris to check | |
94 | 97 | def uris_from_page(page = nil, xpath = '//@href|//@src|//@data-src') |
95 | 98 | page = NS::Browser.get(url(page)) unless page.is_a?(Typhoeus::Response) |
96 | 99 | found = [] |
29 | 29 | return @uri.to_s unless path |
30 | 30 | |
31 | 31 | @uri.join(Addressable::URI.encode(path).gsub('#', '%23')).to_s |
32 | end | |
33 | ||
34 | # @return [ String ] The IP address of the target | |
35 | def ip | |
36 | @ip ||= IPSocket.getaddress(uri.host) | |
37 | rescue SocketError | |
38 | 'Unknown' | |
32 | 39 | end |
33 | 40 | |
34 | 41 | attr_writer :homepage_res |
15 | 15 | require 'uri' |
16 | 16 | require 'fileutils' |
17 | 17 | require 'pathname' |
18 | require 'socket' | |
18 | 19 | require 'timeout' |
19 | 20 | require 'xmlrpc/client' |
20 | 21 | # Monkey Patches/Fixes |
34 | 34 | let(:body) { File.read(fixtures.join('searchreplacedb2.php')) } |
35 | 35 | |
36 | 36 | it 'returns the InterestingFinding object' do |
37 | expect(finder.aggressive).to eql CMSScanner::Model::InterestingFinding.new( | |
37 | expect(finder.aggressive).to eql CMSScanner::Model::SearchReplaceDB2.new( | |
38 | 38 | file_url, |
39 | 39 | confidence: 100, |
40 | 40 | found_by: 'Search Replace Db2 (Aggressive Detection)' |
7 | 7 | let(:headers) { {} } |
8 | 8 | |
9 | 9 | before { stub_request(:get, file.url).to_return(headers: headers) } |
10 | ||
11 | describe '#to_s' do | |
12 | its(:to_s) { should eql 'Headers' } | |
13 | end | |
10 | 14 | |
11 | 15 | describe '#known_headers' do |
12 | 16 | it 'does not contains dupliactes' do |
0 | # frozen_string_literal: true | |
1 | ||
2 | describe CMSScanner::Model::SearchReplaceDB2 do | |
3 | subject(:file) { described_class.new(url) } | |
4 | let(:url) { 'http://example.com/searchreplacedb2.php' } | |
5 | ||
6 | describe '#references' do | |
7 | its(:references) { should_not be_nil } | |
8 | end | |
9 | ||
10 | describe '#type' do | |
11 | its(:type) { should eql 'search_replace_db2' } | |
12 | end | |
13 | end |
6 | 6 | |
7 | 7 | describe '#type' do |
8 | 8 | its(:type) { should eql 'xmlrpc' } |
9 | end | |
10 | ||
11 | describe '#to_s' do | |
12 | its(:to_s) { should eql 'XML-RPC seems to be enabled: http://example.com/xmlrpc' } | |
9 | 13 | end |
10 | 14 | |
11 | 15 | describe '#method_call' do |
13 | 13 | let(:opts) { { show_progression: true } } |
14 | 14 | |
15 | 15 | it 'uses the default progress-bar output' do |
16 | expect(finder.progress_bar.send(:output)).to be_a ProgressBar::Outputs::Tty | |
16 | expected_bar_class = ENV['GITHUB_ACTION'] ? ProgressBar::Outputs::NonTty : ProgressBar::Outputs::Tty | |
17 | ||
18 | expect(finder.progress_bar.send(:output)).to be_a expected_bar_class | |
17 | 19 | end |
18 | 20 | end |
19 | 21 |
60 | 60 | expect(web_site.url('/sub/file.txt')).to eql 'http://e.org/sub/file.txt' |
61 | 61 | end |
62 | 62 | end |
63 | end | |
64 | end | |
65 | ||
66 | describe '#ip' do | |
67 | context 'when target host not known' do | |
68 | let(:url) { 'http://lab.local' } | |
69 | ||
70 | its(:ip) { should eql 'Unknown' } | |
71 | end | |
72 | ||
73 | context 'when target host known' do | |
74 | before { expect(IPSocket).to receive(:getaddress).and_return('127.0.0.1') } | |
75 | ||
76 | its(:ip) { should eql '127.0.0.1' } | |
63 | 77 | end |
64 | 78 | end |
65 | 79 |
0 | [+] URL: http://e.org/ | |
0 | [+] URL: http://e.org/ [127.0.0.1] | |
1 | 1 | [+] Started: Thu Oct 30 12:02:01 2014 |
2 | 2 |
1 | 1 | "start_time": 1414670521, |
2 | 2 | "start_memory": 10, |
3 | 3 | "target_url": "http://e.org/", |
4 | "target_ip": "127.0.0.1", | |
4 | 5 | "effective_url": "http://e.org/" |
5 | 6 | }⏎ |
0 | [+] URL: http://e.org/ | |
0 | [+] URL: http://e.org/ [127.0.0.1] | |
1 | 1 | [+] Effective URL: http://e.org/home |
2 | 2 | [+] Started: Thu Oct 30 12:02:01 2014 |
3 | 3 |
1 | 1 | "start_time": 1414670521, |
2 | 2 | "start_memory": 10, |
3 | 3 | "target_url": "http://e.org/", |
4 | "target_ip": "127.0.0.1", | |
4 | 5 | "effective_url": "http://e.org/home" |
5 | 6 | }⏎ |
2 | 2 | shared_examples 'App::Views::Core' do |
3 | 3 | let(:controller) { CMSScanner::Controller::Core.new } |
4 | 4 | let(:start) { Time.at(1_414_670_521).in_time_zone('Europe/London') } |
5 | let(:tpl_vars) { { url: target_url, start_time: start } } | |
5 | let(:tpl_vars) { { url: target_url, ip: '127.0.0.1', start_time: start } } | |
6 | 6 | |
7 | 7 | describe 'version' do |
8 | 8 | let(:view) { 'version' } |
1 | 1 | |
2 | 2 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) |
3 | 3 | |
4 | require 'simplecov' # Used filters are in /.simplecov | |
4 | require 'simplecov' # More config is defined in ./.simplecov | |
5 | 5 | require 'rspec/its' |
6 | 6 | require 'webmock/rspec' |
7 | 7 | require 'active_support/time' |
8 | ||
9 | if ENV['TRAVIS'] | |
10 | require 'coveralls' | |
11 | SimpleCov.formatter = Coveralls::SimpleCov::Formatter | |
12 | end | |
13 | 8 | |
14 | 9 | # See http://betterspecs.org/ |
15 | 10 | RSpec.configure do |config| |