RFID-ACCESS-Bytes

Hier werden einzelne Projekte mit MicroPython vorgestellt
Antworten
Heinrichs
Beiträge: 173
Registriert: Do 21. Okt 2010, 18:31

RFID-ACCESS-Bytes

Beitrag von Heinrichs » Mo 6. Jun 2022, 08:09

1. Einführung

In dem Beitrag Lesen und Schreiben von RFID-Karten wurde der Aufbau des Speichers einer 1K-RFID-Karte (Mifare 1K classic) schon grob dargestellt und erläutert: Der Speicher ist aufgeteilt in 16 Sektoren; jeder dieser Sektoren besteht aus jeweils 4 Blöcken mit den Sektor-Blocknummern 0 bis 3. Insgesamt stehen also 16 * 4 = 64 Blöcke zur Verfügung. Da in jedem Block 16 Bytes gespeichert werden können, stehen auf unserer RFID-Karte 64 * 16 = 1024, also 1 kB zur Verfügung.

mifare_Fig_5_klein.jpg
Abb. 1: Fig. 5 vom Datasheet
mifare_Fig_5_klein.jpg (41.81 KiB) 7953 mal betrachtet

Das von uns benutzte Modul mfrc522.py greift auf die einzelnen Blöcke mit Hilfe einer “globalen” Blocknummer zurück; z. B. benutzt dieses Modul für die Blöcke des Sektors 2 mit den Sektor-Blocknummern 0, 1, 2 und 3 mit die Werte 8, 9, 10 und 11. Diese Blocknummern sind auch in Abb. 1 des oben genannten Beitrags benutzt worden. Diese “globalen” Blocknummern werden wir auch weiterhin benutzen, wenn wir Daten auf die RFID-Karte schreiben oder von ihr lesen, genauer gesagt: wenn wir die read- bzw. write-Methode von der Klasse MFRC522 einsetzen.

In diesem Beitrag werden wir nicht nur darlegen, dass die einzelnen Blöcke unterschiedliche Zugriffsrechte haben können (z. B. nur Lesezugriff); wir werden auch an zwei einfachen Beispielen zeigen, wie man diese Zugriffsrechte ändern kann. Die Zugriffsrechte sind auf der RFID-Karte in den so genannten ACCESS-Bits gespeichert. Diese befinden sich in den Bytes 6, 7 und 8 des Sector Trailers; das sind die Blöcke mit der Sektor-Blocknummer 3. (Die zugehörigen “globalen” Blocknummern sind 3, 7, 11, ...).

Die Zugriffsrechte werden also sektorweise festgelegt; diese Rechtevergabe erfolgt dabei für jeden dieser 4 Blöcke des Sektors einzeln. Damit kann dann z. B. eingestellt werden, dass der Block 2 von Sektor 4 zwar ausgelesen, aber nicht mehr neu beschrieben werden kann (solange man die neuen Zugriffsrechte beibehält).

Diese Zugriffsrechte lassen sich natürlich nicht mehr ändern, wenn man die Bytes 6, 7 und 8 des Trailers für den Schreibzugriff gesperrt hat. In diesem Fall kann man in unseren Block 2 von Sektor 4 niemals mehr neue Daten schreiben.

Viel entscheidender ist aber: Die Access-Bits müssen nach einem bestimmten Schema (vgl. Abschnitt 2) eingegeben werden; wenn sich hierbei eine Inkonsistenz zeigt (weiter unten mehr dazu), dann wird der entsprechende Block irreversibel blockiert. Deswegen der dringliche Hinweis:

Lassen Sie große Vorsicht beim Beschreiben der Sector Trailer walten. Es empfiehlt sich insbesondere, zum Austesten eine besonders gekennzeichnete RFID-Karte (ohne wichtige Daten) zu benutzen.


2. Der Sector Trailer

Der Sector Trailer beinhalt die Schlüssel Key A (Byte 0 - 5) und Key B (Byte 10 - 15) sowie die Access-Bytes (Byte 6 - 8); der für die Access Bits in der Abb. 1 ausgewiesene Speicherplatz wird nicht nicht vollständig genutzt: Über das Byte 9 kann frei verfügt werden.

Im Auslieferungszustand ist der Sector Trailer (hexadezimal): FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF (vgl. Abschnitt 8.6.3 des Mifare-Datasheets). Das Byte 69 spielt (wie oben schon erwähnt) keine Rolle. Über die Schlüssel Key A und Key B wird die Authentifizierung durchgeführt; nur nach erfolgreicher Authentifizierung mit der Methode auth der Klasse MFRC522 ist ein Zugriff auf die Daten eines Sektors möglich. Dabei bestimmt der erste Parameter dieser Methode, ob Key A oder Key B benutzt wird (vgl. meinen Beitrag Lesen und Schreiben von RFID-Karten).

Wenden wir uns nun den Access-Bytes zu. In diesen Bytes werden die Zugriffsbedingungen für jeden Block eines Sektors festgelegt. Dabei sind jedem Block drei Access-Bits zugeordnet; diese werden jeweils mit C1, C2, C3 bezeichnet. Um die Access-Bits für die verschiedenen Blöcke eines Sektors unterscheiden zu können, fügen wir einen Index an. Die Access-Bits für die einzelnen Blöcke werden damit folgendermaßen gekennzeichnet:

Sektor-BlockAccess-Bits
3C13, C23, C33
2C12, C22, C32
1C11, C21, C31
0C10, C20, C30

Aus diesen Bits setzt man nun die Access-Bytes wie in der folgenden Abbildung gezeigt zusammen:

mifare_Fig_10.jpg
Abb. 2: Fig. 10 vom Datasheet
mifare_Fig_10.jpg (29.49 KiB) 7952 mal betrachtet

Dabei ist C13 das invertierte Bit zu C13. Man erkennt gleich: Die einzelnen Access-Bits sind sozusagen in den Access-Bytes doppelt vorhanden, einmal mit dem Originalwert, und einmal invertiert.

Achtung: Wenn (versehentlich) für C13 und C13 derselbe Bitwert eingetragen wird, liegt eine Inkonsistenz vor. In diesem Fall wird der entsprechende Sektor irreversibel blockiert.


3. Analyse der Access-Bits im Auslieferungszustand

Im Auslieferungszustand ist:

Byte 6 = FF hex = 1111 1111 bin
Byte 7 = 07 hex = 0000 0111 bin
Byte 8 = 80 hex = 1000 0000 bin

Man kann leicht nachkontrollieren, dass hier keine Inkonsistenz vorliegt. Für die Analyse greifen wir auf die Original-Bits zurück:

Sektor-BlockAccess-BitsInhalt
3C13, C23, C33001
2C12, C22, C32000
1C11, C21, C31000
0C10, C20, C30000

Wir erkennen unmittelbar: Die 3 Datenblöcke haben dieselben Zugangsbedingungen, der Sector Trailer besitzt eine andere Zugangsbedingung.

Welche Bedeutung haben nun diese Bitmuster für die Zugangsbedingungen? Das erfahren Sie in den nächsten Abschnitten.


4. Access-Bits für einen Datenblock

Die Bedeutung der Access-Bits für einen Datenblock ergibt sich aus der Tabelle 8 des Datasheet. Wir geben sie hier in einer vereinfachten Version wieder, indem wir uns nur um Schreib- und Lesevorgänge kümmern:

Access-Bit-Muster C1 C2 C3readwrite
0 0 0key A|Bkey A|B
0 1 0key A|Bnie
1 0 0key A|Bkey B
0 1 1key Bkey B
1 1 1nienie

Hinweis: Die restlichen Access-Bit-Muster beziehen sich auf Funktionen, die wir hier nicht behandeln.

Welche Zugangsbedingung entspricht z. B. dem Bitmuster 000, das wir im letzten Abschnitt gefunden hatten? Aus der Abb. 3 ergibt sich für diesen Fall:
  1. Ein Lesevorgang ist möglich mit dem Schlüssel Key A oder mit dem Schlüssel Key B. (Der senkrechte Strich ist ein abkürzendes Zeichen für ODER.)
  2. Ein Schreibvorgang ist möglich mit dem Schlüssel Key A oder mit dem Schlüssel Key B.
Im Auslieferungszustand lassen sich also alle Datenblöcke mit Key A oder mit Key B lesen.


Anders sieht es z. B. bei dem Access-Bit-Muster 010 aus: Hier kann der Block mit Key A oder Key B gelesen werden. Es ist aber nicht möglich, Daten in diesen Block zu schreiben. Mit diesem Bitmuster kann man also einzelne Datenblöcke mit einem Schreibschutz versehen.

Bitte beachten Sie: Wenn Sie alle drei Datenblöcke eines Sektors mit einem Schreibschutz versehen wollen, müssen Sie alle drei Access-Bitmuster (C1x, C2x, C3x) für x = 0, 1, 2 mit 010 belegen.


5. Schreibschutz für einen Datenblock erstellen und testen

Wir wollen unsere Kenntnisse jetzt nutzen, um einen bestimmten Datenblock (z. B. den Block 12) mit einem Schreibschutz versehen. Zuvor wollen wir aber erst einmal Daten in diesen Block schreiben, z. B. den Text “Hallo Welt!”. Mit dem Programm mfrc_write_text_display.py geht das recht einfach. Wir legen eine (neue) Karte an das RFID-Modul, starten das Programm und geben die “globale” Blocknummer und den Text am Terminal ein.

Wer mag, kann diese Zeichenkette auch mit dem Programm mfrc_read_block_2.py zum Test noch einmal auslesen.

Jetzt verändern wir die Access-Bits: Der Block 12 befindet sich im Sektor 3; die Sektor-Blocknummer ist 0. Für diesen Block muss das Access-Bitmuster nun 010 werden. Die Access-Bits für die Blöcke mit den Sektor-Blocknummern 1, 2 und 3 bleiben unverändert. Bei den Access-Bytes ändern sich daher nur C20 (wird zu 1) und C20 (wird zu 0). Damit sind die Access-Bytes:

Byte 6 = 1110 1111 bin = EF hex
Byte 7 = 0000 0111 bin = 07 hex
Byte 8 = 1000 0001 bin = 81 hex

Diese Bytes schreiben wir jetzt zusammen mit den Schlüsseln in den Trailer dieses Sektors; der zugehörige Bytestring ist b'\xff\xff\xff\xff\xff\xff\xef\x07\x81i\xff\xff\xff\xff\xff\xFF'. (Hierbei steht das Zeichen i für das Byte \x69.) Wir benutzen dazu das Programm mfrc_write_trailer_2.py. Dieses Programm ist bewusst sehr einfach gehalten: Die nötigen Eingaben werden nicht über das Terminal, sondern direkt im Programm vorgenommen. Die Variable block erhält dabei den Wert 15, die Blocknummer des Trailers von Sektor 3, und der Variablen new_data weisen wir den oben angegebenen Bytestring zu. (Dies können Sie auch dadurch erreichen, dass Sie im Programm die Auskommentierungen bei new_data passend ändern!)

Legen Sie Ihre Karte an das RFID-Modul und starten Sie nun das Programm; das Terminal zeigt an, ob der Schreibvorgang erfolgreich war. Nun können Sie mit dem Programm mfrc_write_text_display_1d.py versuchen einen beliebigen Text in Block 12 zu schreiben, z. B. “Etwas Neues”. Sie erhalten dann die Meldung, dass der Schreibvorgang nicht erfolgreich war. Dass Block 12 tatsächlich nicht verändert wurde, können Sie mit dem Programm mfrc_read_block_2.py überprüfen.

Versuchen Sie nun auch einmal, Texte in die beiden Blöcke 13 und 14 zu schreiben. Dies sollte möglich sein!

Wer den Schreibschutz für den Block 12 wieder entfernen möchte, schreibt einfach den ursprünglichen Bytestring b'\xff\xff\xff\xff\xff\xff\xff\x07\x80i\xff\xff\xff\xff\xff\xff' in den Trailer (Block 15).


6. Access-Bits für einen Sector Trailer

Auch für den Sector Trailer lassen sich die Zugangsbedingungen neu festlegen. Da hierbei insbesondere auch die Access-Bytes vor Überschreiben geschützt werden können, ist hier besondere Sorgfalt erforderlich!

Die Bedeutung der einzelnen Access-Bit-Muster für den Sector Trailer sind in der folgenden Abb. 3 angegeben:

mifare_table_7.jpg
Abb. 3: Table 7 vom Datasheet
mifare_table_7.jpg (50.67 KiB) 7946 mal betrachtet

Das Access-Bit-Muster 0 0 1 für den Auslieferungszustand können wir folgendermaßen deuten:
  1. key A ist niemals lesbar.
  2. key A mittels Authentifizierung über key A (neu) beschrieben werden.
  3. Die Access-Bits können mittels Authentifizierung über key A sowohl gelesen als auch (neu) beschrieben werden.
  4. key B kann mittels Authentifizierung über key A sowohl gelesen als auch (neu) beschrieben werden.

7. Lesezugriff für Key B unterbinden

Nun wollen wir unsere Kenntnisse anwenden, um den Lesezugriff auf key B zu unterbinden. Dies gelingt mit Hilfe des Access-Bit-Musters 0 1 1. Man beachte, dass anschließend die Access-Bits nur noch durch eine Authentifizierung über key B geändert werden können!

Gegenüber dem Auslieferungszustand müssen wir nur das Bit C23 ändern: C23 wird jetzt zu 1, damit wird C23 zu 0. Die Access-Bytes sind somit:

Byte 6 = 0111 1111 bin = 7F hex
Byte 7 = 0000 0111 bin = 07 hex
Byte 8 = 1000 1000 bin = 88 hex

Wir wählen z. B. den Sektor 5 aus; der Sector Trailor hat dann die "globale" Blocknummer 23. In diesen Block schreiben wir mit dem Programm mfrc_write_trailer_2.py den Bytestring b'\xff\xff\xff\xff\xff\xff\x7f\x07\x88i\xff\xff\xff\xff\xff\xff'; auch dieser Bytestring befindet sich (auskommentiert) bereits im Programm.

Sie werden feststellen: Wenn man Block 23 anschließend ausliest, werden für key B nicht die tatsächlichen Bytes von key B, sondern nur 0-Bytes angezeigt. Dagegen bleiben die restlichen Datenblöcke des Sektors 5 weiter lesbar.


8. Access-Bits anzeigen lassen

Mit dem Programm mfrc_read_sector.py können Sie sich einen Sektor mit den zugehörigen Access-Bits anzeigen lassen. Für den Sektor 5 (aus dem vorherigen Abschnitt) sieht das Ergebnis so aus:

Code: Alles auswählen

uid:  0x13d1d403

Sektornummer (0 - 15): 5
Block[20]: ................
Block[21]: ................
Block[22]: Bl. 2 aus Sek. 5
Block[23]: .........i......
Access-Bits:  [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 1, 1]]
Sie finden das Programm auch im Anhang.

.
Dateianhänge
rfid_access.zip
Mifare-RFID-Datasheet und benötigte Programme
(379.33 KiB) 606-mal heruntergeladen

Antworten