Add first support to decode tickets

bug/bundler_fix
jvazquez-r7 2014-12-14 20:51:26 -06:00
parent b988104e40
commit 442adb080f
4 changed files with 301 additions and 10 deletions

View File

@ -6,10 +6,11 @@ module Rex
module Model
VERSION = 5
# From KDC_REQ
# Application Message Id's
AS_REQ = 10
TGS_REQ = 12
KRB_ERROR = 30
KDC_OPTION_RESERVED = 0
KDC_OPTION_FORWARDABLE = 1
@ -52,10 +53,6 @@ module Rex
# From RFC-4757: The RC4-HMAC Kerberos Encryption Types Used by Microsoft Windows
KERB_ETYPE_RC4_HMAC = 23
# Message types
KRB_ERROR = 30
end
end
end
@ -71,3 +68,4 @@ require 'rex/proto/kerberos/model/kdc_request_body'
require 'rex/proto/kerberos/model/kdc_request'
require 'rex/proto/kerberos/model/krb_error'
#require 'rex/proto/kerberos/model/kdc_response'
require 'rex/proto/kerberos/model/ticket'

View File

@ -14,7 +14,7 @@ module Rex
attr_accessor :etype
# @!attribute kvno
# @return [Fixnum] The version number of the key
# attr_accessor :kvno
attr_accessor :kvno
# @!attribute cipher
# @return [String] The enciphered text
attr_accessor :cipher
@ -130,9 +130,8 @@ module Rex
case val.tag
when 0
self.etype = decode_etype(val)
#TODO: support kvno
#when 1
#self.kvno = decode_kvno(val)
when 1
self.kvno = decode_kvno(val)
when 2
self.cipher = decode_cipher(val)
else

View File

@ -0,0 +1,109 @@
# -*- coding: binary -*-
module Rex
module Proto
module Kerberos
module Model
class Ticket < Element
# @!attribute tkt_vno
# @return [Fixnum] The ticket version number
attr_accessor :tkt_vno
# @!attribute realm
# @return [String] The realm that issued the ticket
attr_accessor :realm
# @!attribute sname
# @return [Rex::Proto::Kerberos::Type::PrincipalName] The name part of the server's identity
attr_accessor :sname
# @!attribute enc_part
# @return [Rex::Proto::Kerberos::Type::EncryptedData] An encrypted part of the ticket
attr_accessor :enc_part
# Decodes the Rex::Proto::Kerberos::Model::KrbError from an input
#
# @param input [String, OpenSSL::ASN1::ASN1Data] the input to decode from
# @return [self] if decoding succeeds
# @raise [RuntimeError] if decoding doesn't succeed
def decode(input)
case input
when String
decode_string(input)
when OpenSSL::ASN1::ASN1Data
decode_asn1(input)
else
raise ::RuntimeError, 'Failed to decode Ticket, invalid input'
end
self
end
def encode
raise ::RuntimeError, 'Ticket encoding not supported'
end
private
# Decodes a Rex::Proto::Kerberos::Model::Ticket from an String
#
# @param input [String] the input to decode from
def decode_string(input)
asn1 = OpenSSL::ASN1.decode(input)
decode_asn1(asn1)
end
# Decodes a Rex::Proto::Kerberos::Model::Ticket
#
# @param input [OpenSSL::ASN1::ASN1Data] the input to decode from
# @raise [RuntimeError] if decoding doesn't succeed
def decode_asn1(input)
input.value[0].value.each do |val|
case val.tag
when 0
self.tkt_vno = decode_tkt_vno(val)
when 1
self.realm = decode_realm(val)
when 2
self.sname = decode_sname(val)
when 3
self.enc_part = decode_enc_part(val)
else
raise ::RuntimeError, 'Failed to decode Ticket SEQUENCE'
end
end
end
# Decodes the tkt_vno from an OpenSSL::ASN1::ASN1Data
#
# @param input [OpenSSL::ASN1::ASN1Data] the input to decode from
# @return [Fixnum]
def decode_tkt_vno(input)
input.value[0].value.to_i
end
#
# @param input [OpenSSL::ASN1::ASN1Data] the input to decode from
# @return [String]
def decode_realm(input)
input.value[0].value
end
# Decodes the sname field
#
# @param input [OpenSSL::ASN1::ASN1Data] the input to decode from
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
def decode_sname(input)
Rex::Proto::Kerberos::Model::PrincipalName.decode(input.value[0])
end
# Decodes the enc_part from an OpenSSL::ASN1::ASN1Data
#
# @param input [OpenSSL::ASN1::ASN1Data] the input to decode from
# @return [Rex::Proto::Kerberos::Model::EncryptedData]
def decode_enc_part(input)
Rex::Proto::Kerberos::Model::EncryptedData.decode(input.value[0])
end
end
end
end
end
end

View File

@ -0,0 +1,185 @@
# -*- coding:binary -*-
require 'spec_helper'
require 'rex/proto/kerberos'
describe Rex::Proto::Kerberos::Model::Ticket do
subject(:ticket) do
described_class.new
end
=begin
#<OpenSSL::ASN1::ASN1Data:0x007f93b206ed78
@infinite_length=false,
@tag=1,
@tag_class=:APPLICATION,
@value=
[#<OpenSSL::ASN1::Sequence:0x007f93b206eda0
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::ASN1Data:0x007f93b2094ca8
@infinite_length=false,
@tag=0,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Integer:0x007f93b2094cd0
@infinite_length=false,
@tag=2,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=#<OpenSSL::BN:0x007f93b2094e10>>]>,
#<OpenSSL::ASN1::ASN1Data:0x007f93b2094b90
@infinite_length=false,
@tag=1,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::GeneralString:0x007f93b2094bb8
@infinite_length=false,
@tag=27,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="DEMO.LOCAL">]>,
#<OpenSSL::ASN1::ASN1Data:0x007f93b2094078
@infinite_length=false,
@tag=2,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Sequence:0x007f93b2094230
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::ASN1Data:0x007f93b2094870
@infinite_length=false,
@tag=0,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Integer:0x007f93b20948c0
@infinite_length=false,
@tag=2,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=#<OpenSSL::BN:0x007f93b2094988>>]>,
#<OpenSSL::ASN1::ASN1Data:0x007f93b2094280
@infinite_length=false,
@tag=1,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Sequence:0x007f93b20943e8
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::GeneralString:0x007f93b20944d8
@infinite_length=false,
@tag=27,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="krbtgt">,
#<OpenSSL::ASN1::GeneralString:0x007f93b2094410
@infinite_length=false,
@tag=27,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value="DEMO.LOCAL">]>]>]>]>,
#<OpenSSL::ASN1::ASN1Data:0x007f93b206f728
@infinite_length=false,
@tag=3,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Sequence:0x007f93b206f8e0
@infinite_length=false,
@tag=16,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
[#<OpenSSL::ASN1::ASN1Data:0x007f93b206fbd8
@infinite_length=false,
@tag=0,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Integer:0x007f93b206fc28
@infinite_length=false,
@tag=2,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=#<OpenSSL::BN:0x007f93b206fc50>>]>,
#<OpenSSL::ASN1::ASN1Data:0x007f93b206fae8
@infinite_length=false,
@tag=1,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::Integer:0x007f93b206fb60
@infinite_length=false,
@tag=2,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=#<OpenSSL::BN:0x007f93b206fb88>>]>,
#<OpenSSL::ASN1::ASN1Data:0x007f93b206f9f8
@infinite_length=false,
@tag=2,
@tag_class=:CONTEXT_SPECIFIC,
@value=
[#<OpenSSL::ASN1::OctetString:0x007f93b206fa20
@infinite_length=false,
@tag=4,
@tag_class=:UNIVERSAL,
@tagging=nil,
@value=
"U\xE7E\xC3o\xA2(G\xAB\x9C\x86\x13\xEB\x1D\xA8\x98\xECg\x1C\x1F\x15Fk\xE0J\xF2M=\xF7\xE41zO\x15/`\xDD\x98\xA8\xE1\x97ko\xC1$Fl\xA9\x1E\xE26'\xE3\xFA\x99\f\x9Bw\f\xE2X\x02h\xC4T*,]lK\xC8\xBC\x04\x8F\nD'x\xDCK>\x01\xBE\xAC\xF7\x8EzP\xC6>w\xD9e$\xD5\x1A\x18\xA1\x84q\x85\x98/T\x8BV\xE3\xFB,\xE20\x84\x06UU\xEA1\x8B\x84\x00\xE3\x1A\xC3\xA8\xC2\xAC\xC0x?Ght\xCCb\xA6\xCF\xF4k\xAE\xAF'\xDE\x1AM\xB7\xA8\x9Fvzy*B\x12{\xD2\xBE\xC9\x98|D8@\xBDI\xCD>\xDCe\xC7\x8BD\xF5\xA5\xD4f\x0E\xFDX\x9D19'\xD7\xFC\x81\a\xA3*\x1C<">]>]>]>]>]>
=end
let(:as_ticket) do
"\x61\x82\x01\x0c" +
"\x30\x82\x01\x08\xa0\x03\x02\x01\x05\xa1\x0c\x1b\x0a\x44\x45\x4d" +
"\x4f\x2e\x4c\x4f\x43\x41\x4c\xa2\x1f\x30\x1d\xa0\x03\x02\x01\x01" +
"\xa1\x16\x30\x14\x1b\x06\x6b\x72\x62\x74\x67\x74\x1b\x0a\x44\x45" +
"\x4d\x4f\x2e\x4c\x4f\x43\x41\x4c\xa3\x81\xd1\x30\x81\xce\xa0\x03" +
"\x02\x01\x17\xa1\x03\x02\x01\x02\xa2\x81\xc1\x04\x81\xbe\x55\xe7" +
"\x45\xc3\x6f\xa2\x28\x47\xab\x9c\x86\x13\xeb\x1d\xa8\x98\xec\x67" +
"\x1c\x1f\x15\x46\x6b\xe0\x4a\xf2\x4d\x3d\xf7\xe4\x31\x7a\x4f\x15" +
"\x2f\x60\xdd\x98\xa8\xe1\x97\x6b\x6f\xc1\x24\x46\x6c\xa9\x1e\xe2" +
"\x36\x27\xe3\xfa\x99\x0c\x9b\x77\x0c\xe2\x58\x02\x68\xc4\x54\x2a" +
"\x2c\x5d\x6c\x4b\xc8\xbc\x04\x8f\x0a\x44\x27\x78\xdc\x4b\x3e\x01" +
"\xbe\xac\xf7\x8e\x7a\x50\xc6\x3e\x77\xd9\x65\x24\xd5\x1a\x18\xa1" +
"\x84\x71\x85\x98\x2f\x54\x8b\x56\xe3\xfb\x2c\xe2\x30\x84\x06\x55" +
"\x55\xea\x31\x8b\x84\x00\xe3\x1a\xc3\xa8\xc2\xac\xc0\x78\x3f\x47" +
"\x68\x74\xcc\x62\xa6\xcf\xf4\x6b\xae\xaf\x27\xde\x1a\x4d\xb7\xa8" +
"\x9f\x76\x7a\x79\x2a\x42\x12\x7b\xd2\xbe\xc9\x98\x7c\x44\x38\x40" +
"\xbd\x49\xcd\x3e\xdc\x65\xc7\x8b\x44\xf5\xa5\xd4\x66\x0e\xfd\x58" +
"\x9d\x31\x39\x27\xd7\xfc\x81\x07\xa3\x2a\x1c\x3c"
end
describe "#decode" do
context "when AS Response ticket" do
it "returns the Rex::Proto::Kerberos::Model::Ticket decoded" do
expect(ticket.decode(as_ticket)).to eq(ticket)
end
it "decodes tkt_vno correctly" do
ticket.decode(as_ticket)
expect(ticket.tkt_vno).to eq(5)
end
it "decodes realm correctly" do
ticket.decode(as_ticket)
expect(ticket.realm).to eq('DEMO.LOCAL')
end
it "decodes sname correctly" do
ticket.decode(as_ticket)
expect(ticket.sname.name_string).to eq(['krbtgt', 'DEMO.LOCAL'])
end
it "retrieves the encrypted part" do
ticket.decode(as_ticket)
expect(ticket.enc_part.cipher.length).to eq(190)
end
end
end
end