SQLite mit der PowerShell nutzen

SQLite mit der PowerShell nutzen

 15.06.2016 -  Sebastian Pech -  ~4 Minuten

SQLite hat sich als kleine Bibliothek für Datei-basierte Datenbanken etabliert. Mit Hilfe der PowerShell und einem ebenso kleinen Modul sind Zugriffe auf die Datenbank einfach zu erledigen.

SQLite

SQLite ist eine Programmbibliothek, die ein relationales Datenbanksystem enthält. SQLite unterstützt einen Großteil der im SQL-92-Standard festgelegten SQL-Sprachbefehle. […] Die SQLite-Bibliothek lässt sich direkt in entsprechende Anwendungen integrieren, sodass keine weitere Server-Software benötigt wird. Dies ist der entscheidende Unterschied zu anderen Datenbanksystemen. Durch das Einbinden der Bibliothek wird die Anwendung um Datenbankfunktionen erweitert, ohne auf externe Softwarepakete angewiesen zu sein. SQLite hat einige Besonderheiten gegenüber anderen Datenbanken: Die Bibliothek ist nur wenige hundert Kilobyte groß. Eine SQLite-Datenbank besteht aus einer einzigen Datei, die alle Tabellen, Indizes, Views, Trigger usw. enthält. Dies vereinfacht den Austausch zwischen verschiedenen Systemen, sogar zwischen Systemen mit unterschiedlichen Byte-Reihenfolgen. Jede Spalte kann Daten beliebiger Typen enthalten, erst zur Laufzeit wird nötigenfalls konvertiert. (Quelle: Wikipedia )

Module

Für den Zugriff auf SQLite Datenbanken gibt es eine Reihe von Modulen. Einige Kapsel sogar das komplette SQL in PowerShell Funktionsaufrufe. Für diesen Artikel reicht das PSSQLite Modul vom GitHub User RamblingCookieMonster. Das Modul ermöglicht den Zugriff auf die Datenbank mittels ein oder zwei einfachen Funktionsaufrufen.

Um .SQLite, .SQLite3 oder .db Dateien zu öffnen hilft das Programm SQLite Browser .

Das Modul kann aus GitHub runtergeladen werden oder mittels git exportiert werden. Entweder wird der Unterordner „PSSQLite“ in ein eigenes Verzeichnis gelegt oder in einen der Standard Modulverzeichnisse der PowerShell installiert. Liegt die Datei im Standardpfad:

> $Env:PSModulePath
C:\Users\xxxxxx\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\windows\system32\WindowsPowerShell\v1.0\Modules\;C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\
> Import-Module PSSQLite

Andernfalls muss der gesamte Pfad angegeben werden:

> Import-Module "PFAD_ZUM_ORDNER\PSSQLite"

Die Hilfe des Moduls lässt sich über die bekannten Befehle ausgeben.

Get-Command -Module PSSQLite
Get-Help Invoke-SQLiteQuery -Full

SQL Kommandos ausführen

Ein wichtigstes Merkmal bei der Nutzung der Bibliotek ist das automatische Erstellen der SQLite Datei. Wurde die Datei noch nicht erstellt gibt es eine Warnung und eine leere Datenbank wird erzeugt.

$db = "PFAD_ZUM_ORDNER\db1.db" # oder .SQLite, .SQLite3
$query = "CREATE TABLE user (
  UserId INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  Firstname NVARCHAR(250) NOT NULL,
  Lastname NVARCHAR(250) NOT NULL,
  Birthdate DATE
)"

# SQLite erstellt die Datei automatisch
Invoke-SqliteQuery -Query $query -DataSource $db

# Daten einfügen
Invoke-SqliteQuery -Query "INSERT INTO user(Firstname, Lastname, Birthdate) VALUES ('Max', 'Müller', '2000-09-01');  -DataSource $db"

Verbindungen nutzen

Möchte man mehr als nur One-Shoot Befehle ausführen bietet sich das öffnen und schließen von Verbindungen an. Dazu benötigt es nur einen weiteren Befehl. Anstelle der DataSource kann dann bei den Querys die SQLiteConnection zum Einsatz kommen.

$db = "PFAD_ZUM_ORDNER\db1.db"
$conn = New-SQLiteConnection @Verbose -DataSource $db
$conn.ConnectionString
$conn.State

Invoke-SqliteQuery -SQLiteConnection $conn -Query "SELECT * FROM user"

$conn.Close()
$conn.State

SQL-Injection umgehen mittels Parametern

SQL-Injection bezeichnet das Ausnutzen einer Sicherheitslücke in Zusammenhang mit SQL-Datenbanken, die durch mangelnde Maskierung oder Überprüfung von Metazeichen in Benutzereingaben entsteht. Der Angreifer versucht dabei, über die Anwendung, die den Zugriff auf die Datenbank bereitstellt, eigene Datenbankbefehle einzuschleusen. Sein Ziel ist es, Daten auszuspähen, in seinem Sinne zu verändern, die Kontrolle über den Server zu erhalten oder einfach größtmöglichen Schaden anzurichten (Quelle: Wikipedia ) Wie sieht das aber in der Praxis aus? Nehmen wir an das ein Programm Daten vom Benutzer einließt.

$vorname = Read-Host "Vorname"
$nachname = Read-Host "Nachname"
$gebdat = Read-Host "Geburtsdatum (YYYY-MM-DD)"

Würden diese Daten nun direkt in das Query eingegeben werden kann der Benutzer jede Zeichenkette zu einem SQL Befehl machen.

# SEHR SCHLECHT!!!!!! SQL-Injection anfällig!!!!!!!!!
$query = "INSERT INTO user(Firstname, Lastname, Birthdate) VALUES ('$vorname', '$nachname', '$gebdat')"

Gibt der Benutzer als Geburtsdatum dann etwas ein wie: 2016-10-10′); DROP TABLE user; — Dann wird aus dem obigen Befehl:

INSERT INTO user(Firstname, Lastname, Birthdate) VALUES ('xxxx', 'xxxx', '2016-10-10'); DROP TABLE user; --')"

Damit erzeugt das Statement einen Datensatz und löscht direkt darauf die Tabelle. Dies ist ein sehr destruktives Beispiel. In einem weniger schädlichen Szenario können damit weitere Datensätze erzeugt werden. Der richtige Weg ist die Nutzung von Parametern. Die SQLite Bibliothek übernimmt dann die Aufgabe der korrekten Maskierung von schädlichen Eingaben.

$query = "INSERT INTO user(Firstname, Lastname, Birthdate) VALUES (@firstname, @lastname, @birthdate)"
Invoke-SqliteQuery -SQLiteConnection $Script:Connection -Query $query -SqlParameters @{
  firstname = $vorname
  lastname = $nachname
  birthdate = $gebdat
}