Пример #1
0
    def sendSentinel(self):
        """
        State 1:  Send sentinel

           Cookie :  SESSSIONID=HandshakeID; ID=Tunnel_Tag

        HandshakeID = Sentinel+Nonce_Client
        """
        self.rc4_handshake_c2d = RC4.RC4(self.session_key)
        self.rc4_handshake_d2c = RC4.RC4(self.session_key)
        self.rc4_tunnel = RC4.RC4(self.session_key)

        # Filler text
        #
        plain_text = const.HTTPU_CLIENTHELLO

        auth_plain_text = '%s%s%s' % (self.encoder.digest(plain_text),
                                      const.HTTPU_HASHSEP, plain_text)

        cipher_text = self.rc4_handshake_c2d.update(auth_plain_text)

        # HTTP Request
        #
        req = http_util.create_http_req(self, cipher_text, self.handshake_ID,
                                        self.tunnel_tag.encode("hex"),
                                        self.host_name)

        self.transport.write(req)

        # New state
        #
        self.state = const.STATE_3_UNI
Пример #2
0
    def send_cipher_req(self, plain_text):
        """
        Create request containing encrypted, integrity checked
        data and send request on to decoy host
        """
        plain_text = str(self.sent_count) + ":" + plain_text

        auth_plain_text = '%s%s%s' % (self.encoder.digest(plain_text),
                                      const.HTTPU_HASHSEP, plain_text)

        url_padding = cb_random.gen_rand_bytes(self,
                                               const.URL_PADDING_BYTE_LEN)

        cipher_text = self.rc4_tunnel.update(auth_plain_text) + url_padding

        req = http_util.create_http_req(self, cipher_text, self.handshake_ID,
                                        self.tunnel_tag.encode("hex"),
                                        self.host_name)

        if self.state != const.STATE_0_UNI:
            self.sent_count += 1

        # Send request on to decoy host
        #
        self.transport.write(req)
Пример #3
0
    def dataReceived(self, data):
        """
        State 5.5:  Ready

          A.     URL :  SeqNum_C2D +
          B.            HMAC_Client( R2 ) +
          C.            E_Client( R2 )

          D.  Cookie :  SESSSIONID=Decoupled_ID

         R2 =  Salt_3        +
               SeqNum_C2D    +
               Decoupled_ID  +
               CovertData

        Sending covert data from client in http request
        """

        # A.  SeqNum_C2D
        #
        self.dst_p.seqNum_C2D_Counter = self.dst_p.seqNum_C2D_Counter + 1

        s = ( self.dst_p.seqNum_C2D_Rand +
              str( self.dst_p.seqNum_C2D_Counter ) )

        seqNum_C2D = hmac.new(
            s, self.dst_p.client_hash, hashlib.sha256 ).digest()

        # B.  HMAC_Client( R2 )
        #
        salt_3 = cb_random.gen_rand_bytes(self, const.SALT_BYTE_LEN)

        text = ( salt_3 +
                 seqNum_C2D +
                 self.dst_p.decoupled_ID +
                 data )

        auth_text = hmac.new(
            text, self.dst_p.client_hash, hashlib.sha256 ).digest()

        # C.  E_Client( R2 )
        #
        enc_text = security_util.encrypt_text(self,
            text, self.dst_p.client_key, True, False, False)

        # D.  SESSSIONID=Decoupled_ID
        #
        final_text = seqNum_C2D + auth_text + enc_text

        req = http_util.create_http_req(self,
            final_text, self.dst_p.decoupled_ID,
            self.dst_p.tunnel_tag.encode("hex"),
            self.host_name)

        # Send request on to decoy host
        #
        self.dst_p.transport.write(req)
Пример #4
0
    def connectionMade(self):
        """
        State 0:  Request tunnel type

           Cookie :  SESSSIONID=HandshakeID; ID=Tunnel_Tag

        HandshakeID = Sentinel+Nonce_Client
        """

        # Sentinel
        #
        s = const.SENTINEL_DEADBEEF
        if use_crypto == True:
            s = self.sentinel_hex[0:const.SENTINEL_HEX_LEN]

        # Nonce_Client
        #
        self.nonce_client = cb_random.gen_rand_bytes(
            self, const.NONCE_CLIENT_BYTE_LEN)

        # Handshake_ID
        #
        self.handshake_ID = s + self.nonce_client.encode("hex")

        # Tunnel Tag
        #
        self.tunnel_tag = hmac.new(
            const.HTTP_UNI_TUNNEL + self.nonce_client.encode("hex"),
            self.sentinel_hex[const.SENTINEL_HEX_LEN:],
            hashlib.sha256).digest()

        # Filler text
        #
        plain_text = const.HTTPU_CLIENTHELLO

        auth_plain_text = '%s%s%s' % (self.encoder.digest(plain_text),
                                      const.HTTPU_HASHSEP, plain_text)

        cipher_text = auth_plain_text

        # HTTP Request
        #
        req = http_util.create_http_req(self, cipher_text, self.handshake_ID,
                                        self.tunnel_tag.encode("hex"),
                                        self.host_name)

        self.transport.write(req)

        # New state
        #
        self.state = const.STATE_1_UNI
Пример #5
0
    def sendSentinel(self):
        """
        State 1:  Send sentinel

           Cookie :  SESSSIONID=HandshakeID; ID=Tunnel_Tag

        HandshakeID = Sentinel+Nonce_Client
        """
        # HTTP Request
        #
        req = http_util.create_http_req(self,
            '', self.handshake_ID, self.tunnel_tag.encode("hex"),
            self.host_name)
        self.transport.write(req)

        # New state
        #
        self.state = const.STATE_3
Пример #6
0
    def connectionMade(self):
        """
        State 0:  Request tunnel type

           Cookie :  SESSSIONID=HandshakeID; ID=Tunnel_Tag

        HandshakeID = Sentinel+Nonce_Client
        """
        # Sentinel
        #
        s = const.SENTINEL_DEADBEEF
        if use_crypto == True:
            s = self.sentinel_hex[0:const.SENTINEL_HEX_LEN]

        # Nonce_Client
        #
        self.nonce_client = cb_random.gen_rand_bytes(self,
            const.NONCE_CLIENT_BYTE_LEN)

        # Handshake_ID
        #
        self.handshake_ID = ( s + self.nonce_client.encode("hex") )

        # Tunnel_Tag
        #
        self.tunnel_tag = hmac.new(
                const.HTTP_BI_TUNNEL + self.nonce_client.encode("hex"),
                self.sentinel_hex[const.SENTINEL_HEX_LEN:],
                hashlib.sha256 ).digest()

        # HTTP Request
        #
        rand_url_len = random.randint(10, 40)
        rand_url = cb_random.gen_rand_bytes(self, rand_url_len)
        req = http_util.create_http_req(self,
                rand_url, self.handshake_ID, self.tunnel_tag.encode("hex"),
                self.host_name)
        self.transport.write(req)

        # New state
        #
        self.state = const.STATE_1
Пример #7
0
    def sendPremaster(self, resp):
        """
        State 3:  Send premaster

         A.     URL :   E_KeyDPPub( Premaster )       +
                                    SeqNum_C2D_Rand ) +

         B.          HMAC_KeyDPPub( Premaster         +
                                    SeqNum_C2D_Rand   +
                                    Decoupled_ID      +
                                    Nonce_DP )

         C.  Cookie :  SESSSIONID=Decoupled_ID

        Decoupled_ID = Randomstring
        """
        try:

            # Check that DP sent back a decoupled_ID in a cookie
            #
            [new_cookie, self.decoupled_ID] = self.get_cookie_val( resp )
            if self.decoupled_ID == -1:
                self.transport.loseConnection() # TODO: CHECK!
                return

            # Pull out the covert message and extract its components
            #
            pieces = resp.split('\r\n\r\n', 1)
            if len(pieces) != 2:
                print 'ERROR: bogus http response (%d pieces)' % len(pieces)
                self.transport.loseConnection() # TODO: CHECK!
                return

            # TODO: what does an ordinary client do when it gets BOTH
            # a "content-length" and "transfer-encoding chunked"?
            # We don't detect this, but just believe the first.
            #
            match_len = False
            match_chunk = False
            header = pieces[0]
            for line in header.split('\r\n'):
                match_len = re.search(
                        '^[Cc]ontent-[Ll]ength:\s*([0-9]+)\s*$', line)
                if match_len:
                    # print 'XXXXXX content-length' # TODO: rm
                    break
                match_chunk = re.search(
                        '^[Tt]ransfer-[Ee]ncoding:\s*chunked\s*$', line)
                if match_chunk:
                    # print 'XXXXXX chunk-encoding' # TODO: rm
                    break

            if match_len:
                covert_begin  = str(resp).index(const.END_HEADER) + len(const.END_HEADER)
                covert_end = ( const.SIGNATURE_DP_PRIV_KEY_BYTE_LEN +
                               const.ENCRYPT_SALT_NONCE_BYTE_LEN )
                covert = resp[ covert_begin : covert_begin + covert_end ]

            elif match_chunk:
                chunk_len_begin  = str(resp).index(const.END_HEADER) + len(const.END_HEADER)
                chunk_len_to_end = str(resp[chunk_len_begin:])
                chunk_len_end    = chunk_len_to_end.index(const.END_LINE) + len(const.END_LINE)
                chunk_len        = chunk_len_to_end[ : chunk_len_end ]

                covert_begin = len(chunk_len) + str(resp).index(const.END_HEADER) + len(const.END_HEADER)
                covert_end = const.SIGNATURE_DP_PRIV_KEY_HEX_LEN + const.ENCRYPT_SALT_NONCE_HEX_LEN
                covert = str( resp[ covert_begin : covert_begin + covert_end ] )


                if not all(c in string.hexdigits for c in covert):
                    print "covert msg is not hex, not a hijack"
                    self.transport.loseConnection() # TODO: CHECK!
                    return
                else:
                    covert = covert.decode("hex")
            else:
                print 'ERROR: no Content-Length or "Transfer-Encoding chunked"'
                self.transport.loseConnection() # TODO: CHECK!
                return

            i1 = const.SIGNATURE_DP_PRIV_KEY_BYTE_LEN
            signature    = covert[ : i1 ]
            enc_nonce_dp = covert[ i1 : ]

            dec_nonce_dp = security_util.decrypt_text(self,
                enc_nonce_dp, self.extra_d2c_key, False, True, False)

            if dec_nonce_dp == -1:
                self.transport.loseConnection() # TODO: CHECK!
                return

            salt_1        = dec_nonce_dp[ : const.SALT_BYTE_LEN ]
            self.nonce_dp = dec_nonce_dp[ const.SALT_BYTE_LEN : ]

            # Verify that signature matches str_to_verify
            #
            str_to_verify = (
                    salt_1 + self.nonce_dp + new_cookie + self.handshake_ID )

            verified = security_util.verify_signature( self,
                self.pubkey_dp, str_to_verify, signature )


            if verified == True:

                # A. E_KeyDPPub( Premaster + SeqNum_C2D_Rand )
                #
                premaster = cb_random.gen_rand_bytes( self,
                    const.PREMASTER_BYTE_LEN )

                k = RSA.load_pub_key_bio( BIO.MemoryBuffer(self.pubkey_dp) )

                enc_text = k.public_encrypt(
                    premaster + self.seqNum_C2D_Rand,
                    RSA.pkcs1_oaep_padding )

                # B. HMAC_KeyDPPub( Premaster + SeqNum_C2D_Rand + Decoupled_ID + Nonce_DP )
                #
                # Note that decoupled_ID that is decoded here is client's
                # decouple_ID: it just happens to be stored in hex.
                # If something gets messed up, should fall through to
                # TypeError in except
                #
                text = ( premaster +
                         self.seqNum_C2D_Rand +
                         self.decoupled_ID.decode("hex") +
                         self.nonce_dp )

                auth_text = hmac.new( text, self.pubkey_dp, hashlib.sha256 ).digest()
                bin_text = binascii.hexlify( enc_text + auth_text )
                zip_text = zlib.compress( bin_text )

                # C. SESSSIONID=Decoupled_ID
                #
                req = http_util.create_http_req(self,
                    zip_text, self.decoupled_ID, self.tunnel_tag.encode("hex"),
                    self.host_name )

                self.transport.write(req)

                [ self.client_key,
                  self.dp_key,
                  self.client_hash,
                  self.dp_hash ] = security_util.compute_keys(
                     self, premaster, self.nonce_client, self.nonce_dp )

                # New state
                #
                self.state = const.STATE_5
            else:
                self.transport.loseConnection() # TODO: CHECK!

        except ValueError, TypeError:
            print 'Error: message has no payload'
            self.transport.loseConnection()