Zum Hauptinhalt springen

Neulich stieß ich auf ein Programm, mit dem ich aus einem vorgefertigten Satz von Abfragen auswählen konnte und das dann mit einem Server kommunizierte, um die Antwort auf die ausgewählte Abfrage abzurufen. Ich begann mich zu wundern, als ich feststellte, dass das Programm nie nach einem Passwort für die Authentifizierung beim Server fragte. Es stellte sich heraus, dass das Kennwort in das Programm eingebettet war. Der Autor erklärte, dass dies in Ordnung sei, weil 1) es sich um eine Binärdatei handelte, so dass niemand sie lesen konnte, und 2) wenn sie sie lesen könnten, wären sie nicht in der Lage, die Kennwortzeichenfolge zu finden.

Keiner dieser Gründe ist stichhaltig und ich möchte diesen Beitrag nutzen, um das zu demonstrieren. Mein Beispielprogramm schreibt nur das "Passwort" auf das Terminal, aber der einzige Unterschied zwischen ihm und einem tatsächlichen Produktionsprogramm ist die Anzahl der Zeichenfolgen, die ein böswilliger Benutzer durchsuchen müsste.

#include <stdio.h>
#include <string.h>

main ()
{
char password [9] = {"secret"};

printf ("This is the password: %sn", password);

}
Abbildung 1 - Grundprogramm mit eingebettetem Passwort

Bei der Ausführung zeigt es an

x1
Das ist das Passwort: geheim
bereit 14:12:16
Abbildung 2 - Ausführung des Grundprogramms

Um die Zeichenketten im Programmmodul anzuzeigen, kann unser böswilliger Benutzer den Befehl strings aus dem Verzeichnis >system>gnu_library>bin verwenden. Das -n5 begrenzt die Ausgabe auf Zeichenketten mit 5 Zeichen oder mehr. Ich habe die Ausgabe abgeschnitten (. . . .), um die Anzeige zu verkürzen, aber Sie können sehen, dass das Kennwort eine der allerersten angezeigten Zeichenketten ist. Wenn sich das Kennwort in unmittelbarer Nähe zu Schlüsselwörtern wie "login" oder "password" oder zu einer identifizierbaren Benutzerkennung wie "admin", "root" oder "sql" befindet, wird die Suche erleichtert.

>system>gnu_library>bin>strings -n5 x1.pm
bind, Release 17.1.beta.be
phx_vos#
Noah_Davids.CAC
Vorveröffentlichung
Dies ist das Passwort: %s
geheim
s$start_c_programm
_preemption_cleanup
_beenden
. . . . .
Abbildung 3 - Verwendung des GNU-Befehls strings zum Auffinden aller Strings, die länger als 4 Zeichen sind, im Programmmodul

Wenn der Befehl strings nicht verfügbar ist, kann unser böswilliger Benutzer einfach das Programmmodul anzeigen. Ich vermute, dass wir das alle schon aus Versehen gemacht haben, und obwohl es nicht schön ist, wird das Passwort angezeigt. Ich habe die Ausgabe wieder abgeschnitten und Sie können das Kennwort wieder sehen.

d x1.pm

%phx_vos#m16_mas>SysAdmin>Noah_Davids>x1.pm 11-01-13 14:13:59 mst

`00`01`00`1Abind, Release 17.1.beta.be`00`00`00`00`00`00`00`04ctp
`00`00`00`00`0
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`0
0phx_vos
+#`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`
00`00Noa
. . . .
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`C
D'`8B`C0
+`00`00`00`00Das ist das Passwort: %s
`00`00`00`00`00`00`00secret`00`00`00`00`00`00`00`04`B0`00`00`00`00`01`00
`00`00,`
+`00`00`04`00`00`00`[email protected]`00`FF`F8`FF`FE`00`04main`00`00`83`EC`2C`C7D$$`00
. . . .
Abbildung 4 - Anzeige des Programm-Moduls zum Finden des Passworts

Es gibt mehrere Alternativen zum Einbetten des Kennworts in das Programm.

Das Kennwort kann in einer Datei abgelegt werden und das Programm kann die Datei lesen. Nur die Personen mit einem "need to run" erhalten Lesezugriff auf die Datei und alle anderen erhalten Null-Zugriff. Natürlich ist "need to run" nicht unbedingt gleichzusetzen mit "need to know the password". Außerdem besteht immer die Gefahr, dass jemand versehentlich den Zugriff ändert.

Eine Alternative ist, die Kennwortzeichenfolge im Programm zu belassen und nur den Zugriff auf das Programm zu beschränken. Diese Lösung leidet ebenfalls unter dem "Es ist leicht, eine Zugriffsliste zu ändern"-Problem. Wenn das Programm im gleichen Verzeichnis wie andere Programme aufbewahrt wird, die von jedem ausgeführt werden können, steigt die Wahrscheinlichkeit, dass eine Zugriffsliste geändert wird.

Schließlich können Sie das Kennwort im Programmmodul behalten, aber die Zeichenfolge irgendwie verschleiern. Das folgende Programm zeigt eine einfache Möglichkeit, dies zu tun.

#include <stdio.h>
#include <string.h> 

main ()
{
char obfuscate [9] = {0x0c, 0x81, 0xe2, 0x94, 0xe6, 0x9c};
char key [9] = {127, 228, 129, 230, 131, 232, 133, 234, 135};
char password [9];
int i;

for (i = 0; i < strlen (obfuscate); i++)
    password [i] = obfuscate [i] ^ key [i];
password [i] = 0x0;
printf ("This is the password: %sn", password);
}
Abbildung 5 - Programm mit verschleierter Kennwortzeichenfolge

Wie Sie sehen können, werden lediglich die verschleierten Zeichen genommen und mit einer anderen Gruppe von Schlüsselzeichen XOR-verknüpft, um das Kennwort zu erstellen. Die Ausführung des Programms erzeugt die gleiche Ausgabe wie das erste Programm.

x2
Das ist das Passwort: geheim
bereit 14:12:51
Abbildung 6 - Ausführung eines verschleierten Programms

Aber eine Suche nach Zeichenketten zeigt nichts, was wie das Passwort aussieht

>system>gnu_library>bin>strings -n5 x1.pm
bind, Release 17.1.beta.be
phx_vos#
Noah_Davids.CAC
Vorveröffentlichung
Dies ist das Passwort: %s
s$start_c_programm
_preemption_cleanup
_beenden
. . . .
Abbildung 7 - Der Befehl strings zeigt das Passwort nicht mehr an

Und während bei der Anzeige der Datei die verschleierten Kennwortzeichen und die Schlüsselzeichen angezeigt werden, müssen Sie genau wissen, wo sie zu finden sind und auch, wie sie kombiniert werden, um das Kennwort zu erstellen.

d x2.pm

%phx_vos#m16_mas>SysAdmin>Noah_Davids>x2.pm 11-01-13 14:15:27 mst

. . . .
+`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`00`CD'`8B`
C0`00`0
+0`00`00Das ist das Passwort: %s

`00`00`00`00`00`00`00`0C`81`E2`94`E6`9C`00`00`00`00`00`00`00`00`00`00`7F
`E4`81`
+E6`83`E8`85`EA`87`00`00`00`00`04`B0`00`00`00`00`01`00`00`00`00`00`00`0
4`01`B0
+`00`[email protected]`00`FF`F0`00`08`FF`FE`00`04main`00`00`83`EC`89$X`89t$T`89|$P`C
7D$L`00
Abbildung 8 - Anzeige des Programm-Moduls zeigt kein erkennbares Passwort mehr an

Dies ist immer noch keine perfekte Lösung, da das Programmmodul disassembliert werden kann, um herauszufinden, wie das Kennwort generiert wird. Das Disassemblieren des Programms erfordert jedoch sehr viel mehr Raffinesse als das bloße Anzeigen des Programmmoduls.

Ich bin zwiegespalten, was das Ablegen der verschleierten Kennwortzeichenfolge in einer Datei und den anschließenden Schutz der Datei über eine Zugriffsliste angeht. Einerseits, wenn das Passwort jemals geändert werden muss, ist dies eine viel bessere Lösung als die Einbettung der verschleierten Passwortzeichenfolge in das Programm. Andererseits vermute ich, dass, selbst wenn es andere Konfigurationsoptionen in der Datei gibt, das Einbetten der Zeichenfolge in die Datei unserem böswilligen Benutzer weniger potenzielle Kennwortzeichenfolgen zur Verfügung stellt, die er untersuchen muss. Natürlich muss er sich trotzdem Zugriff auf die Datei verschaffen und dann die Verschleierungstechnik und den Schlüssel herausfinden.

Ein letzter Punkt: Wie habe ich die verschleierten Kennwortzeichen generiert? Das Schöne an der XOR-Operation ist, dass ((A XOR B) XOR B) gleich A ist, also habe ich einfach ein kurzes Programm geschrieben, das das Original-Passwort nimmt, die Zeichen mit meinem Schlüssel XOR-verknüpft und das Ergebnis ausgibt.

#include <stdio.h>
#include <string.h>

main ()
{
char password [9];
char key [9] = {127, 228, 129, 230, 131, 232, 133, 234, 135};
char newPW [9];
int i;

strcpy (password, "secret");
for (i = 0; i < strlen (password); i++)
    {
    newPW [i] = password [i] ^ key [i];
    printf ("%xn", newPW [i]);
    }
}
Abbildung 9 - Programm zum Erzeugen eines verschleierten Passworts

© 2020 Stratus Technologies.