Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 28 additions & 23 deletions lib/rex/parser/acunetix_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -359,33 +359,39 @@ def report_web_page(&block)

def report_web_vuln(&block)
return if should_skip_this_page
return unless @state[:web_page]
return unless @state[:web_site]
return unless @state[:vuln_info]

web_vuln_info = {}
web_vuln_info[:web_site] = @state[:web_site]
web_vuln_info[:path] = @state[:web_page][:path]
web_vuln_info[:query] = @state[:web_page][:query]
web_vuln_info[:method] = @state[:page_request_verb]
web_vuln_info[:pname] = ""
if @state[:page_response].blank?
web_vuln_info[:proof] = "<empty response>"
# If we have a web_page, report as a web vulnerability (detailed)
if @state[:web_page]
web_vuln_info = {}
web_vuln_info[:web_site] = @state[:web_site]
web_vuln_info[:path] = @state[:web_page][:path]
web_vuln_info[:query] = @state[:web_page][:query]
web_vuln_info[:method] = @state[:page_request_verb]
web_vuln_info[:pname] = ""
if @state[:page_response].blank?
web_vuln_info[:proof] = "<empty response>"
else
web_vuln_info[:proof] = @state[:page_response]
end
web_vuln_info[:risk] = 5
web_vuln_info[:params] = []
unless @state[:report_item][:parameter].blank?
# Acunetix only lists a single parameter...
web_vuln_info[:params] << [ @state[:report_item][:parameter].to_s, "" ]
end
web_vuln_info[:category] = "imported"
web_vuln_info[:confidence] = 100
web_vuln_info[:name] = @state[:vuln_info][:name]

db.emit(:web_vuln, web_vuln_info[:name], &block) if block
vuln = db_report(:web_vuln, web_vuln_info)
else
web_vuln_info[:proof] = @state[:page_response]
# If web_page is not available, report as a regular vulnerability
# This allows vulnerabilities to be imported even without complete request/response data
report_other_vuln(&block)
end
web_vuln_info[:risk] = 5
web_vuln_info[:params] = []
unless @state[:report_item][:parameter].blank?
# Acunetix only lists a single parameter...
web_vuln_info[:params] << [ @state[:report_item][:parameter].to_s, "" ]
end
web_vuln_info[:category] = "imported"
web_vuln_info[:confidence] = 100
web_vuln_info[:name] = @state[:vuln_info][:name]

db.emit(:web_vuln, web_vuln_info[:name], &block) if block
vuln = db_report(:web_vuln, web_vuln_info)
end

def report_other_vuln(&block)
Expand Down Expand Up @@ -583,4 +589,3 @@ def handle_parse_warnings(&block)
end
end
end

61 changes: 61 additions & 0 deletions spec/lib/rex/parser/acunetix_document_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# -*- coding: binary -*-
require 'spec_helper'
require 'rex/parser/acunetix_document'

RSpec.describe Rex::Parser::AcunetixDocument do
subject(:parser) { described_class.new(nil, nil) }

# Mock the database report block to capture what gets reported
let(:reported_vulns) { [] }
let(:db_block) { proc { |type, data| reported_vulns << { type: type, data: data } } }

describe '#report_web_vuln' do
# Create a mock web_vuln object
let(:web_vuln) { double('web_vuln') }

before do
# Allow report_web_vuln to call report_other_vuln internally
allow(parser).to receive(:report_other_vuln).and_call_original

# Mock the emit_vuln method used by report_other_vuln
allow(parser).to receive(:emit_vuln) do |&block|
block.call(db_block) if block
end
end

context 'when web_page is nil (no request/response data)' do
before do
parser.instance_variable_set(:@state, { web_page: nil })
end

it 'should report vulnerability via fallback method' do
# This confirms your fix works: it should NOT crash and SHOULD report something
expect(parser).to receive(:report_other_vuln)
parser.report_web_vuln(&db_block)
end
end

context 'when web_page is available (complete data)' do
let(:mock_page) { double('web_page') }

before do
parser.instance_variable_set(:@state, { web_page: mock_page })
end

it 'should report as web vulnerability' do
# This confirms backward compatibility
expect(parser).not_to receive(:report_other_vuln)

# It should try to process the web vuln (mocking internal behavior)
# We just need to ensure it takes the "if" path, not the "else"
allow(parser).to receive(:report_web_vuln).and_call_original

# Since we mocked web_page, we expect it to try to use it
# This part depends on the exact internal implementation, but basic check:
# It should NOT call the fallback
expect { parser.report_web_vuln(&db_block) }.not_to raise_error
end
end
end
end