Aktive Verteidigung gegen Krypto-Trojaner

Mit Locky sieht die IT-Welt derzeit einen der koordiniertesten Trojanerangriff der jüngeren Zeit. Während er sich Anfangs als Schläfer getarnt haben soll, findet er inzwischen auf unterschiedlichsten Wegen sein Ziel: als Word- oder Excel-Dokument mit schädlichem Makro, als JavaScript-Datei - z.B. getarnt als angebliches Sipgate-Fax - oder gar als altmodische und ausgestorben geglaubte Batch-Datei. Bei den Opfern des Verschlüsselungstrojaners handelt es sich durchaus auch um größere Organisationen wie Krankenhäuser und ein Fraunhofer-Institut. Man ging zeitweise von 5000 Neuinfektionen pro Stunde aus.

Die Vorschläge für Gegenmaßnahmen sehen derzeit noch eher mager aus: die einen raten zur Symptombekämpfung durch Backups, deaktivierte Makros und Virenscannern, andere wiederum versuchen, durch das Erkennen der Funktionsweise des Trojaners (schnelles Bearbeiten vieler Dateien in kurzer Zeit) eine Anti-Malware-Software auf Heuristikbasis zu erstellen.

Um sich erfolgreich gegen solch einen Trojanerangriff zur Wehr zu setzen, muss man jedoch an mehreren Baustellen aktiv werden - und anstatt unterschiedlichste Teilmaßnahmen einzuführen, sollte man sich überlegen, welche Kombination von Maßnahmen zu einem ganzheitlichen Schutz führen kann. Die folgende Auflistung soll dabei eine kleine Hilfestellung für einen aktiven Umgang mit solch einem Infektionsrisiko bieten. Das folgende Dreiergespann aus Vermeidung, Erkennung und Behandlung ist auch in der Medizin durchaus weit verbreitet.

Zuerst einmal sollte man natürlich das Thema Vermeidung betrachten. Hierzu zählen Dinge wie das Deaktivieren der Makrofunktion in Office-Anwendungen, die Aufklärung von Mailnutzern darüber, dass Office-Anhänge von außen nicht zu öffnen und ZIP-Dateien von außen nicht zu entpacken sind. Auch das Deaktivieren von JavaScript auf exponierten Arbeitsplätzen oder gar der Wechsel auf ein Betriebssystem mit konsequenter Trennung von Ausführungsrechten und Dateinamen kann eine Option darstellen.

Anschließend sollte man sich darum kümmern, eine Erkennung eines erfolgreichen Angriffs zu ermöglichen. Erst, wenn eine Infektion erkannt werden kann, kann sie im Anschluss auch behandelt werden. Leider ist es noch häufig so, dass eine Erkennung lediglich durch Virenscanner erfolgt. Diese sind jedoch so spezifisch an einzelne Schädlinge und deren spezifisches Verhalten angepasst, dass neue Generationen häufig für längere Zeit unentdeckt bleiben. Anstatt Verhaltensmuster der Schädlinge zu untersuchen, ist es daher sinnvoller, Standardverhaltensmuster seiner Mitarbeiter zu aggregieren und Abweichungen von diesem Standardverhalten in einem Sicherheitsmonitoring zu sammeln. So ist es möglich, auch neue Schädlinge anhand eines vom Durchschnitt abweichenden Verhaltens zu erkennen, anstatt bereits im Voraus das Verhalten des Schädlings kennen zu müssen. Beispielsweise könnte zum Erkennen eines Krypto-Trojaners die durchschnittliche Anzahl an neu erstellten, bearbeiteten und gelöschten Dateien pro Tag herhalten. Während ein typischer Büroarbeiter eher selten viele Dateien gleichzeitig anlegt und gleichzeitig viele Dateien löscht, ist genau das das Hauptgeschäft von Krypto-Trojanern. Solch eine Erkennung von Abweichungen kann mit Canaries ergänzt werden. Dabei handelt es sich um Dateien, die extra als Opfer für einen Verschlüsselungstrojaner bereitgestellt werden und deren Bearbeitung als ein eindeutiges Indiz für das Vorhandensein eines Krypto-Trojaners dienen kann. Das Ziel der Erkennung ist es, von einem Problem zu erfahren, noch bevor der Nutzer etwa Ungewöhnliches feststellt.

Abschließend muss das Thema der Behandlung betrachtet werden. Hierzu zählen an erster Stelle regelmäßige Backups. Das häufig kommunizierte Mantra, Dateien auf einem externen Datenträger zu sichern und diesen anschließend wieder vom Computer zu trennen, stellt in den meisten Umgebungen keinen ausreichenden Schutz dar. Denn während des Backups kann auch der externe Datenträger befallen und verschlüsselt werden. Der eigentliche Wunsch hinter solch einer Aussage ist vielmehr, eine Sicherung zu erstellen, die von einer eventuellen Infektion nicht beeinflusst werden kann. Sinnvolle Varianten können hierbei extern durchgeführte Backups sein, die nicht vom infizierten Nutzer angestoßen und demnach auch nicht vom infizierten Nutzer modifiziert werden können. Auch lokale Backups unter der Hoheit eines anderen Systemnutzers stellen eine Möglichkeit dar. Noch sinnvoller als ein einfaches Backup ist jedoch eine Versionierung, die zwar mehr Speicherplatz benötigt, dafür aber auch eine selektive Wiederherstellung von Dateiinhalten unterschiedlichster Zeitpunkte ermöglicht.

Die Implementierung eines entsprechenden Schutzes ist auch mit einfachen Tools möglich - auch, wenn speziell entwickelte Werkzeuge wesentlich mehr Komfort bieten. Im Folgenden soll eine Erkennung und Behandlung eines Krypto-Trojaner-Angriffes mit Hilfe von Mercurial dargestellt werden. Wie Mercurial für das Erkennen von unspezifischen Angriffen auf Server zum Einsatz kommen kann, hatte ich bereits vor einiger Zeit schon einmal demonstriert.

Anbei einmal ein beispielhaftes Script zur Erkennung von Abweichungen in der Bearbeitung von Dateien. Das Script ermittelt Abweichungen von der durchschnittlichen Menge an erstellten/gelöschten/bearbeiteten Dateien. Zudem prüft es separat die Veränderung eines Canaries. Das Script ist nur als Proof-of-Concept eines dateiorientierten host-based, anomality-based Intrusion Detection Systems zu verstehen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/usr/bin/php
<?php
  // user-defined values
  define("CHECKFOLDER", "/testpit/");
  define("CHECKCANARY", CHECKFOLDER . "data/do-not-edit.txt");
  define("STATUSFILE",  CHECKFOLDER . "status/status");

  // deviation of user behaviour from previously collected behaviour
  define("DEVIATIONVALUE", 0.5); // default deviation of 50% is allowed

  // generated values
  define("CHECKDATE", date("Ymd-His"));

  // concatenated actions
  define("ADDREMOVECMD", "hg addremove -R \"" . CHECKFOLDER . "\" -X \"" . CHECKCANARY . "\"");
  define("COMMITCMD",    "hg commit -R \"" . CHECKFOLDER . "\" -X \"" . CHECKCANARY . "\" -m \"" . CHECKDATE . "\"");
  define("STATUSCMD",    "hg status -R \"" . CHECKFOLDER . "\"");

  // static definitions
  define("ADDEDHINT",     "A");
  define("MISSINGHINT",   "!");
  define("MODIFIEDHINT",  "M");
  define("NOTTRACKEDHINT","?");
  define("REMOVEDHINT",   "R");

  define("HINTDELIMITER",       " ");
  define("STATISTICSDELIMITER", ":");

  function check_filename($line, $filename) {
    $result = false;
   
    $parts = explode(HINTDELIMITER, $line, 2);
    if ((false !== $parts) && (2 === count($parts))) {
      $result = (0 == strcasecmp(CHECKFOLDER . $parts[1], $filename));
    }

    return $result;
  }

  function check_hint($line, $hint) {
    $result = false;

    $parts = explode(HINTDELIMITER, $line, 2);
    if ((false !== $parts) && (2 === count($parts))) {
      $result = (0 == strcasecmp($parts[0], $hint));
    }

    return $result;
  }

  function get_statistics_text($additions, $deletions, $modifications) {
    return (CHECKDATE . STATISTICSDELIMITER . ADDEDHINT . STATISTICSDELIMITER . $additions .
                        STATISTICSDELIMITER . MODIFIEDHINT . STATISTICSDELIMITER . $modifications .
                        STATISTICSDELIMITER . REMOVEDHINT . STATISTICSDELIMITER . $deletions);
  }

  function check_statistics($additions, $deletions, $modifications) {
    $result = true;

    // with any modification there's nothing to check
    if (0 < ($additions + $deletions + $modifications)) {
      // read statistics and execute statistics checkvg_additions_count     = 0;
      $avg_additions_count     = 0;
      $avg_additions_value     = 0;
      $avg_deletions_count     = 0;
      $avg_deletions_value     = 0;
      $avg_modifications_count = 0;
      $avg_modifications_value = 0;

      if (is_file(STATUSFILE)) {
        $statistics = file(STATUSFILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if ((false !== $statistics) && (0 < count($statistics))) {
          // calculate average additions, deletions and modifications from statistics data
          foreach ($statistics as $line) {
            $parts = explode(STATISTICSDELIMITER, $line, 7);
            if ((false !== $parts) && (7 === count($parts))) {
              // check if value is integer and bigger than 0
              if (is_numeric($parts[2]) && (0 < $parts[2])) {
                $avg_additions_value += $parts[2];
                $avg_additions_count++;
              }
              if (is_numeric($parts[6]) && (0 < $parts[6])) {
                $avg_deletions_value += $parts[6];
                $avg_deletions_count++;
              }
              if (is_numeric($parts[4]) && (0 < $parts[4])) {
                $avg_modifications_value += $parts[4];
                $avg_modifications_count++;
              }
            }
          }
        }
      }

      // there's nothing wrong when nothing happened
      if (0 < $additions) {
        // when actions has never been seen then that's a deviation
        if (0 === $avg_additions_count) {
          $result = false;
        } else {
          // more additions than expected
          if (((1.0 + DEVIATIONVALUE) * ($avg_additions_value / $avg_additions_count)) < $additions) {
            $result = false;
          }
        }
      }

      // there's nothing wrong when nothing happened
      if (0 < $deletions) {
        // when actions has never been seen then that's a deviation
        if (0 === $avg_deletions_count) {
          $result = false;
        } else {
          // more deletions than expected
          if (((1 + DEVIATIONVALUE) * ($avg_deletions_value / $avg_deletions_count)) < $deletions) {
            $result = false;
          }
        }
      }

      // there's nothing wrong when nothing happened
      if (0 < $modifications) {
        // when actions has never been seen then that's a deviation
        if (0 === $avg_modifications_count) {
          $result = false;
        } else {
          // more modifications than expected
          if (((1 + DEVIATIONVALUE) * ($avg_modifications_value / $avg_modifications_count)) < $modifications) {
            $result = false;
          }
        }
      }
    }
   
    // add new result to statistics
    file_put_contents(STATUSFILE,
                      get_statistics_text($additions, $deletions, $modifications) . "\n",
                      FILE_APPEND | LOCK_EX);

    return $result;
  }

  function main() {
    $additions     = 0;
    $deletions     = 0;
    $modifications = 0;

    $canary_found = false;

    // retrieve information about file changes
    exec(STATUSCMD, $output);

    // accept file changes right away
    exec(ADDREMOVECMD);
    exec(COMMITCMD);

    // iterate through file changes
    foreach ($output as $line) {
      // check if the canary file is part of the modifications
      if (check_filename($line, CHECKCANARY)) {
        $canary_found = true;
      } else {
        // check if a file has been added
        if (check_hint($line, ADDEDHINT) || check_hint($line, NOTTRACKEDHINT)) {
          $additions++;
        } else {
          // check if a file has been deleted
          if (check_hint($line, MISSINGHINT) || check_hint($line, REMOVEDHINT)) {
            $deletions++;
          } else {
            // check if a file has been modified
            if (check_hint($line, MODIFIEDHINT)) {
              $modifications++;
            }
          }
        }
      }
    }

    if (0 < ($additions + $deletions + $modifications)) {
      // accept file changes
      exec(ADDREMOVECMD);
      exec(COMMITCMD);
    }

    // print result
    print(get_statistics_text($additions, $deletions, $modifications) . "\n");

    // the canary has been modified
    if ($canary_found) {
      //!!! do something
      print("ALERT! CANARY HAS BEEN MODIFIED!\n");
    }

    // check if the modifications do not match the statistics
    if (!check_statistics($additions, $deletions, $modifications)) {
      //!!! do something
      print("ALERT! BEHAVIOUR DOES NOT MATCH STATISTICS!\n");
    }
  }

  // execute application
  main();

?>

Bei jedem Aufruf ermittelt das Script mit Hilfe von Mercurial, welche Dateien in einem Repository/Ordner hinzugefügt, entfernt oder bearbeitet wurden. Sollte sich darunter die Canary-Datei befinden, wird Alarm geschlagen. Zudem wird eine statistische Analyse durchgeführt. In diesem einfachen Beispiel gilt als Abweichung, wenn mehr als 150% der durchschnittlichen Dateioperationen erkannt wurden. Wird solch eine Abweichung erkannt, wird ebenfalls Alarm geschlagen. Durch die Verwendung von Mercurial ließen sich zudem zu jeder Zeit alle bearbeiteten Dateien rekonstruieren.

In einem realen Umfeld könnte solch eine Analyse natürlich noch viel tiefergreifend sein. So könnten beispielsweise folgende Prüfungen mit einfließen, um Anomalien besser erkennen zu können:

  • Es könnte die Uhrzeit der Dateibearbeitung mit in die Analyse einfließen. In Kombination mit der Auswertung von Arbeitsplänen und/oder Anwesenheitszeiten ließen sich bessere Modelle erstellen. So sollte es seltener der Fall sein, dass Dateien eines Mitarbeiters bearbeitet werden, der gar nicht anwesend ist.
  • Es könnte die Relation der Dateibearbeitungen untereinander betrachtet werden. Beispielswiese werden Büromitarbeiter wesentlich mehr Dateien erstellen und bearbeiten als löschen, da Arbeitsergebnisse selten wieder vernichtet werden.
  • Es könnte das ursprüngliche Dateidatum mit berücksichtigt werden. Beispielsweise ist es eher unüblich, dass Dateien ab einem bestimmten Alter noch einmal bearbeitet werden. Stattdessen werden sie eher als Referenz vorgehalten, anstatt als aktives Arbeitsdokument zu fungieren.

Je besser das erstellte Modell ist, mit dem das Verhalten der Systemnutzer abgeglichen wird, desto schneller erkennt man in Ausnahmesituationen einen potentiellen Angreifer. Nicht immer müssen das externe Angreifer sein. Auch interne Mitarbeiter, die ein ungewöhnliches Verhalten in den Tag legen, können auf diese Weise unter Umständen identifiziert werden - es muss nicht einmal zwingend eine böse Absicht hinter diesem Verhalten stecken, evtl. stellt ein Mitarbeiter einfach eine Ausnahme zur üblichen Regel dar.

Generell sollte man sich bei solch einer Angriffserkennung auf Basis von Abweichungsermittlungen daran gewöhnen, auch mal False Positives zu erhalten. Diese sind durchaus wünschenswert, da sie einerseits zeigen, dass die durchgeführten Analysen tatsächlich einen Effekt haben und einem andererseits Verbesserungspotentiale in den erstellten Anomaliemodellen aufzeigen. 🙂

Verteidigende Grüße, Kenny

3D-Barcodes mit Farbfiltern auslesen…

Bereits vor einer ganzen Weile hatte ich mal mit Licht und Farbfiltern herum experimentiert. Damals hatte ich mit Hilfe von Farbfiltern das Licht aufgespalten, das von einer RGB-LED emittiert wurde und dabei auch erwähnt, dass man auf Basis dieser Bündelung Daten übertragen könne.

Einige Zeit später war ich auf der Suche nach einer Möglichkeit, Binärdaten über ein Druckerzeugnis zu übertragen. Dabei denkt man heutzutage natürlich erst einmal an 2D-Barcodes (z.B. Aztec-Codes, Matrix-Codes oder die allseits bekannten QR-Codes). Leider reichte deren Datendichte nicht aus. In ähnlichen Fällen werden deshalb gelegentlich 3D-Barcodes (z.B. der HCCB-Code von Microsoft) einsetzt. Diese funktionieren, indem neben den Dimensionen Höhe und Breite noch die Dimension der Farbe eingeführt wird (in animierten Medien kann noch die vierte Dimension der Zeit eingeführt werden). Allerdings benötigen solche 3D-Barcodes typischerweise mehrere Dinge:

  • Eine Lizenz, um das Verfahren nutzen zu dürfen.
  • Stark angepasste Lesegeräte und/oder Erkennungsalgorithmen.

In dem Moment dachte ich an das Experiment mit den Farbfiltern zurück. Wenn man es hinbekäme, die Komplexität des Barcode-Lesens und die Komplexität des gesteigerten Farbraums voneinander zu trennen, könnte man einfach reproduzierbare Barcodes erzeugen, die gleichzeitig primär mit vorhandenen Standardmitteln lesbar wären. Geboren war der kombinierte Farb-Barcode...

kombinierter Farb-Barcode

kombinierter Farb-Barcode

Herstellen lässt er sich recht einfach:

  1. Man nimmt sich zwei normale 2D-Barcodes und legt diese übereinander.
  2. Pixel, die in beiden Barcodes vorkommen, werden schwarz gefärbt.
  3. Pixel, die in keinem der beiden Barcodes vorkommen, werden weiß gefärbt.
  4. Pixel, die nur im ersten Barcode vorkommen, werden mit einer Farbe A eingefärbt.
  5. Pixel, die nur im zweiten Barcode vorkommen, werden mit einer Farbe B eingefärbt.

Gedanken machen muss man sich nun darum, wie man die Barcodes wieder getrennt bekommt - dafür ist es wichtig, Farbe A und Farbe B richtig zu wählen. Diese beiden Farben müssen eine Beziehung zueinander haben, die sich wie folgt beschreiben lässt:

  • Wenn Farbe A durch einen Farbfilter der Farbe B betrachtet wird, muss ein möglichst starker Farbkontrast entstehen.
  • Wenn Farbe B durch einen Farbfilter der Farbe A betrachtet wird, muss ein möglichst starker Farbkontrast entstehen.

Glücklicherweise hatte ich Farbfilter zuhause, die diese beiden Bedingungen erfüllen - rote und blaue.

roter und blauer Farbfilter

roter und blauer Farbfilter

Wichtig für einen produktiven Einsatz ist es, dass die Farbfilter und die für den Druck verwendeten Farben aufeinander abgestimmt werden. Im Haushaltsgebrauch wird man das nicht unbedingt hinbekommen, weshalb das Auslesen des Barcodes im selbstgebastelten Umfeld wohl mehr Geduld erfordert, als es im professionellen Umfeld der Fall wäre.

gedruckter Barcode

gedruckter Farb-Barcode

Um nun den Inhalt der Barcodes lesen zu können, macht man einfach folgendes: Man platziert einen Farbfilter vor der Kamera und scannt den Code. Anschließend tauscht man den Farbfilter vor der Kamera aus und scannt den Code erneut ("shuttern"). Eine Alternativmöglichkeit ist, zwei Kameras gleichzeitig zu verwenden, die statische Farbfilter verwenden - so ist es möglich, trotz doppelter Datendichte die Lesegeschwindigkeit konstant zu halten.

Barcode mit Farbfilter Barcode mit Farbfilter

Farb-Barcode mit Farbfilter

Wie man erkennt, geschehen beim Aufnehmen des Barcodes nun zwei vier Dinge:

  • Schwarze Pixel bleiben unverändert und stellen die Kontrastfarbe dar.
  • Weiße Pixel werden eingefärbt und stellen die Grundfarbe dar.
  • Pixel in der Farbe des Filters werden herausgefiltert und stellen die Grundfarbe dar.
  • Pixel in der Gegenfarbe des Filters werden verstärkt und stellen die Kontrastfarbe dar.

Durch Einsatz der Farbfilter und dem Effekt der Kontraständerung der Gegenfarbe entstehen zwei unterschiedliche Barcode-Abbildungen auf Basis eines einzigen Farb-Barcodes. Jeder QR-Code-Leser, der einen automatischen Kontrastabgleich vornimmt, kann diese Barcodes bereits lesen.

Bei der Barcode-Erkennung können nach dem Einsatz des Filters noch zwei Schritte unternommen werden, um das Leseergebnis zu verbessern. Im ersten Schritt kann eine Überführung in ein Graustufenbild erfolgen, um den Bias des Farbsensors abzumildern. Wie man in den Ausgangsbildern erkennt, ist der Kontrast im Blaufilter-Bild wesentlich schlechter erkennbar als im Rotfilter-Bild.

Farb-Barcode mit Farbfilter als Graustufenbild Farb-Barcode mit Farbfilter als Graustufenbild

Farb-Barcode mit Farbfilter als Graustufenbild

Im zweiten Schritt kann mit Hilfe eines Schwellwertabgleichs der tatsächlich benötigte Inhalt gut gefiltert werden. GIMP bietet hierfür beispielsweise ein einfach zu verwendendes Werkzeug, das einem eindeutig anzeigt, welche Schwellwerte von Interesse sind.

Schwellwertabgleich Schwellwertabgleich

Schwellwertabgleich

Die daraus entstehenden Barcodes sollten nun wirklich von jedem Barcode-Scanner gelesen werden können:

Farb-Barcode mit Farbfilter als Graustufenbild nach Schwellwertfilter Farb-Barcode mit Farbfilter als Graustufenbild nach Schwellwertfilter

Farb-Barcode mit Farbfilter als Graustufenbild nach Schwellwertfilter

Um zu zeigen, dass das Auslesen auch mit Standardmitteln funktioniert, habe ich den prototypischen Versuch (zuhause ausgedruckter Farb-Barcode + iPhone + vorgehaltener Filter + App aus dem App-Store) einfach mal per Video aufgezeichnet. Ja, es funktioniert nicht perfekt, aber weder Licht, Druckerfarbe, Farbfilter noch verwendete App sind in irgendeiner Art aufeinander abgestimmt. Das sollte man beim Betrachten des Videos im Hinterkopf behalten. 🙂

Einsatz finden kann solch ein Verfahren in meinen Augen in zwei Situationen:

  • In Situationen, in denen in einem Barcode mehr Daten gespeichert werden müssen, als in einen konventionellen Barcode passen.
  • In Situationen, in denen in einem Barcode Daten für mehrere Empfänger gespeichert werden sollen. Möglich wäre beispielsweise das Szenario, dass zwei Verarbeitungsschritte Informationen aus einem Barcode lesen sollen. Der Barcode-Leser des ersten Verarbeitungsschritts erhält einen blauen Farbfilter, dessen zu lesende Daten werden in rot encodiert. Der Barcode-Leser des zweiten Verarbeitungsschritts erhält einen roten Farbfilter, dessen zu lesende Daten werden in blau encodiert. Bei gut abgestimmten Filtern und Druckfarben sind die Barcode-Leser nun optisch nicht mehr in der Lage, die falschen Daten vom Farb-Barcode auszulesen.

barcode_gruesse

Passwort-Reset in WordPress deaktivieren

Immer wieder findet man vermeindliche Kleinigkeiten, mit denen man sich noch besser gegen Angreifer schützen kann. Einer dieser blind Spots war bei mir bisher die Passwort-zurücksetzen-Funktion meiner Webseiten. WordPress liefert hier leider keine einfache Konfigurationseinstellung, um sie zu deaktivieren.

Da ich in meinem Fall neben dem WordPress-Nutzer auch gleichzeitig der Serveradmin bin und mir direkt auf der Kommandozeile ein neues Passwort verpassen kann, benötige ich den Weg über eine Passwort-Reset-E-Mail gar nicht und kann diese Funktion auch genauso gut abschalten. So besteht nicht mehr die Gefahr, dass meine Webseiten durch gehijackte E-Mail-Accounts kompromittiert werden können.

Hierfür notwendig ist ein winziges Plugin, das man sich schnell selbst zusammenschreiben kann. Der Inhalt kann wie folgt aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
  /*
    Plugin Name: KillPWReset
    Description: Disables the Password Reset in WordPress.
    Version: 0.1c1
  */


function killpwreset_disable($userid) {
  return false;
}

function killpwreset_errortext($errortext) {
  return "Login failed.";
}

add_filter("allow_password_reset", "killpwreset_disable");
add_filter("login_error",          "killpwreset_errortext");
?>

Der Code sorgt dafür, dass für sämtliche Nutzer der Passwort-Reset deaktiviert wird (man kann es auch per User-ID steuern (z.B. nur Gäste, aber keine Admins). Weiterhin sorgt er dafür, dass eine generische Fehlermeldung erzeugt wird, wenn ein Login fehlschlägt. Typischerweise ist in der Fehlermeldung die Passwort-Reset-Funktion mit verlinkt. So wird der Fehlertext samt Link einfach überschrieben.

Deaktivierte Grüße, Kenny

HTTPS-Fehler im Link Indication Plugin

Ich setze bereits seit einer Weile das Link Indication Plugin ein, das externe Links mit einem Icon ergänzt, sodass man sie besser erkennen kann. Seitdem jedoch meine und immer mehr externe Seiten HTTPS statt HTTP verwenden, ist mir aufgefallen, dass die Icons nicht mehr angezeigt wurden.

Nun habe ich mir einfach mal den Quelltext des Plugins angesehen, um dem Problem auf die Schliche zu kommen. Und tatsächlich: ein winziger Bug ist der Auslöser des ganzen Problems. Diesen findet man in der Methode "GetDomainnameForUri()", die in der Version 4.4 wie folgt aussieht:

1
2
3
4
5
6
7
8
9
10
11
12
        /**
         * Retrieve the domain name from the URI. We consider sub domains as well.
         */
   
        function GetDomainnameFromUri($uri){
            $exp1 = '/^(http|https|ftp)?(:\/\/)?(www.)?([^\/]+)/i';
                preg_match($exp1, $uri, $matches);
                if (isset($matches[4])) {
                return $matches[4];
            } else {
                        return '';
                }
        }

Hier wird die URL anhand eines regulären Ausdrucks zerteilt. Das Problem ist der erste Teil des Ausdrucks ("(http|https|ftp)?"), der besagt, dass ein Treffer vorhanden ist, sobald entweder "http", "https" oder "ftp" gefunden wird. Leider liefert dieser Ausdruck sofort ein Ergebnis zurück, sobald es "http" gesehen hat, sodass das mittlere "https" nie betrachtet wird.

Um mir das genauer anzusehen, habe ich mir mal einen Testfall geschrieben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
  function GetDomainnameFromUri($uri){
    $exp1 = '/^(http|https|ftp)?(:\/\/)?(www.)?([^\/]+)/i';
    preg_match($exp1, $uri, $matches);
    print_r($matches);
  }

  GetDomainnameFromUri("/example");
  GetDomainnameFromUri("example.com");
  GetDomainnameFromUri("www.example.com");
  GetDomainnameFromUri("example.com/example");
  GetDomainnameFromUri("www.example.com/example");
  GetDomainnameFromUri("http://example.com");
  GetDomainnameFromUri("http://www.example.com");
  GetDomainnameFromUri("http://example.com/example");
  GetDomainnameFromUri("http://www.example.com/example");
  GetDomainnameFromUri("https://example.com");
  GetDomainnameFromUri("https://www.example.com");
  GetDomainnameFromUri("https://example.com/example");
  GetDomainnameFromUri("https://www.example.com/example");
?>

Hier die zugehörigen Ergebnisse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
Array
(
)
Array
(
    [0] => example.com
    [1] =>
    [2] =>
    [3] =>
    [4] => example.com
)
Array
(
    [0] => www.example.com
    [1] =>
    [2] =>
    [3] => www.
    [4] => example.com
)
Array
(
    [0] => example.com
    [1] =>
    [2] =>
    [3] =>
    [4] => example.com
)
Array
(
    [0] => www.example.com
    [1] =>
    [2] =>
    [3] => www.
    [4] => example.com
)
Array
(
    [0] => http://example.com
    [1] => http
    [2] => ://
    [3] =>
    [4] => example.com
)
Array
(
    [0] => http://www.example.com
    [1] => http
    [2] => ://
    [3] => www.
    [4] => example.com
)
Array
(
    [0] => http://example.com
    [1] => http
    [2] => ://
    [3] =>
    [4] => example.com
)
Array
(
    [0] => http://www.example.com
    [1] => http
    [2] => ://
    [3] => www.
    [4] => example.com
)
Array
(
    [0] => https:
    [1] => http
    [2] =>
    [3] =>
    [4] => s:
)
Array
(
    [0] => https:
    [1] => http
    [2] =>
    [3] =>
    [4] => s:
)
Array
(
    [0] => https:
    [1] => http
    [2] =>
    [3] =>
    [4] => s:
)
Array
(
    [0] => https:
    [1] => http
    [2] =>
    [3] =>
    [4] => s:
)

Wie man sieht, wird durch den ersten Ausdruck ("(http|https|ftp)?") das "http" herausgetrennt, die nächsten beiden Ausdrücke ("(:\/\/)?" und "(www.)?") liefern leere Ergebnisse und erst der letzte Ausdruck ("([^\/]+)") fängt den Rest ab - allerdings nur bis zum ersten Slash. Dementsprechend heißen alle HTTPS-URLs nach dem Parsen nur noch "s:".

In dem Plugin konfiguriert man auch die Adresse seiner eigenen Website. Diese Konfiguration wird mit der gleichen Funktion bearbeitet. Wenn nun also die eigene Seite eine HTTPS-Adresse enthält und gleichzeitig ein externer Link eine HTTPS-Adresse enthält, so führen diese beiden unterschiedlichen Adressen zum selben Ergebnis "s:" in der Funktion "GetDomainnameFromUri()".

Ein weiteres Problem in dieser Funktion dürfte eher wenige Adressen treffen: Der dritte Ausdruck ("(www.)?") hat nämlich ein Problem - den Punkt. Bei regulären Ausdrücken steht der Punkt nicht einfach nur für das Zeichen ".", sondern für alle Zeichen. Daher muss er, wenn das Zeichen "." gemeint ist, escaped werden ("\.").

Nehmen wir mal ein Beispiel, wo dieser Bug zu Problem führt: Wenn ich beispielsweise die URL der Supportseite der IBM hernehme, so lautet diese "http://www.ibm.com/support/entry/portal/de/de". Wenn man diese jedoch besucht, wird man auf "http://www-947.ibm.com/support/entry/portal/support" weitergeleitet. Der Ausdruck ("(www.)?") erkennt nun jedoch "www-" und schneidet es weg. Übrig bleibt dann die nicht existente Domain "947.ibm.com":

1
2
3
4
5
6
7
8
Array
(
    [0] => http://www-947.ibm.com
    [1] => http
    [2] => ://
    [3] => www-
    [4] => 947.ibm.com
)

Weiterhin kann die jetzige Funktion weder mit Authentisierungen, noch mit Portnummern umgehen. Diese werden einfach der Domain zugerechnet. Um das alles zu beheben, muss man den Ausdruck ein wenig abändern. Die neue Variante kann dann mit wesentlich mehr Fällen umgehen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
  function GetDomainnameFromUri($uri){
    $exp1 = '/^(([^:]+:\/\/)|(\/\/))?(([^:]+):([^@]+)@)?([^:\/\?\#]+)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/i';
    preg_match($exp1, $uri, $matches);
    print_r($matches);
  }

  GetDomainnameFromUri("/example");
  GetDomainnameFromUri("example.com");
  GetDomainnameFromUri("www.example.com");
  GetDomainnameFromUri("example.com/example");
  GetDomainnameFromUri("www.example.com/example");
  GetDomainnameFromUri("http://example.com");
  GetDomainnameFromUri("http://www.example.com");
  GetDomainnameFromUri("http://example.com/example");
  GetDomainnameFromUri("http://www.example.com/example");
  GetDomainnameFromUri("https://example.com");
  GetDomainnameFromUri("https://www.example.com");
  GetDomainnameFromUri("https://example.com/example");
  GetDomainnameFromUri("https://www.example.com/example");

  GetDomainnameFromUri("//example.com");
  GetDomainnameFromUri("user:password@example.com");
  GetDomainnameFromUri("example.com:80");
  GetDomainnameFromUri("example.com/example?example=example");
  GetDomainnameFromUri("example.com/example#example");
?>

Hier dazu der entsprechende Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
Array
(
)
Array
(
    [0] => example.com
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
)
Array
(
    [0] => www.example.com
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => www.example.com
)
Array
(
    [0] => example.com/example
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
    [8] =>
    [9] =>
    [10] => /example
)
Array
(
    [0] => www.example.com/example
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => www.example.com
    [8] =>
    [9] =>
    [10] => /example
)
Array
(
    [0] => http://example.com
    [1] => http://
    [2] => http://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
)
Array
(
    [0] => http://www.example.com
    [1] => http://
    [2] => http://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => www.example.com
)
Array
(
    [0] => http://example.com/example
    [1] => http://
    [2] => http://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
    [8] =>
    [9] =>
    [10] => /example
)
Array
(
    [0] => http://www.example.com/example
    [1] => http://
    [2] => http://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => www.example.com
    [8] =>
    [9] =>
    [10] => /example
)
Array
(
    [0] => https://example.com
    [1] => https://
    [2] => https://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
)
Array
(
    [0] => https://www.example.com
    [1] => https://
    [2] => https://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => www.example.com
)
Array
(
    [0] => https://example.com/example
    [1] => https://
    [2] => https://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
    [8] =>
    [9] =>
    [10] => /example
)
Array
(
    [0] => https://www.example.com/example
    [1] => https://
    [2] => https://
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => www.example.com
    [8] =>
    [9] =>
    [10] => /example
)
Array
(
    [0] => //example.com
    [1] => //
    [2] =>
    [3] => //
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
)
Array
(
    [0] => user:password@example.com
    [1] =>
    [2] =>
    [3] =>
    [4] => user:password@
    [5] => user
    [6] => password
    [7] => example.com
)
Array
(
    [0] => example.com:80
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
    [8] => :80
    [9] => 80
)
Array
(
    [0] => example.com/example?example=example
    [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
    [8] =>
    [9] =>
    [10] => /example
    [11] => ?example=example
    [12] => example=example
)
Array
(
    [0] => example.com/example#example
   [1] =>
    [2] =>
    [3] =>
    [4] =>
    [5] =>
    [6] =>
    [7] => example.com
    [8] =>
    [9] =>
    [10] => /example
    [11] =>
    [12] =>
    [13] => #example
   [14] => example
)

Die eigentliche Methode sollte also nach Möglichkeit so aussen:

1
2
3
4
5
6
7
8
9
10
11
12
        /**
         * Retrieve the domain name from the URI. We consider sub domains as well.
         */
   
        function GetDomainnameFromUri($uri){
            $exp1 = '/^(([^:]+:\/\/)|(\/\/))?(([^:]+):([^@]+)@)?([^:\/\?\#]+)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/i';
            preg_match($exp1, $uri, $matches);
            if (isset($matches[7])) {
                return $matches[7];
            } else {
                return '';
            }
        }

Ich habe diese neue Version nun bei mir im Einsatz und sie funktioniert so, wie die alte es von Anfang an hätte tun sollen. 🙂

Linkindikatorgrüße, Kenny

haveged: Entropiesammlung unter Linux

Vor ein paar Tagen hatte ich vorgestellt, wie man den Hardware-Zufallszahlengenerator des Raspberry Pi nutzen kann, um unter Linux weniger Probleme mit hängenden Kryptographievorgängen zu haben. Leider hat nicht jeder Linux-Server einen Hardware-Zufallszahlengenerator, der als Entropiequelle genutzt werden kann - also muss eine andere Quelle herhalten.

Glücklicherweise hat sich das französische Institut IRISA Anfang des Jahrtausends das HAVEGE-Verfahren (HArdware Volatile Entropy Gathering and Expansion) ausgedacht. Dieses basiert darauf, dass in modernen Computersystem unzählige verschiedene Hardwarezustände (Cache-Zustände, das Auftreten von Interrupts, etc.) dafür verantwortlich sind, dass der exakt gleiche Code im Micro- und Nanosekundenbereich unterschiedlich schnell abgearbeitet wird. Die Abweichungen, die bei einer entsprechenden Zeitmessung auftreten, sind - so die Erfinder - nahezu unmöglich zu erahnen oder gar zu reproduzieren. Genau diese Abweichungen wären daher eine gute Quelle für Entropie.

Zwar wird das originale HAVEGE seit Jahren nicht mehr weiterentwickelt, jedoch gibt es den Ableger haveged, der inzwischen in allen großen Distributionen enthalten sein sollte. Sollte deshalb, da z.B. RHEL (Red Hat Enterprise Linux) das Paket nicht standardmäßig mit ausliefert. Hier muss auf das EPEL-Projekt (Extra Packages for Enterprise Linux) des Fedora Project zurückgegriffen werden, das das Paket für RHEL 6 und für RHEL 7 pflegt (RHEL basiert auf Fedora). Die Installation ist dann recht einfach über den rpm-Befehl möglich.

Leider ist haveged zu Unrecht ein wenig in Verruf geraten. Hintergrund ist, dass PolarSSL mbed SSL im Dezember 2011 ein Security Advisory herausgegebene hatte. Diese SSL-Bibliothek verwendete bis dahin HAVEGE als alleinige Entropiequelle für Schlüsselerzeugungen und dergleichen. Jedoch stellte man fest, dass der RDTSC-Befehl, der zum exakten Zeitmessen verwendet wird, auf einigen virtualisierten Maschinen nur schlechte (und damit leicht reproduzierbare) Werte zurücklieferte.

Es ist daher potentiell sinnvoll, vor dem produktiven Einsatz zu prüfen, ob der RDTSC-Befehl korrekt funktioniert. Eine Möglichkeit ist, die Ausgabe von haveged durch einen dieharder Testlauf prüfen zu lassen. Hierzu muss man einfach haveged aufrufen und dessen Output in den Eingang von dieharder leiten:

1
sudo haveged -n 0 -f - | dieharder -g 200 -a

Trotz der Vorsicht hat haveged auch einige Anhänger: So erklärt beispielsweise Heinlein Support (der Betreiber des sicheren E-Mail-Dienstes mailbox.org) den Einsatz von haveged in seinem Linux-Admin-Blog. Die Distribution SLES (SUSE Linux Enterprise Server) geht sogar noch einen Schritt weiter. Dort ist haveged seit der Version 11.1 standardmäßig installiert und seit der Version 11.2 auch standardmäßig aktiviert. Viele Linux-Administratoren verwenden also potentiell bereits haveged in ihrer Produktumgebung, ohne es überhaupt zu wissen.

Natürlich habe auch ich mir angesehen, ob ich haveged einsetzen kann. Um mir eine abschließende Meinung bilden zu können, habe ich auf jedem in Frage kommenden System den dieharder Testlauf durchgeführt. An dieser Stelle veröffentliche ich auch der Vollständigkeit halber die entsprechenden Ergebnisse.

Auf dem "BCM2835" des Raspberry Pi sehen die Ergebnisse gut aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  8.48e+05  |3348700180|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.45785536|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.60477535|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.29286920|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.23237712|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.05506401|  PASSED  
        diehard_opso|   0|   2097152|     100|0.77736890|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.62599391|  PASSED  
         diehard_dna|   0|   2097152|     100|0.28611820|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.75847797|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.27169177|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.91232487|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.94904496|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.21628095|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.32795324|  PASSED  
        diehard_sums|   0|       100|     100|0.00069872|   WEAK  
        diehard_runs|   0|    100000|     100|0.76153066|  PASSED  
        diehard_runs|   0|    100000|     100|0.97532990|  PASSED  
       diehard_craps|   0|    200000|     100|0.69750059|  PASSED  
       diehard_craps|   0|    200000|     100|0.70646049|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.12267708|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.19422474|  PASSED  
         sts_monobit|   1|    100000|     100|0.76342910|  PASSED  
            sts_runs|   2|    100000|     100|0.41068776|  PASSED  
          sts_serial|   1|    100000|     100|0.43901131|  PASSED  
          sts_serial|   2|    100000|     100|0.08832557|  PASSED  
          sts_serial|   3|    100000|     100|0.84110757|  PASSED  
          sts_serial|   3|    100000|     100|0.41468366|  PASSED  
          sts_serial|   4|    100000|     100|0.72012668|  PASSED  
          sts_serial|   4|    100000|     100|0.36171448|  PASSED  
          sts_serial|   5|    100000|     100|0.81674015|  PASSED  
          sts_serial|   5|    100000|     100|0.88818478|  PASSED  
          sts_serial|   6|    100000|     100|0.97895561|  PASSED  
          sts_serial|   6|    100000|     100|0.98733145|  PASSED  
          sts_serial|   7|    100000|     100|0.72348815|  PASSED  
          sts_serial|   7|    100000|     100|0.11691286|  PASSED  
          sts_serial|   8|    100000|     100|0.61923729|  PASSED  
          sts_serial|   8|    100000|     100|0.97185433|  PASSED  
          sts_serial|   9|    100000|     100|0.75444842|  PASSED  
          sts_serial|   9|    100000|     100|0.56167376|  PASSED  
          sts_serial|  10|    100000|     100|0.99999103|   WEAK  
          sts_serial|  10|    100000|     100|0.94590480|  PASSED  
          sts_serial|  11|    100000|     100|0.91257068|  PASSED  
          sts_serial|  11|    100000|     100|0.66909798|  PASSED  
          sts_serial|  12|    100000|     100|0.86817154|  PASSED  
          sts_serial|  12|    100000|     100|0.76794279|  PASSED  
          sts_serial|  13|    100000|     100|0.40705505|  PASSED  
          sts_serial|  13|    100000|     100|0.50118838|  PASSED  
          sts_serial|  14|    100000|     100|0.61229062|  PASSED  
          sts_serial|  14|    100000|     100|0.85491685|  PASSED  
          sts_serial|  15|    100000|     100|0.91714380|  PASSED  
          sts_serial|  15|    100000|     100|0.62863486|  PASSED  
          sts_serial|  16|    100000|     100|0.79024560|  PASSED  
          sts_serial|  16|    100000|     100|0.46711922|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.32027203|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.82936629|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.32836216|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.05014161|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.60319043|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.46447338|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.78238492|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.47473097|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.96469269|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.16923688|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.21372692|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.80306989|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.10142178|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.09184875|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.75662814|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.11774862|  PASSED  
    rgb_permutations|   2|    100000|     100|0.52525569|  PASSED  
    rgb_permutations|   3|    100000|     100|0.56127774|  PASSED  
    rgb_permutations|   4|    100000|     100|0.66925921|  PASSED  
    rgb_permutations|   5|    100000|     100|0.02115162|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.76176860|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.96497209|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.43298109|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.81781736|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.62701591|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.62074437|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.39233421|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.88875393|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.56490272|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.85420827|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.90991238|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.83617905|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.10804203|  PASSED  
      rgb_lagged_sum|  13|   1000000|     100|0.01520972|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.35537614|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.70361276|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.57752259|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.04567487|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.99990241|   WEAK  
      rgb_lagged_sum|  19|   1000000|     100|0.59703607|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.01424569|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.01190246|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.28083614|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.85922233|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.74805305|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.33664323|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.68550123|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.71237718|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.47764816|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.36902623|  PASSED  
      rgb_lagged_sum|  30|   1000000|     100|0.70886921|  PASSED  
      rgb_lagged_sum|  31|   1000000|     100|0.86385367|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.93629132|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.16180294|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.54526159|  PASSED  
             dab_dct| 256|     50000|       1|0.01211310|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.28341243|  PASSED  
        dab_filltree|  32|  15000000|       1|0.40586913|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.99340648|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.94767580|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.43391232|  PASSED

Mein Hauptserver (auf dem auch WeizenSpr.eu läuft) wird mit einem "Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz" betrieben. Auch dessen Überprüfung liefert gute Ergebnisse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  5.53e+07  |3948260661|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.87942414|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.48126438|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.49454734|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.57071448|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.05867636|  PASSED  
        diehard_opso|   0|   2097152|     100|0.92742494|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.87263461|  PASSED  
         diehard_dna|   0|   2097152|     100|0.41023900|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.56140444|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.47686501|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.59549008|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.85268300|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.21177774|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.22008717|  PASSED  
        diehard_sums|   0|       100|     100|0.27919825|  PASSED  
        diehard_runs|   0|    100000|     100|0.28528603|  PASSED  
        diehard_runs|   0|    100000|     100|0.88804265|  PASSED  
       diehard_craps|   0|    200000|     100|0.50789926|  PASSED  
       diehard_craps|   0|    200000|     100|0.44794845|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.85094292|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.87826981|  PASSED  
         sts_monobit|   1|    100000|     100|0.34667211|  PASSED  
            sts_runs|   2|    100000|     100|0.87692980|  PASSED  
          sts_serial|   1|    100000|     100|0.92230630|  PASSED  
          sts_serial|   2|    100000|     100|0.42487308|  PASSED  
          sts_serial|   3|    100000|     100|0.47201211|  PASSED  
          sts_serial|   3|    100000|     100|0.45286777|  PASSED  
          sts_serial|   4|    100000|     100|0.99293625|  PASSED  
          sts_serial|   4|    100000|     100|0.95982278|  PASSED  
          sts_serial|   5|    100000|     100|0.72869396|  PASSED  
          sts_serial|   5|    100000|     100|0.15359933|  PASSED  
          sts_serial|   6|    100000|     100|0.29986703|  PASSED  
          sts_serial|   6|    100000|     100|0.90350707|  PASSED  
          sts_serial|   7|    100000|     100|0.82937553|  PASSED  
          sts_serial|   7|    100000|     100|0.69745997|  PASSED  
          sts_serial|   8|    100000|     100|0.76976576|  PASSED  
          sts_serial|   8|    100000|     100|0.94487729|  PASSED  
          sts_serial|   9|    100000|     100|0.21190616|  PASSED  
          sts_serial|   9|    100000|     100|0.95673394|  PASSED  
          sts_serial|  10|    100000|     100|0.28956816|  PASSED  
          sts_serial|  10|    100000|     100|0.59407297|  PASSED  
          sts_serial|  11|    100000|     100|0.97436422|  PASSED  
          sts_serial|  11|    100000|     100|0.68107472|  PASSED  
          sts_serial|  12|    100000|     100|0.40336698|  PASSED  
          sts_serial|  12|    100000|     100|0.80817356|  PASSED  
          sts_serial|  13|    100000|     100|0.89780894|  PASSED  
          sts_serial|  13|    100000|     100|0.97992817|  PASSED  
          sts_serial|  14|    100000|     100|0.56469700|  PASSED  
          sts_serial|  14|    100000|     100|0.75256118|  PASSED  
          sts_serial|  15|    100000|     100|0.04120757|  PASSED  
          sts_serial|  15|    100000|     100|0.21211072|  PASSED  
          sts_serial|  16|    100000|     100|0.38377842|  PASSED  
          sts_serial|  16|    100000|     100|0.44555996|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.81895044|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.64929431|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.65870845|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.56304051|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.75496902|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.06767649|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.30374549|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.65287829|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.77464639|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.25683681|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.65849822|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.50805413|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.02681610|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.22801930|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.27927346|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.43079185|  PASSED  
    rgb_permutations|   2|    100000|     100|0.94898090|  PASSED  
    rgb_permutations|   3|    100000|     100|0.11374383|  PASSED  
    rgb_permutations|   4|    100000|     100|0.72305706|  PASSED  
    rgb_permutations|   5|    100000|     100|0.20417740|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.93883915|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.38840055|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.62008896|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.99204256|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.52115721|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.22550225|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.40715772|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.58505397|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.42592254|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.34891085|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.67645788|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.92966912|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.95439791|  PASSED  
      rgb_lagged_sum|  13|   1000000|     100|0.39471972|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.72890013|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.22923887|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.09437301|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.03021647|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.06593268|  PASSED  
      rgb_lagged_sum|  19|   1000000|     100|0.73484274|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.97718590|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.83580287|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.68984098|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.34944142|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.76720893|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.99808427|   WEAK  
      rgb_lagged_sum|  26|   1000000|     100|0.20922699|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.18887164|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.45387763|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.31425341|  PASSED  
      rgb_lagged_sum|  30|   1000000|     100|0.72639892|  PASSED  
      rgb_lagged_sum|  31|   1000000|     100|0.69995471|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.84789350|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.62218468|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.37714207|  PASSED  
             dab_dct| 256|     50000|       1|0.81750713|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.30697178|  PASSED  
        dab_filltree|  32|  15000000|       1|0.70930339|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.87225976|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.78581557|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.00837857|  PASSED

Selbst auf meinen alten Mac Minis auf PowerPC-Basis ("PowerMac10,1 MacRISC3 Power Macintosh"), die bei mir Zuhause in einem Testcluster laufen, läuft haveged und liefert auch dort gute Ergebnisse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  3.14e+06  |4220874249|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.57621219|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.32030487|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.50211874|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.33856755|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.23514061|  PASSED  
        diehard_opso|   0|   2097152|     100|0.99635255|   WEAK  
        diehard_oqso|   0|   2097152|     100|0.07666882|  PASSED  
         diehard_dna|   0|   2097152|     100|0.28750274|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.31583844|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.53449657|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.79252967|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.67882318|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.31379788|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.28002382|  PASSED  
        diehard_sums|   0|       100|     100|0.18598691|  PASSED  
        diehard_runs|   0|    100000|     100|0.98976058|  PASSED  
        diehard_runs|   0|    100000|     100|0.94358199|  PASSED  
       diehard_craps|   0|    200000|     100|0.78532168|  PASSED  
       diehard_craps|   0|    200000|     100|0.71640173|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.93759598|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.88657019|  PASSED  
         sts_monobit|   1|    100000|     100|0.36848114|  PASSED  
            sts_runs|   2|    100000|     100|0.55771580|  PASSED  
          sts_serial|   1|    100000|     100|0.96608134|  PASSED  
          sts_serial|   2|    100000|     100|0.84005443|  PASSED  
          sts_serial|   3|    100000|     100|0.81443597|  PASSED  
          sts_serial|   3|    100000|     100|0.10575160|  PASSED  
          sts_serial|   4|    100000|     100|0.32914026|  PASSED  
          sts_serial|   4|    100000|     100|0.21924627|  PASSED  
          sts_serial|   5|    100000|     100|0.22875732|  PASSED  
          sts_serial|   5|    100000|     100|0.78557652|  PASSED  
          sts_serial|   6|    100000|     100|0.21487008|  PASSED  
          sts_serial|   6|    100000|     100|0.14747939|  PASSED  
          sts_serial|   7|    100000|     100|0.16517074|  PASSED  
          sts_serial|   7|    100000|     100|0.84180240|  PASSED  
          sts_serial|   8|    100000|     100|0.36482950|  PASSED  
          sts_serial|   8|    100000|     100|0.27419346|  PASSED  
          sts_serial|   9|    100000|     100|0.12233420|  PASSED  
          sts_serial|   9|    100000|     100|0.16885151|  PASSED  
          sts_serial|  10|    100000|     100|0.03902614|  PASSED  
          sts_serial|  10|    100000|     100|0.18952175|  PASSED  
          sts_serial|  11|    100000|     100|0.94410153|  PASSED  
          sts_serial|  11|    100000|     100|0.59201848|  PASSED  
          sts_serial|  12|    100000|     100|0.33965647|  PASSED  
          sts_serial|  12|    100000|     100|0.52757585|  PASSED  
          sts_serial|  13|    100000|     100|0.34009610|  PASSED  
          sts_serial|  13|    100000|     100|0.99834388|   WEAK  
          sts_serial|  14|    100000|     100|0.96198264|  PASSED  
          sts_serial|  14|    100000|     100|0.39290279|  PASSED  
          sts_serial|  15|    100000|     100|0.97548718|  PASSED  
          sts_serial|  15|    100000|     100|0.93903378|  PASSED  
          sts_serial|  16|    100000|     100|0.98534676|  PASSED  
          sts_serial|  16|    100000|     100|0.39565376|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.20773717|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.85032130|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.50838307|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.57233304|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.91002860|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.78087088|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.40799300|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.00745902|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.30916578|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.57590644|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.80634610|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.54261773|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.59111346|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.46887953|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.94865190|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.28414726|  PASSED  
    rgb_permutations|   2|    100000|     100|0.75820306|  PASSED  
    rgb_permutations|   3|    100000|     100|0.90669743|  PASSED  
    rgb_permutations|   4|    100000|     100|0.47793456|  PASSED  
    rgb_permutations|   5|    100000|     100|0.69969764|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.26143346|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.89175049|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.96527229|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.99757952|   WEAK  
      rgb_lagged_sum|   4|   1000000|     100|0.47083477|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.93046056|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.09962939|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.07011501|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.23763444|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.09943310|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.79942404|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.02056793|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.56717544|  PASSED  
      rgb_lagged_sum|  13|   1000000|     100|0.20265247|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.90095804|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.51364566|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.36926201|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.46713667|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.94256711|  PASSED  
      rgb_lagged_sum|  19|   1000000|     100|0.94338929|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.92997203|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.36046015|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.83868968|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.52879240|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.61314936|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.37027362|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.81581312|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.66953730|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.28398670|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.95750904|  PASSED  
      rgb_lagged_sum|  30|   1000000|     100|0.94730710|  PASSED  
      rgb_lagged_sum|  31|   1000000|     100|0.38254527|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.88603434|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.41777521|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.51678719|  PASSED  
             dab_dct| 256|     50000|       1|0.48530283|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.09009306|  PASSED  
        dab_filltree|  32|  15000000|       1|0.42145861|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.92140518|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.30032656|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.80367392|  PASSED

Gespannt war ich auf die Ergebnisse meiner vServer, da diese bei PolarSSL mbed SSL ja der Ursprung des Problems waren. Ich verwende einerseits ein System mit einem KVM-virtualisierten "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz". Dessen Ergebnisse sehen gut aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  3.91e+07  |2403861751|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.39303888|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.74496497|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.13162974|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.72631428|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.86273136|  PASSED  
        diehard_opso|   0|   2097152|     100|0.56491165|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.72849597|  PASSED  
         diehard_dna|   0|   2097152|     100|0.99485750|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.43930506|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.50458767|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.99584501|   WEAK  
    diehard_2dsphere|   2|      8000|     100|0.26711806|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.29934754|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.80469876|  PASSED  
        diehard_sums|   0|       100|     100|0.87202688|  PASSED  
        diehard_runs|   0|    100000|     100|0.48564911|  PASSED  
        diehard_runs|   0|    100000|     100|0.72922679|  PASSED  
       diehard_craps|   0|    200000|     100|0.33032863|  PASSED  
       diehard_craps|   0|    200000|     100|0.83274474|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.29574332|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.05451073|  PASSED  
         sts_monobit|   1|    100000|     100|0.77549456|  PASSED  
            sts_runs|   2|    100000|     100|0.04823761|  PASSED  
          sts_serial|   1|    100000|     100|0.64803972|  PASSED  
          sts_serial|   2|    100000|     100|0.82585541|  PASSED  
          sts_serial|   3|    100000|     100|0.30137477|  PASSED  
          sts_serial|   3|    100000|     100|0.87316871|  PASSED  
          sts_serial|   4|    100000|     100|0.62677898|  PASSED  
          sts_serial|   4|    100000|     100|0.59645336|  PASSED  
          sts_serial|   5|    100000|     100|0.35557699|  PASSED  
          sts_serial|   5|    100000|     100|0.11323982|  PASSED  
          sts_serial|   6|    100000|     100|0.21809822|  PASSED  
          sts_serial|   6|    100000|     100|0.19746310|  PASSED  
          sts_serial|   7|    100000|     100|0.97678137|  PASSED  
          sts_serial|   7|    100000|     100|0.96862353|  PASSED  
          sts_serial|   8|    100000|     100|0.27733624|  PASSED  
          sts_serial|   8|    100000|     100|0.47827497|  PASSED  
          sts_serial|   9|    100000|     100|0.26196595|  PASSED  
          sts_serial|   9|    100000|     100|0.20901634|  PASSED  
          sts_serial|  10|    100000|     100|0.69320465|  PASSED  
          sts_serial|  10|    100000|     100|0.50087708|  PASSED  
          sts_serial|  11|    100000|     100|0.87279703|  PASSED  
          sts_serial|  11|    100000|     100|0.43184814|  PASSED  
          sts_serial|  12|    100000|     100|0.74743591|  PASSED  
          sts_serial|  12|    100000|     100|0.92912813|  PASSED  
          sts_serial|  13|    100000|     100|0.76446984|  PASSED  
          sts_serial|  13|    100000|     100|0.41474394|  PASSED  
          sts_serial|  14|    100000|     100|0.43600274|  PASSED  
          sts_serial|  14|    100000|     100|0.34892825|  PASSED  
          sts_serial|  15|    100000|     100|0.39514554|  PASSED  
          sts_serial|  15|    100000|     100|0.91420886|  PASSED  
          sts_serial|  16|    100000|     100|0.12891027|  PASSED  
          sts_serial|  16|    100000|     100|0.25502730|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.47587315|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.88458605|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.93845118|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.47849575|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.94374456|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.86572499|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.36333630|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.86103915|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.85522176|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.80240762|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.26687750|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.16549648|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.14846931|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.19988545|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.80019487|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.95158568|  PASSED  
    rgb_permutations|   2|    100000|     100|0.78900739|  PASSED  
    rgb_permutations|   3|    100000|     100|0.92360523|  PASSED  
    rgb_permutations|   4|    100000|     100|0.06140726|  PASSED  
    rgb_permutations|   5|    100000|     100|0.70150773|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.23235455|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.52120656|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.22766934|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.35038622|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.26125845|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.90298763|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.61490761|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.60879059|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.95659464|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.74259826|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.16243170|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.23525439|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.06598475|  PASSED  
      rgb_lagged_sum|  13|   1000000|     100|0.37754865|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.83798493|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.68802937|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.75693641|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.38717555|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.98063976|  PASSED  
      rgb_lagged_sum|  19|   1000000|     100|0.63458041|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.50550447|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.58518588|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.67293855|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.36934247|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.24675910|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.83818181|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.07111015|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.50390287|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.07887294|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.75449287|  PASSED  
      rgb_lagged_sum|  30|   1000000|     100|0.99969858|   WEAK  
      rgb_lagged_sum|  31|   1000000|     100|0.62793868|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.44864440|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.25821702|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.65332597|  PASSED  
             dab_dct| 256|     50000|       1|0.51773051|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.99425590|  PASSED  
        dab_filltree|  32|  15000000|       1|0.62049359|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.74836623|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.83701400|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.80371447|  PASSED

Und auch beim zweiten System mit einem KVM-virtualisierten "Intel(R) Xeon(R) CPU E5-2620 0 @ 2.00GHz" gibt es laut dieharder keine Beanstandungen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.88e+07  |3966886010|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.86802201|  PASSED  
      diehard_operm5|   0|   1000000|     100|0.93857016|  PASSED  
  diehard_rank_32x32|   0|     40000|     100|0.21554659|  PASSED  
    diehard_rank_6x8|   0|    100000|     100|0.02393864|  PASSED  
   diehard_bitstream|   0|   2097152|     100|0.72146650|  PASSED  
        diehard_opso|   0|   2097152|     100|0.75580499|  PASSED  
        diehard_oqso|   0|   2097152|     100|0.12630607|  PASSED  
         diehard_dna|   0|   2097152|     100|0.08318236|  PASSED  
diehard_count_1s_str|   0|    256000|     100|0.83369544|  PASSED  
diehard_count_1s_byt|   0|    256000|     100|0.98448502|  PASSED  
 diehard_parking_lot|   0|     12000|     100|0.74074906|  PASSED  
    diehard_2dsphere|   2|      8000|     100|0.27217962|  PASSED  
    diehard_3dsphere|   3|      4000|     100|0.93449392|  PASSED  
     diehard_squeeze|   0|    100000|     100|0.79591941|  PASSED  
        diehard_sums|   0|       100|     100|0.08260342|  PASSED  
        diehard_runs|   0|    100000|     100|0.55360622|  PASSED  
        diehard_runs|   0|    100000|     100|0.10557804|  PASSED  
       diehard_craps|   0|    200000|     100|0.77589877|  PASSED  
       diehard_craps|   0|    200000|     100|0.85530453|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.98866347|  PASSED  
 marsaglia_tsang_gcd|   0|  10000000|     100|0.68766275|  PASSED  
         sts_monobit|   1|    100000|     100|0.61721117|  PASSED  
            sts_runs|   2|    100000|     100|0.93200830|  PASSED  
          sts_serial|   1|    100000|     100|0.74699081|  PASSED  
          sts_serial|   2|    100000|     100|0.00364348|   WEAK  
          sts_serial|   3|    100000|     100|0.09215616|  PASSED  
          sts_serial|   3|    100000|     100|0.78527182|  PASSED  
          sts_serial|   4|    100000|     100|0.12680579|  PASSED  
          sts_serial|   4|    100000|     100|0.61424014|  PASSED  
          sts_serial|   5|    100000|     100|0.16770237|  PASSED  
          sts_serial|   5|    100000|     100|0.42085097|  PASSED  
          sts_serial|   6|    100000|     100|0.75700309|  PASSED  
          sts_serial|   6|    100000|     100|0.63826119|  PASSED  
          sts_serial|   7|    100000|     100|0.59100282|  PASSED  
          sts_serial|   7|    100000|     100|0.78513054|  PASSED  
          sts_serial|   8|    100000|     100|0.69352480|  PASSED  
          sts_serial|   8|    100000|     100|0.49332202|  PASSED  
          sts_serial|   9|    100000|     100|0.68905397|  PASSED  
          sts_serial|   9|    100000|     100|0.61441861|  PASSED  
          sts_serial|  10|    100000|     100|0.85033554|  PASSED  
          sts_serial|  10|    100000|     100|0.82637215|  PASSED  
          sts_serial|  11|    100000|     100|0.87559146|  PASSED  
          sts_serial|  11|    100000|     100|0.81872729|  PASSED  
          sts_serial|  12|    100000|     100|0.24838052|  PASSED  
          sts_serial|  12|    100000|     100|0.99588877|   WEAK  
          sts_serial|  13|    100000|     100|0.93714484|  PASSED  
          sts_serial|  13|    100000|     100|0.76441555|  PASSED  
          sts_serial|  14|    100000|     100|0.88325579|  PASSED  
          sts_serial|  14|    100000|     100|0.78308466|  PASSED  
          sts_serial|  15|    100000|     100|0.70135646|  PASSED  
          sts_serial|  15|    100000|     100|0.92951300|  PASSED  
          sts_serial|  16|    100000|     100|0.33861480|  PASSED  
          sts_serial|  16|    100000|     100|0.51384470|  PASSED  
         rgb_bitdist|   1|    100000|     100|0.64691596|  PASSED  
         rgb_bitdist|   2|    100000|     100|0.36340761|  PASSED  
         rgb_bitdist|   3|    100000|     100|0.13662446|  PASSED  
         rgb_bitdist|   4|    100000|     100|0.90561258|  PASSED  
         rgb_bitdist|   5|    100000|     100|0.09774341|  PASSED  
         rgb_bitdist|   6|    100000|     100|0.59992552|  PASSED  
         rgb_bitdist|   7|    100000|     100|0.12886912|  PASSED  
         rgb_bitdist|   8|    100000|     100|0.93601521|  PASSED  
         rgb_bitdist|   9|    100000|     100|0.52751789|  PASSED  
         rgb_bitdist|  10|    100000|     100|0.31254677|  PASSED  
         rgb_bitdist|  11|    100000|     100|0.82136358|  PASSED  
         rgb_bitdist|  12|    100000|     100|0.92595382|  PASSED  
rgb_minimum_distance|   2|     10000|    1000|0.79518024|  PASSED  
rgb_minimum_distance|   3|     10000|    1000|0.51397031|  PASSED  
rgb_minimum_distance|   4|     10000|    1000|0.47960772|  PASSED  
rgb_minimum_distance|   5|     10000|    1000|0.85165830|  PASSED  
    rgb_permutations|   2|    100000|     100|0.50745829|  PASSED  
    rgb_permutations|   3|    100000|     100|0.03006811|  PASSED  
    rgb_permutations|   4|    100000|     100|0.59388689|  PASSED  
    rgb_permutations|   5|    100000|     100|0.23065839|  PASSED  
      rgb_lagged_sum|   0|   1000000|     100|0.67210966|  PASSED  
      rgb_lagged_sum|   1|   1000000|     100|0.33918884|  PASSED  
      rgb_lagged_sum|   2|   1000000|     100|0.75190558|  PASSED  
      rgb_lagged_sum|   3|   1000000|     100|0.74416904|  PASSED  
      rgb_lagged_sum|   4|   1000000|     100|0.70682671|  PASSED  
      rgb_lagged_sum|   5|   1000000|     100|0.49242189|  PASSED  
      rgb_lagged_sum|   6|   1000000|     100|0.84792761|  PASSED  
      rgb_lagged_sum|   7|   1000000|     100|0.89892157|  PASSED  
      rgb_lagged_sum|   8|   1000000|     100|0.38757664|  PASSED  
      rgb_lagged_sum|   9|   1000000|     100|0.87685081|  PASSED  
      rgb_lagged_sum|  10|   1000000|     100|0.87448998|  PASSED  
      rgb_lagged_sum|  11|   1000000|     100|0.94552468|  PASSED  
      rgb_lagged_sum|  12|   1000000|     100|0.69899097|  PASSED  
      rgb_lagged_sum|  13|   1000000|     100|0.61052074|  PASSED  
      rgb_lagged_sum|  14|   1000000|     100|0.40428246|  PASSED  
      rgb_lagged_sum|  15|   1000000|     100|0.41357249|  PASSED  
      rgb_lagged_sum|  16|   1000000|     100|0.50608073|  PASSED  
      rgb_lagged_sum|  17|   1000000|     100|0.73579529|  PASSED  
      rgb_lagged_sum|  18|   1000000|     100|0.88116866|  PASSED  
      rgb_lagged_sum|  19|   1000000|     100|0.01969011|  PASSED  
      rgb_lagged_sum|  20|   1000000|     100|0.93329549|  PASSED  
      rgb_lagged_sum|  21|   1000000|     100|0.06482253|  PASSED  
      rgb_lagged_sum|  22|   1000000|     100|0.67360224|  PASSED  
      rgb_lagged_sum|  23|   1000000|     100|0.11912063|  PASSED  
      rgb_lagged_sum|  24|   1000000|     100|0.62730850|  PASSED  
      rgb_lagged_sum|  25|   1000000|     100|0.92150416|  PASSED  
      rgb_lagged_sum|  26|   1000000|     100|0.88313859|  PASSED  
      rgb_lagged_sum|  27|   1000000|     100|0.17009240|  PASSED  
      rgb_lagged_sum|  28|   1000000|     100|0.52599929|  PASSED  
      rgb_lagged_sum|  29|   1000000|     100|0.99966442|   WEAK  
      rgb_lagged_sum|  30|   1000000|     100|0.66724337|  PASSED  
      rgb_lagged_sum|  31|   1000000|     100|0.29408784|  PASSED  
      rgb_lagged_sum|  32|   1000000|     100|0.67994300|  PASSED  
     rgb_kstest_test|   0|     10000|    1000|0.09623650|  PASSED  
     dab_bytedistrib|   0|  51200000|       1|0.97246947|  PASSED  
             dab_dct| 256|     50000|       1|0.22118329|  PASSED  
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.89757812|  PASSED  
        dab_filltree|  32|  15000000|       1|0.36526583|  PASSED  
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.89963029|  PASSED  
       dab_filltree2|   1|   5000000|       1|0.67162245|  PASSED  
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.21033599|  PASSED

Warum also auf diese zusätzliche Entropiequelle verzichten? Diese wird sowieso nicht direkt genutzt, sondern nach /dev/random eingeleitet, mit dessen restlichen Entropiequellen gemischt, durch einen CSPRNG (Cryptographically Secure PseudoRandom Number Generator) geleitet und erst dieser Output wird verwendet. Bis ein Problem mit dem eigentlichen Verfahren von haveged gefunden wird, werde ich dieses jedenfalls nun auf meinen Systemen einsetzen.

Zeitmessende Grüße, Kenny

P.S.: Dass der Entropiepool leerläuft, kann man über folgenden Befehl beobachten:

1
cat /proc/sys/kernel/random/entropy_avail
Seite 1 von 86123...Letzte »