Kategorien

Suchen


Aktuelle Artikel

Archiv

MySQL

« Vorherige Beiträge Nächste Beiträge »

PHP: Unable to load dynamic library ‘/usr/lib/php5/extensions/mysql.so’

Freitag, 05.02.2010

Wenn im ErrorLog des Apache2 WebServers (“tail /var/log/apache2/error.log”) u.a. folgende Zeile zu finden ist, kann PHP die Extension (Erweiterung) nicht finden und laden:

PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib/php5/extensions/mysql.so' - /usr/lib/php5/extensions/mysql.so: cannot open shared object file: No such file or directory in Unknown on line 0

Häufig wird dann angefangen, wild an der Konfiguration zu ändern und basteln. Dabei wird meist das naheliegendste übersehen:

Gibt es das angegebene Verzeichnis überhaupt ?
Erst recht, wenn mehrere (oder gar viele) Extensions nicht geladen werden können.

Wenn dann der Befehl

dir -l /usr/lib/php5/extensions/

die folgende Fehlermeldung anzeigt, sollte alles klar sein:

dir: Zugriff auf /usr/lib/php5/extensions/ nicht möglich: Datei oder Verzeichnis nicht gefunden

Lösung

Den Pfad für die Extensions in der “php.ini” anpassen. Diese kann, falls der Pfad nicht bekannt ist, mithilfe des folgenden Befehls gefunden werden.

find / -name php.ini

Dieser Befehl zeigt Ihnen ggf. auch andere “php.ini” Dateien auf ihrem System an. Manchmal konfiguriert man ein einer “php.ini” und wundert sich, dass keine Änderung eintritt. Wenn man zufällig die falsche Datei in den Händen hat, dann kann man auch lange auf ein Ergebnis warten ;)

Häufig fällt dieses Problem nach einer (Neu)Installation erst auf, wenn die mySQL / mySQLi Unterstützung fehlt. Grund ist dann (meist), dass die mysql.so Extension in PHP nicht geladen werden kann.

mySQL: Doppelte IDs auflisten / Doppelte Einträge finden

Donnerstag, 12.11.2009

Um in mySQL doppelte Einträge (Feldinhalte) aufzulisten, hilft Ihnen das folgende SQL Statement:

SELECT id FROM muster m WHERE (
SELECT count(*) FROM muster WHERE id = m.id
) >1

In diesem Beispiel werden alle IDs aus der Tabelle “muster” aufgelistet, die doppelt vorhanden sind.

Wenn Sie Ihre eigene Tabelle eintragen, achten Sie bitte darauf, beide Namen anzupassen.

mySQL: Zeilen aus verbundenen Tabellen löschen

Samstag, 08.08.2009

Um Daten (Zeilen) aus Tabellen effektiv zu löschen, dürfen Sie die 1 MB Grenze (Standardwert der Systemvariablen max_allowed_packet) nicht überschreiten.
Bei komplexen DELETE Anweisungen ist das aber schnell der Fall.

Die Lösung ist dann nur die Zerlegeung der DELETE Statements in kleinere Protionen (notfalls Einzelanweidungen).
Am schnellsten läuft ein DELETE Befehl, wenn nur 100 bis 1000 related_column-Werte pro (indizierter) Anweisung anstehen.

Hat die “related_column” (Feld für die Verbindung der Tabellen) keinen Index, ist die Geschwindigkeit von der Anzahl der Argumente der IN-Klausel unabhängig.

mySQL: Alte MD5 Passwörter – OLD_PASSWORD()

Dienstag, 07.07.2009

In alten mySQL Versionen (vor V4.1) wurde für die Passwortverschlüsselung ein 16 Zeichen langer MD5 Hash genutzt (sh. auch unseren Arikel “Sicherheit: MD5 Hash decodieren / entschlüsseln (16 stelligen Hash)“).

Diese Technik war (und ist) unsicher und daher wurde ab Version 4.1 auf den 32 Zeichen langen MD5 Hash umgestiegen. Dieser gilt heute als Standard MD5 Hash und wird in allen gängigen Umgebungen und Systemen gleich berechnet.

Um nun bei Bedarf trotzdem noch den alten Hash erzeugen zu können (z.Bsp. müssen Sie verschlüsselte Passwörter vergleichen), stellen wir Ihnen einige Tools zur Verfügung:

Sollten Sie Fragen oder konstruktive Kritik haben, schreiben Sie uns gerne eine E-Mail.

Online Hash Berechnung

Bitte geben Sie das Passwort in das folgende Feld ein und klicken Sie auf “Hash erzeugen”:

Ihnen wird der Hash unterhalb dieser Zeile angezeigt:

Keine Eingabe.

C Programm (Linux / UNIX)

Nutzen Sie folgenden Download-Link für die compilierte Version. Sollten Sicherheitsbeschränkungen den Download der Software verhindern, versuchen Sie das ZIP oder TAR.GZ Archiv zu laden:
[download id="2"]
[download id="3"]
[download id="4"]

C# Programm für MS-Windows

Diese MS-Windows Version folgt in den nächsten Tagen – und wie immer natürlich kostenlos.

Sicherheit: MD5 Hash decodieren / entschlüsseln (16 stelligen Hash)

Dienstag, 07.07.2009

Der folgende C Source kann ggf. Ihnen helfen, vergessene MD5 Passwörter (nur 16-stelligen Hash) wieder zu erhalten. Dabei werden nur Passwörter mit bis zu 8 Zeichen berechnet. Außerdem können nicht alle Sonderzeichen berücksichtigt werden. Von Decodieren bzw. Entschlüsseln kann aufgrund der angewendeten Methoden nicht geredet werden. Das genannte MD5 Verfahren hat mathematische Lücken und wurde daher bereits ab mySQL Version 4.1 durch den stärken und (bislang sicheren) MD5/32 Hash abgelöst.

Hinweis:
Den Sourcecode nutzen Sie vollständig auf eigene Gefahr und Verantwortung. Bitte prüfen Sie vorher, ob Sie berechtigt sind, den MD5 Hash zu berechnen. Sollten Sie Zweifel haben, nutzen Sie die Methoden nicht !

Um Ihnen nicht den vollständigen Source zu liefern (und jedem Hobby-Passwort-Analysten die Berechnung zu erlauben) haben wir die wichtigen Bitverschiebungen im Source durch Smileys ersetzt. Für erfahrene Entwickler wird das Herausfinden und Ersetzen der entsprechenden Sourcecode-Positionen kein Problem darstellen. Zusätzlich bleibt der Source äußerst karg kommentiert.

// Tools zur Decodierung von 16stelligen MD5 Hashes
// Verwendet von mySQL OLD_PASSWORT() etc.

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

#define xor ^

void search3_new( );
void search4_new( );
void search5_new( );
void search6_new( );
void search7_new( );
void search8_new( );
void get_old_nr2( );
void init_password( );
void found_footprint( );

int search_extension(unsigned long nrd, unsigned long nr2d, unsigned long add1d);
char footprint_str[32];
int len3=0, len4=0, len5=0, len6=0, len7=0, len8=0, len9=0, len10=0, lenall=1;

unsigned char char1, char2, char3, char4, char5, char6, char7, char8, char9, char10;
unsigned char extension_char1, extension_char2, extension_char3;
unsigned long nr2_g2_expected1_genuine;
unsigned long nr2_g2_expected2_genuine;
unsigned long nr2_g3;
unsigned long nr2_g3plus;
unsigned long nr2_expected;
unsigned long footprint1;
unsigned long footprint2;

int hexdigit_value(char c) {
  if (c >= '0' && c <= '9' ) return c - '0';
  if (c >= 'a' && c <= 'f' ) return c - 'a' + 10;
  if (c >= 'A' && c <= 'F' ) return c - 'A' + 10;  

  printf("Fehler: '%c' ist kein Hex-Wert\r\n", c);
  exit(0);
  return 0;
}

int main(int argc, char **argv) {
  int p;

  if (argc!=2 || (argc >= 2 && strcmp(argv[1], "--help") == 0)) {
    printf("Syntax  : %s [MD5 Hash]\r\n", argv[0] );
    printf("Beispiel: %s 565491d704013245 (liefert das Passwort \"123456\")\r\n", argv[0]);
    exit(0);
  }

  char * args = argv[1];

  if (strlen(args) != 16 ) {
        printf("Fehler: '%s' ist kein MD5 Hash (16 Hex-Zeichen)\r\n", args);
        exit(1);
  }

   // Hash holen
  strcpy(footprint_str, args);
  unsigned long f1=0, f2=0;

  int q;
  for (q = 0; q < 8; q++) {
    f1 = (f1 << 4) + hexdigit_value(args[q]);
    f2 = (f2 << 4) + hexdigit_value(args[q+8]);
  }

  footprint1 = f1;
  footprint2 = f2;

  // Initialisierungen
  get_old_nr2();
  init_password();

  // Suche
  search3_new();
  search4_new();
  search5_new();
  search6_new();
  search7_new();
  search8_new();
  printf("Das Passwort hat wohl mehr als 8 Zeichen ...\r\n");

  return(0);
}

void init_password(  ) {
  char1  = 0;
  char2  = 0;
  char3  = 0;
  char4  = 0;
  char5  = 0;
  char6  = 0;
  char7  = 0;
  char8  = 0;
  char9  = 0;
  char10 = 0;
}

void get_old_nr2() {
  unsigned long old_nr2_value;
  int old_nr2[8] ;
  int new_nr2[8] ;
  int new_nr[8];
  int carry[8] ;
  int p;

  for (p = 0; p < 8; p++) {
    old_nr2[p] = 0;
    new_nr2[p] = 0;
    new_nr[p]  = 0;
    carry[p]   = 0;
  }

  new_nr[1] = footprint1 & 255;
  new_nr[2] = (footprint1 >>  8 ) & 255;
  new_nr[3] = (footprint1 >> 16 ) & 255;
  new_nr[4] = (footprint1 >> 24 ) & 255;

  new_nr2[1] = footprint2 & 255;
  new_nr2[2] = (footprint2 >>  8 ) & 255;
  new_nr2[3] = (footprint2 >> 16 ) & 255;
  new_nr2[4] = (footprint2 >> 24 ) & 255;

  for (p=1; p<=4; p++) {
    unsigned long tmp;
    tmp = old_nr2[p-1] ^ new_nr[p];
    old_nr2[p] = new_nr2[p] - carry[p] - tmp;

    if (old_nr2[p] < 0 ) {
      carry[p+1]  = 1;
      old_nr2[p] += 256;
    }
  }

  old_nr2_value = (old_nr2[1] | (old_nr2[2] << 8) |
                  (old_nr2[3] << 16) | (old_nr2[4] << 24) ) & 0x7FFFFFFF;

  nr2_g2_expected1_genuine = old_nr2_value & 0x7FF00000;
  nr2_g2_expected2_genuine = (old_nr2_value - 0x100000) & 0x7FF00000;
  nr2_expected = old_nr2_value;
  nr2_g3 = nr2_g2_expected1_genuine & 0x70000000;
  nr2_g3plus = (nr2_g2_expected1_genuine + 0x10000000) & 0x70000000;
}

void found_footprint() {
  char password[256], *ps;
  int p;
  ps = password;

  if (char1) *ps++ = char1;
  if (char2) *ps++ = char2;
  if (char3) *ps++ = char3;
  if (char4) *ps++ = char4;
  if (char5) *ps++ = char5;
  if (char6) *ps++ = char6;
  if (char7) *ps++ = char7;

  *ps++ = extension_char1;
  *ps++ = extension_char2;
  *ps++ = extension_char3;
  *ps   = 0;

  // Gefundenes Passwort anzeigen
  printf("%s = %s\r\n", footprint_str, password);
  exit(0);
}

void search3_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;
  if (search_extension(nr, nr2, add))
    return;
}

void search4_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;

  for (char1 = 33; char1 < 127; char1++) {
    nr  = 1345345333L;
    add = 7;
    nr2 = 0x12345671L;
    nr  ^= (((nr & 63) + add) * (unsigned long)char1) + (nr << 8);
    nr2 += (nr2 << 8) ^ nr;
    add += char1;

    if (search_extension(nr, nr2, add))
        return;
  }
}

void search5_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;

  for (char1 = 33; char1 < 127; char1++)
    for (char2 = 33; char2 < 127; char2++) {
      nr  = 1345345333L;
      add = 7;
      nr2 = 0x12345671L;

      nr  ^= (((nr & 63) + add) * (unsigned long)char1) + (nr << 8);
      nr2 += (nr2 << 8) ^ nr;
      add += char1;

      nr  ^= (((nr & 63) + add) * (unsigned long)char2) + (nr << 8);
      nr2 += (nr2 << 8) ^ nr;
      add += char2;

      if (search_extension(nr, nr2, add))
          return;
  }
}

void search6_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;

  for (char1 = 33; char1 < 127; char1++)
    for (char2 = 33; char2 < 127; char2++)
        for (char3 = 33; char3 < 127; char3++) {
          nr  = 1345345333L;
          add = 7;
          nr2 = 0x12345671L;

          nr  ^= (((nr & 63) + add) * (unsigned long)char1) + (nr << 8);
          nr2 += (nr2 << 8) ^ nr;
          add += char1;

          nr  ^= (((nr & 63) + add) * (unsigned long)char2) + (nr << 8);
          nr2 += (nr2 << 8) ^ nr;
          add += char2;

          nr  ^= (((nr & 63) + add) * (unsigned long)char3) + (nr << 8);
          nr2 += (nr2 << 8) ^ nr;
          add += char3;

          if (search_extension(nr, nr2, add)) return;
  }
}

void search7_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;

  for (char1 = 33; char1 < 127; char1++)
    for (char2 = 33; char2 < 127; char2++)
        for (char3 = 33; char3 < 127; char3++)
          for (char4 = 33; char4 < 127; char4++) {
               nr  = 1345345333L;
          add = 7;
          nr2 = 0x12345671L;

              nr  ^= (((nr & 63) + add) * (unsigned long)char1) + (nr << 8);
              nr2 += (nr2 << 8) ^ nr;
              add += char1;

              nr  ^= (((nr & 63) + add) * (unsigned long)char2) + (nr << 8);
              nr2 += (nr2 << 8) ^ nr;
              add += char2;

              nr  ^= (((nr & 63) + add) * (unsigned long)char3) + (nr << 8);
              nr2 += (nr2 << 8) ^ nr;
              add += char3;

              nr  ^= (((nr & 63) + add) * (unsigned long)char4) + (nr << 8);
              nr2 += (nr2 << 8) ^ nr;
              add += char4;

              if (search_extension(nr, nr2, add)) return;
  }
}

void search8_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;

  for (char1 = 33; char1 < 127; char1++)
    for (char2 = 33; char2 < 127; char2++)
        for (char3 = 33; char3 < 127; char3++)
          for (char4 = 33; char4 < 127; char4++)
              for (char5 = 33; char5 < 127; char5++) {
                nr  = 1345345333L;
                add = 7;
                nr2 = 0x12345671L;

                nr  ^= (((nr & 63) + add) * (unsigned long)char1) + (nr << 8);
                nr2 += (nr2 << 8) ^ nr;
                add += char1;

                nr  ^= (((nr & 63) + add) * (unsigned long)char2) + (nr << 8);
                nr2 += (nr2 << 8) ^ nr;
                add += char2;

                nr  ^= (((nr & 63) + add) * (unsigned long)char3) + (nr << 8);
                nr2 += (nr2 << 8) ^ nr;
                add += char3;

                nr  ^= (((nr & 63) + add) * (unsigned long)char4) + (nr << 8);
                nr2 += (nr2 << 8) ^ nr;
                add += char4;

                nr  ^= (((nr & 63) + add) * (unsigned long)char5) + (nr << 8);
                nr2 += (nr2 << 8) ^ nr;
                add += char5;

                if (search_extension(nr, nr2, add)) return;
  }
}

void search9_new() {
  unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L;

  for (char1 = 33; char1 < 127; char1++)
    for (char2 = 33; char2 < 127; char2++)
        for (char3 = 33; char3 < 127; char3++)
          for (char4 = 33; char4 < 127; char4++)
              for (char5 = 33; char5 < 127; char5++)
                for (char6 = 33; char6 < 127; char6++) {
                    nr  = 1345345333L;
                    add = 7;
                    nr2 = 0x12345671L;

                    nr  ^= (((nr & 63) + add) * (unsigned long)char1) + (nr << 8);
                    nr2 += (nr2 << 8) ^ nr;
                    add += char1;

                    nr  ^= (((nr & 63) + add) * (unsigned long)char2) + (nr << 8);
                    nr2 += (nr2 << 8) ^ nr;
                    add += char2;

                    nr  ^= (((nr & 63) + add) * (unsigned long)char3) + (nr << 8);
                    nr2 += (nr2 << 8) ^ nr;
                    add += char3; 

                    nr  ^= (((nr & 63) + add) * (unsigned long)char4) + (nr << 8);
                    nr2 += (nr2 << 8) ^ nr;
                    add += char4;

                    nr  ^= (((nr & 63) + add) * (unsigned long)char5) + (nr << 8);
                    nr2 += (nr2 << 8) ^ nr;
                    add += char5;

                    nr  ^= (((nr & 63) + add) * (unsigned long)char6) + (nr << 8);
                    nr2 += (nr2 << 8) ^ nr;
                    add += char6;

                    if (search_extension(nr, nr2, add)) return;
  }
}

int search_extension(unsigned long nrd, unsigned long nr2d, unsigned long add1d) {
  unsigned long nre, nrf, nrg;
  unsigned long nr2e, nr2f, nr2g;
  unsigned long add1e, add1f, add1g;
  unsigned long constant1e, constant3e, variable1e;
  unsigned long constant1f, constant3f, variable1f;
  unsigned long constant1g, constant3g, variable1g;
  unsigned long nrdisc1, nrdisc2, nr2disc1, nr2disc2;
  unsigned long nr12;
  unsigned long delta1, delta2, delta3, delta4;
  unsigned long dividende1 , dividende2;

  constant1e = (nrd & 63) + add1d;
  constant3e = nr2d << 8;
  variable1e = (constant1e << 5) + (nrd << 8);

  nrdisc1  = nrd xor variable1e;
  nrdisc2  = nrdisc1 + 0x100000;
  nr2disc1 = nr2d + (constant3e xor nrdisc1);
  nr2disc2 = nr2d + (constant3e xor nrdisc2);
  nr12   = nrdisc1 << 8;

  delta1 = nrdisc1 xor (nr2disc1 << 8);
  delta2 = ((delta1 xor (nr12 + 0x10000000)) + nr2disc1) & 0x70000000;
  delta1 = ((delta1 xor nr12) + nr2disc1) & 0x70000000;

  nr12   = nrdisc2 << 8;
  delta3 = nrdisc2 xor (nr2disc2 << 8);
  delta4 = ((delta3 xor (nr12 + 0x10000000)) + nr2disc2) & 0x70000000;
  delta3 = ((delta3 xor nr12) + nr2disc2) & 0x70000000;

  if (delta1 == nr2_g3 || delta2 == nr2_g3 || delta3 == nr2_g3 || delta4 == nr2_g3 ||
      delta1 == nr2_g3plus || delta2 == nr2_g3plus || delta3 == nr2_g3plus ||
      delta4 == nr2_g3plus)

    for (extension_char1 = 33; extension_char1 <= 126; extension_char1++) {
      variable1e = variable1e + constant1e;
      nre = nrd xor variable1e;
      nr2e = nr2d + (constant3e xor nre);

      nr12   = nre << 8;
      delta1 = nre xor (nr2e << 8);
      delta2 = ((delta1 xor (nr12 + 0x100000)) + nr2e) & 0x7FF00000;
      delta1 = ((delta1 xor nr12) + nr2e) & 0x7FF00000;

      if (delta1 == nr2_g2_expected1_genuine || delta1==nr2_g2_expected2_genuine ||
          delta2 == nr2_g2_expected1_genuine || delta2==nr2_g2_expected2_genuine ) {

      add1e = add1d + extension_char1;

      constant1f = (nre & 63) + add1e;
      constant3f = nr2e << 8;
      variable1f = (constant1f << 5 ) + (nre << 8);

      for (extension_char2 = 33; extension_char2 <= 126; extension_char2++) {
        variable1f = variable1f + constant1f;
        nrf = nre xor variable1f;
        nr2f = nr2e + (constant3f xor nrf);            

        if ((nr2f & 0x7FFFFFFF) == nr2_expected) {
          add1f      = add1e + extension_char2;
          constant1g = (nrf & 63) + add1f;
          constant3g = nr2f << 8;
          variable1g = (constant1g << 5 ) + (nrf << 8);

          for (extension_char3 = 33; extension_char3 <= 126; extension_char3++) {
            variable1g = variable1g + constant1g;
            nrg = nrf xor variable1g;
            nr2g = nr2f + (constant3g xor nrg);

            if ((nrg & 0x7FFFFFFF) == footprint1 && (nr2g & 0x7FFFFFFF) == footprint2) {
              found_footprint();
              return(1);
            }
          }
        }
      }
    }
  }

  return(0);
}

mySQL: Alten MD5 Hash in C# berechnen (16 stellig)

Donnerstag, 25.06.2009

Die mySQL Versionen vor V4.1 nutzen einen veralteten MD5 Hash-Algorithmus. Dieser lieferte nur einen max. 16 stelligen Hashwert und ist weiterhin unsicher und teilweise decodierbar. Zwar gilt für MD5 aufgrund seines Algorithmusses grundsätzlich, dass diese Hashwerte nicht “decodiert” werden können – für den alten MD5/16 Code gilt dies’ jedoch nicht eingeschränkt.

Aufgrund des häufigen Anfragen für eine einfache Berechnung dieses MD5/16 Hash haben wir Ihnen den C# Sourcecode zur Verfügung gestellt. Diese liefert Ihnen für ein Passwort (= Parameter) den MD5/16 Hash:

namespace ConsoleApplication
{
    class Program
    {
        static string mysql_old_password(string sPassword)
        {
            UInt32[] result = new UInt32[2];
            bool bDebug = false;
            UInt32 nr = (UInt32)1345345333, add = (UInt32)7, nr2 = (UInt32)0x12345671;
            UInt32 tmp;

            char [] password = sPassword.ToCharArray();
            int i;

            for (i = 0; i < sPassword.Length; i++)
            {
                if (password[i] == ' ' || password[i] == '\t')
                    continue;

                tmp = (UInt32)password[i];
                nr ^= (((nr & 63) + add) * tmp) + (nr << 8);
                nr2 += (nr2 << 8 ) ^ nr;
                add += tmp;
            }

            result[0] = nr & (((UInt32)1 << 31) - (UInt32)1);
            UInt32 val = (((UInt32)1 << 31) - (UInt32)1);
            result[1] = nr2 & val;
            string hash = String.Format("{0:X}{1:X}", result[0], result[1]);
            return hash.ToLower();
        }

        static void Main(string[] args)
        {
            string hash = mysql_old_password("Hier Ihr Passwort");
            Console.WriteLine(hash);
       }
    }
}

Das häufige Problem sind alte mySQL Datenbanken, die Identifikationen enthalten und heute nicht mehr einfach ohne mySQL geprüft werden können.

Den alten MD5/16 Hash erhalten Sie auch weiterhin innerhalb von mySQL durch den Befehl "OLD_PASSWORD()". Dieser Quellcode soll Ihnen nur dann helfen, wenn Sie alte Daten (z.Bsp. aus Sicherungen) prüfen müssen.

mySQL: Schutz vor Angriffen in Datenbankabfragen (SQL Injection)

Freitag, 05.06.2009

Normale SQL Abfragen mit direkt eingebundenen Parametern ohne zusätzliche Schutzfunktionen kann sehr böse Folgen haben. Meist merken Sie davon nichts – Ihre Daten sind jedoch in höchster Gefahr.

Szenario #1: Ein einfacher Angriff

Nehmen wir eine (leider) normale Datenbankabfrage in PHP:

$query = "SELECT * FROM users
WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";

Nicht immer müssen die “richtigen” Parameter durch Ihre Oberfläche übergeben werden. Durch einfache Manipulation der Parameter (über gesonderte Abfragen) können beliebige Daten mit POST übergeben werden. Gehen wir von folgenden Parametern aus:

$_POST['username'] = "max";
$_POST['password'] = "' OR ''='";

Dadurch würde das SQL Statement so aussehen:

SELECT * FROM users WHERE user='max' AND password='' OR ''=''

Szenario #2: Auflisten von Benutzernamen & Passwörtern

Ebenfalls leicht möglich. Dafür wird eine Datenbankabfrage (SELECT Statement) einfach erweitert:

$query = "SELECT id, name, inserted, size
FROM products
WHERE size = '$size'
ORDER BY $order LIMIT $limit, $offset;";

Nun wird z.Bsp. der Parameter “size” vom Angreifer modifiziert:

'
union select '1', concat(uname || '-' || passwd) as name, '1971-01-01', '0' from usertable;
--

Dadurch wird folgende SQL Statement an die Datenbank übergeben:

SELECT id, name, inserted, size
FROM products
WHERE size = ''
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--' ORDER BY $order LIMIT $limit, $offset;

Szenario #3: Zurücksetzen / Ändern eines Passwortes

Das SQL Statement wird wie folgt zusammengebaut:

$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";

Diese kleine Erweiterung des Parameters “uid” reicht aus:

$uid == ' or uid like'%admin%'; --

Dadurch erhält Ihre Datenbank diesen Updatebefehl:

$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";

Szenario #4: Zugriff auf das Betriebssystem Ihre Datenbankservers

Ihre Abfrage:

$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";

Wenn jetzt der Parameter “name” entsprechend verändert wird, erhalten Sie folgendes SQL Statement:

SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD'--";

Dadurch würde (sofern Sie als entsprechend berechtigter Benutzer verbunden sind) ein neuer Benutzer “test” angelegt werden … und dieser kann dann natürlich frei auf dem Datenbankserver arbeiten.

Schutz Ihrer Daten & Datenbank

  1. Verbinden Sie sich nur als Benutzer mit den benötigten Rechten zur Datenbank.
    Niemals als Administrator (sa / sysdba / sys / …)

  2. Prüfen Sie Parameter vor der Benutzung auf Plausibilität.
    Z.Bsp. bei nummerischen Werten durch die Funktion “is_numeric()”.

  3. Escapen Sie jeden anderen Parameter, welchen Sie direkt an die Datenbank weitergeben.
    Nutzen Sie dafür Funktionen wie “mysql_real_escape_string()”, “sqlite_escape_string()”, usw.

  4. Geben Sie keine Datenbank internen Informationen heraus (Schema, Views, Spezifikationen, etc.)
    Diese Infos können leicht für Angriffe genutzt werden und erleichtern die gezielte Manipulation Ihrer Daten.

Beispiel für eine bessere Abfrage:

$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));

mySQL: 4 GB Grenze umgehen

Donnerstag, 04.06.2009

Wenn Sie eine mySQL Tabelle “überfüllen” möchten, erhalten Sie die Fehlermeldung “The table is full”.

Meist haben Sie dann die 4 GB Grenze von mySQL erreicht. Dieses Problem tritt in Verbindung mit Tabellen vom Typ “myISAM” auf. Um dieses Hürde zu überspringen und mahr Daten speichern zu können, können Sie den Grenzwert mit einem “ALTER TABLE” Befehl übersteuern. Bitte beachten Sie, dass dieser Befehl einige Zeit in Anspruch nimmt !

Beispiel:

In diesem Beispiel heißt die Datenbank “wetter”:

Die aktuellen Grenze erhalten Sie durch folgenden Befehl:

mysql> show table status like 'wetter'
*************************** 1. row ***************************
Name: wetter
Type: MyISAM
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 0
Max_data_length: 4294967295
Index_length: 1024
Data_free: 0
Auto_increment: NULL
Create_time: 2003-03-03 00:43:43
Update_time: 2003-03-03 00:43:43
Check_time: 2003-06-14 15:11:21
Create_options:
Comment:
1 row in set (0.00 sec)

Hier finden Sie die Info: Max_data_length = 4 GB.

Setzen Sie das Limit neu mit diesem Befehl:

mysql> alter table wetter max_rows=200000000000 avg_row_length=50;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

Und prüfen Sie die Grenze wieder:

mysql> show table status like 'wetter'
*************************** 1. row ***************************
Name: wetter
Type: MyISAM
Row_format: Dynamic
Rows: 0
Avg_row_length: 0
Data_length: 0
Max_data_length: 1099511627775
Index_length: 1024
Data_free: 0
Auto_increment: NULL
Create_time: 2003-06-17 13:12:49
Update_time: 2003-06-17 13:12:49
Check_time: NULL
Create_options: max_rows=4294967295 avg_row_length=50
Comment:
1 row in set (0.00 sec)

Fertig. Sie können nun mehr Daten in Ihrer mySQL Datenbank speichern.

mySQL: Sortierung nach zufälligen Werten

Dienstag, 30.12.2008

Wenn Sie bei einer mySQL Abfrage (Query) eine Spalte mit zufälligen Werten anfügen möchten, dann nutzen Sie diesen Befehl:

SELECT ID, Name, RAND() FROM Test

Wenn Sie nach dieser Spalte sortieren möchten, dann hilft Ihnen ein einfaches “Order by” mit einem entsprechenden Spaltennamen leider nicht weiter.
Sie müssen dann ein weiteres Feld der Abfrage in die Berechnung einbeziehen. Dann geht’s:

SELECT ID, Name, 0*ID+RAND() AS sort FROM Test ORDER BY sort

Entwicklungsumgebung mit cakePHP, mySQL & Eclipse

Sonntag, 21.12.2008

Benötigte Software (in Klammern die für diese Anleitung genutzte Version)

Installation(en)

Sofern ich keine Angabe zu einem Bildschirm oder Schritt einer Software-Installation gemacht habe, übernehmen Sie einfach die vorgegebenen / angezeigten Einstellungen.


Ihre cakePHP Installation ist jetzt vollständig einsetzbar. Die Installation und Konfiguration von Eclipse bringt Ihnen jedoch einen vielseitigen und optimalen Editor für Ihre neuen (php) Webseiten. Die Codevervollständigung, PHP Syntaxprüfung und weitere Features unterstützen Sie bei der Entwicklung Ihrer Internetseiten.

Bei dieser Anleitung habe ich die Eclipse Classic Version gewählt. Je nach Wunsch können Sie aber auch andere (auf der Eclipse Download Seite angezeigte) Versionen nutzen.


Eclipse ist jetzt bereits voll einsetzbar. Damit Ihnen die Arbeit mit PHP aber leichter fällt und alle gewünschten Zusatzfunktionen zur Verfügung stehen, muss die PHP Erweiterung installiert werden:

Alle Programme und Erweiterungen sind nun fertig installiert. Sie können mit der Arbeit an Ihren Webseiten beginnen:

Fertig.

« Vorheriger Beitrag Nächster Beitrag »