require 'spec_helper' require 'rex/version' require 'rex/text' # rubocop:disable Lint/DeprecatedGemVersion RSpec.describe Rex::Exploit::ViewState do let(:data) { Random.new.bytes(rand(10..100)) } let(:key) { Random.new.bytes(20) } context 'when the algorithm is SHA-1' do let(:algo) { 'sha1' } describe '.decode_viewstate' do let(:encoded) { described_class.generate_viewstate(data, algo: algo, key: key) } it 'returns the data and HMAC' do decoded = described_class.decode_viewstate(encoded, algo: algo) expect(decoded).to be_a Hash expect(decoded[:data]).to eq data expect(decoded[:hmac]).to eq described_class.generate_viewstate_hmac(data, algo: algo, key: key) end end describe '.generate_viewstate' do it 'generates the HMAC signature' do expect(described_class).to receive(:generate_viewstate_hmac).with(data, algo: algo, key: key).and_call_original described_class.generate_viewstate(data, algo: algo, key: key) end it 'generates a Base64 encoded blob' do viewstate = described_class.generate_viewstate(data, algo: algo, key: key) debase64ed = Rex::Text.decode_base64(viewstate) expect(debase64ed).to eq data + described_class.generate_viewstate_hmac(data, algo: algo, key: key) end end describe '.generate_viewstate_hmac' do it 'delegates to OpenSSL::HMAC' do expect(OpenSSL::HMAC).to receive(:digest).with(algo, key,data) described_class.generate_viewstate_hmac(data, algo: algo, key: key) end it 'generates a 20 byte HMAC' do hmac = described_class.generate_viewstate_hmac(data, algo: algo, key: key) expect(hmac.bytesize).to eq 20 end end describe '.is_viewstate_valid?' do let(:encoded) { described_class.generate_viewstate(data, algo: algo, key: key) } it 'raises an Error when it can not be decoded' do # use key.length / 2 to guarantee there is not enough data for the key to be found expect { described_class.is_viewstate_valid?(Rex::Text.encode_base64('A' * (key.length / 2))) }.to raise_error(described_class::Error) end it 'returns true for the correct key' do expect(described_class.is_viewstate_valid?(encoded, algo: algo, key: key)).to be_truthy end it 'returns false for the incorrect key' do expect(described_class.is_viewstate_valid?(encoded, algo: algo, key: key + '#')).to be_falsey end end end end