basic Man-in-the-Middle extension to the Relay-Card
This commit is contained in:
@@ -24,6 +24,7 @@ vpicccards_PYTHON = virtualsmartcard/cards/__init__.py \
|
|||||||
virtualsmartcard/cards/ePass.py \
|
virtualsmartcard/cards/ePass.py \
|
||||||
virtualsmartcard/cards/nPA.py \
|
virtualsmartcard/cards/nPA.py \
|
||||||
virtualsmartcard/cards/Relay.py \
|
virtualsmartcard/cards/Relay.py \
|
||||||
|
virtualsmartcard/cards/RelayMiddleman.py \
|
||||||
virtualsmartcard/cards/cryptoflex.py
|
virtualsmartcard/cards/cryptoflex.py
|
||||||
|
|
||||||
do_subst = $(SED) \
|
do_subst = $(SED) \
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ relay.add_argument("--reader",
|
|||||||
type=int,
|
type=int,
|
||||||
default=0,
|
default=0,
|
||||||
help="number of the reader containing the card to be relayed (default: %(default)s)")
|
help="number of the reader containing the card to be relayed (default: %(default)s)")
|
||||||
|
relay.add_argument("--mitm",
|
||||||
|
action="store",
|
||||||
|
type=str,
|
||||||
|
help="relative path to a file containing a Man-in-the-Middle class that is supposed to be used with the relay")
|
||||||
|
|
||||||
npa = parser.add_argument_group('Emulation of German identity card (`--type=nPA`)')
|
npa = parser.add_argument_group('Emulation of German identity card (`--type=nPA`)')
|
||||||
npa.add_argument("--ef-cardaccess",
|
npa.add_argument("--ef-cardaccess",
|
||||||
@@ -153,7 +157,7 @@ else:
|
|||||||
hostname = args.hostname
|
hostname = args.hostname
|
||||||
|
|
||||||
vicc = VirtualICC(args.datasetfile, args.type, hostname, args.port,
|
vicc = VirtualICC(args.datasetfile, args.type, hostname, args.port,
|
||||||
readernum=args.reader, ef_cardaccess=ef_cardaccess_data,
|
readernum=args.reader, mitmPath=args.mitm, ef_cardaccess=ef_cardaccess_data,
|
||||||
ef_cardsecurity=ef_cardsecurity_data, ca_key=ca_key_data, cvca=cvca,
|
ef_cardsecurity=ef_cardsecurity_data, ca_key=ca_key_data, cvca=cvca,
|
||||||
disable_checks=args.disable_ta_checks, esign_ca_cert=esign_ca_cert,
|
disable_checks=args.disable_ta_checks, esign_ca_cert=esign_ca_cert,
|
||||||
esign_cert=esign_cert, logginglevel=logginglevel)
|
esign_cert=esign_cert, logginglevel=logginglevel)
|
||||||
|
|||||||
@@ -370,6 +370,30 @@ class Iso7816OS(SmartcardOS):
|
|||||||
self.mf.current = self.mf
|
self.mf.current = self.mf
|
||||||
|
|
||||||
|
|
||||||
|
def loadMitMFromPath(path: str):
|
||||||
|
from importlib import import_module
|
||||||
|
from pathlib import Path
|
||||||
|
def onNth(tup,ind,func):
|
||||||
|
start = tup[0:ind] + (func(tup[ind]),)
|
||||||
|
return start if ind + 1 == 0 else start + tup[ind+1:]
|
||||||
|
|
||||||
|
def pathToModuleName(path):
|
||||||
|
return ".".join(onNth(Path(path).parts,-1,lambda fName : str(Path(fName).stem)))
|
||||||
|
|
||||||
|
mitmModule = import_module(pathToModuleName(path))
|
||||||
|
|
||||||
|
# Sanity Checks
|
||||||
|
if not getattr(mitmModule,"get_MitM",None):
|
||||||
|
raise ValueError("The provided module does not contain a 'get_MitM' method.")
|
||||||
|
mitm = mitmModule.get_MitM()
|
||||||
|
if not getattr(mitm,"handleInPDU",None):
|
||||||
|
raise ValueError("The produced MitM has no 'handleInPDU' method.")
|
||||||
|
if not getattr(mitm,"handleOutPDU",None):
|
||||||
|
raise ValueError("The produced MitM has no 'handleOutPDU' method.")
|
||||||
|
|
||||||
|
return mitm
|
||||||
|
|
||||||
|
|
||||||
# sizeof(int) taken from asizof-package {{{
|
# sizeof(int) taken from asizof-package {{{
|
||||||
_Csizeof_short = len(struct.pack('h', 0))
|
_Csizeof_short = len(struct.pack('h', 0))
|
||||||
# }}}
|
# }}}
|
||||||
@@ -393,7 +417,7 @@ class VirtualICC(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, datasetfile, card_type, host, port,
|
def __init__(self, datasetfile, card_type, host, port,
|
||||||
readernum=None, ef_cardsecurity=None, ef_cardaccess=None,
|
readernum=None, mitmPath=None, ef_cardsecurity=None, ef_cardaccess=None,
|
||||||
ca_key=None, cvca=None, disable_checks=False, esign_key=None,
|
ca_key=None, cvca=None, disable_checks=False, esign_key=None,
|
||||||
esign_ca_cert=None, esign_cert=None,
|
esign_ca_cert=None, esign_cert=None,
|
||||||
logginglevel=logging.INFO):
|
logginglevel=logging.INFO):
|
||||||
@@ -429,7 +453,9 @@ class VirtualICC(object):
|
|||||||
self.os = CryptoflexOS(MF, SAM)
|
self.os = CryptoflexOS(MF, SAM)
|
||||||
elif card_type == "relay":
|
elif card_type == "relay":
|
||||||
from virtualsmartcard.cards.Relay import RelayOS
|
from virtualsmartcard.cards.Relay import RelayOS
|
||||||
self.os = RelayOS(readernum)
|
from virtualsmartcard.cards.RelayMiddleman import RelayMiddleman
|
||||||
|
mitm = loadMitMFromPath(mitmPath) if mitmPath else RelayMiddleman()
|
||||||
|
self.os = RelayOS(readernum,mitm=mitm)
|
||||||
elif card_type == "handler_test":
|
elif card_type == "handler_test":
|
||||||
from virtualsmartcard.cards.HandlerTest import HandlerTestOS
|
from virtualsmartcard.cards.HandlerTest import HandlerTestOS
|
||||||
self.os = HandlerTestOS()
|
self.os = HandlerTestOS()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import logging
|
|||||||
import smartcard
|
import smartcard
|
||||||
import sys
|
import sys
|
||||||
from virtualsmartcard.VirtualSmartcard import SmartcardOS
|
from virtualsmartcard.VirtualSmartcard import SmartcardOS
|
||||||
|
from virtualsmartcard.cards.RelayMiddleman import RelayMiddleman
|
||||||
|
|
||||||
|
|
||||||
class RelayOS(SmartcardOS):
|
class RelayOS(SmartcardOS):
|
||||||
@@ -31,7 +32,7 @@ class RelayOS(SmartcardOS):
|
|||||||
an actual smart card reader and sends the responses back to the vpcd.
|
an actual smart card reader and sends the responses back to the vpcd.
|
||||||
This class can be used to implement relay or MitM attacks.
|
This class can be used to implement relay or MitM attacks.
|
||||||
"""
|
"""
|
||||||
def __init__(self, readernum):
|
def __init__(self, readernum, mitm=RelayMiddleman()):
|
||||||
"""
|
"""
|
||||||
Initialize the connection to the (physical) smart card via a given
|
Initialize the connection to the (physical) smart card via a given
|
||||||
reader
|
reader
|
||||||
@@ -57,6 +58,8 @@ class RelayOS(SmartcardOS):
|
|||||||
|
|
||||||
logging.info("Connected to card in '%s'", self.reader)
|
logging.info("Connected to card in '%s'", self.reader)
|
||||||
|
|
||||||
|
self.mitm = mitm
|
||||||
|
|
||||||
atexit.register(self.cleanup)
|
atexit.register(self.cleanup)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
@@ -116,6 +119,8 @@ class RelayOS(SmartcardOS):
|
|||||||
# sendCommandAPDU() expects a list of APDU bytes
|
# sendCommandAPDU() expects a list of APDU bytes
|
||||||
apdu = map(ord, msg)
|
apdu = map(ord, msg)
|
||||||
|
|
||||||
|
apdu = self.mitm.handleInPDU(apdu)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rapdu, sw1, sw2 = self.session.sendCommandAPDU(apdu)
|
rapdu, sw1, sw2 = self.session.sendCommandAPDU(apdu)
|
||||||
except smartcard.Exceptions.CardConnectionException as e:
|
except smartcard.Exceptions.CardConnectionException as e:
|
||||||
@@ -130,5 +135,7 @@ class RelayOS(SmartcardOS):
|
|||||||
else:
|
else:
|
||||||
rapdu = rapdu + [sw1, sw2]
|
rapdu = rapdu + [sw1, sw2]
|
||||||
|
|
||||||
|
rapdu = self.mitm.handleOutPDU(rapdu)
|
||||||
|
|
||||||
# return the response APDU as string
|
# return the response APDU as string
|
||||||
return "".join(map(chr, rapdu))
|
return "".join(map(chr, rapdu))
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
class RelayMiddleman(object):
|
||||||
|
"""
|
||||||
|
The RelayMiddleman class serves as a base from which a user might derive
|
||||||
|
their own relay middle man class. This base class implements the simplest
|
||||||
|
Man-in-the-Middle: the NoOp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def handleInPDU(self, inPDU: bytes):
|
||||||
|
"""
|
||||||
|
This method is called on each PDU that is fed into the realy (vdpu -> vicc).
|
||||||
|
It may be overwritten to modify the packages send from the terminal to the
|
||||||
|
real smart card.
|
||||||
|
"""
|
||||||
|
return inPDU
|
||||||
|
|
||||||
|
def handleOutPDU(self, outPDU: bytes):
|
||||||
|
"""
|
||||||
|
This method is called on each PDU that is produced by the relay (vicc -> vdpu).
|
||||||
|
It may be overwritten to modify the packages send from the real smart card to the
|
||||||
|
terminal.
|
||||||
|
"""
|
||||||
|
return outPDU
|
||||||
Reference in New Issue
Block a user