Rechteverwaltung für Microsoft SQL Server - dFPUG

Werbung
Rechteverwaltung für Microsoft SQL Server
Armin Kast
Rechteverwaltung im SQL Server 7 / SQL Server 2000 in der Praxis
Rechte auf DB und Tabellen
Entwickler / Support wird kontaktiert und
der Fehler beschrieben.......
Damit ein Anwender mittels Clientsoftware
auf einen SQL Server 7 zugreifen kann,
benötigt dieser Rechte auf die Datenbank
und die darin enthaltenen Tabellen. Diese
Rechte können in unterschiedlichster Art
vergeben werden. Entweder man verwendet
die visuellen Werkzeuge des SQL Servers 7
wie z.B. den Enterprise Manager, oder man
schreibt ein Script mit welchem dann die
darin verankerten Rechte zum SQL Server 7
übertragen werden. Wie auch immer die
Rechte auch auf den SQL Server 7
gekommen sind, vielfach möchte man diese
auch wieder auslesen und prüfen ob ein
Nutzer auch wirklich die gültigen Rechte
besitzt. Stellen wir uns folgendes Szenario
vor:
So oder ähnlich kann es sehr schnell gehen
wenn
man
nicht
geeignete
Schutzmechanismen,
oder
gar
eine
komplette
Nutzerverwaltung
im
Administrationsteil
einer
Applikation
implementiert.
Wie kann man nun die Rechte aus dem SQL
Server herauslesen und prüfen ob die
geeigneten Rechte vorhanden sind. Zum
einen durch eine kleinen Test in welchem
man versucht einen Dummydatensatz, den
man z.B. in einer Tabelle platziert hat, zu
schreiben.
SQLEXEC(hnd,“UPDATE xyz SET testfeld = 1 WHERE NR=-1 “)
Das programmierte Chaos
Ein Entwickler hat seine fertige Applikation
beim Kunden installiert und mit dem SQL
Server-Administrator des Kunden die
Datenbank mit den zugehörigen Tabellen,
Constraints und Trigger eingerichtet. Die
Rechte wurden anschließend mit einen
Script, für den vom Kunden definierten
Anwenderkreis, auf dem SQL Server
eingetragen. Der Administrator erhält durch
Einweisung Kenntnis über die Pflege und
Neueinrichtung von weiteren Benutzern.
Ein paar Tage später soll der Administrator
einen weitern Benutzer einrichten. Hierbei
unterläuft ihm ein Fehler und er setzt
Schreibrechte ( INSERT / UPDATE /
DELETE ) von Anwendern auf nur
Leserechte ( SELECT ) zurück. Die
Applikation bricht beim aktualisieren von
Daten mit einer Fehlermeldung ab. Der
03-09 Rechteverwaltung für Ms SQL Server
Ein Lösungsansatz
Liefert SQLEXEC() ein positives Ergebnis
so konnte auf die Tabelle geschrieben
werden. Dies ist aber nicht der Weisheit
letzter Schluss, da auch der Testdatensatz
gelöscht werden könnte. Auch der Versuch
mittels
SQLEXEC(hnd,“INSERT
VALUE(„Test“,1,2,3)“)
INTO
xyz
ist keine gute Variante da dieser Satz auch
anschließend wieder gelöscht werden muss.
Bricht die Applikation an dieser Stelle ab,
steht der Datensatz in der Tabelle.
Der richtige Weg...
Also müssen wird auf die Systemobjekte des
SQL Servers zurückgreifen und die dort
gespeicherten Rechte auslesen. Die Rechte
auf die Tabellen eines Anwenders stehen in
FoxX-Professional
Seite 1
Systemtabellen des SQL Servers. In der
unten stehenden Grafik ist die Zuordnung
der Systemtabellen, welche sich in jeder
Datenbank befinden, abgebildet. Die
Vorgehensweise ist folgende. Zuerst müssen
wir wissen welcher Anwender sich am
System angemeldet hat. Dies erfahren wir
über die SUSER_SID()- bzw. über die
Über die SID ermitteln wir die UID, welche
in der Systemtabelle SYSUSERS steht. Im
weiteren verlauf können wir dann die
Rechte, welche sich in der Systemtabelle
SYSOBJECTS sowie SYSPROTECTS
befinden, auf die Tabellen dieses Anwenders
ermitteln. Hierzu kommen folgende
Funktionen des SQL Servers zum Einsatz:
SUSER_SID() liefert die
angemeldeten Anwenders.
SID
des
PATINDEX('%pattern%', expression) Gibt
für
alle
gültigen
Textsowie
Zeichendatentypen die Startposition des
ersten Auftretens eines Musters (Pattern) in
einem angegebenen Ausdruck bzw. NULL,
wenn das Muster nicht gefunden wird,
zurück. Da die Muster aber mit Sicherheit
existieren können wir immer davon
ausgehen ein Ergebnis in numerischer Form,
nämlich genau 1, zu erhalten.
SUSER_NAME()- Funktion.
SELECT SO.name,
MAX(PATINDEX('193',STR(SP.action,3,0))) AS SEL,
MAX(PATINDEX ('195',STR(SP.action,3,0))) AS INS,
MAX(PATINDEX ('196',STR(SP.action,3,0))) AS DEL,
MAX(PATINDEX ('197',STR(SP.action,3,0))) AS UPDT
FROM Sysobjects SO, Sysprotects SP
WHERE SP.id = SO.id AND
SP.uid IN ( SELECT uid FROM Sysusers
WHERE SID = SUSER_SID() )
AND SP.protecttype <> 206
GROUP BY SO.name
Dieser etwas komplexere SELECT Befehl
liest uns für den angemeldeten Anwender
alle Rechte „193=SELECT, 195=INSERT
196=DELETE und 197=UPDATE“ auf die
Tabellen aus und stellt das Ergebnis in der
Form dar, das auf den Tabellennamen das
Recht in numerischer Schreibweise folgt.
Wichtig ist die Abfrage „SP.protecttype <>
206“ da ansonsten evtl. entzogene
Privilegien nicht berücksichtigt werden!
Die Abfrage speichert den Wert für
SELECT/INSERT/UPDATE/DELETE
der jeweilige Tabelle mit 1 insofern hierfür
ein Recht vergeben wurde und den Wert 0
wenn kein Recht existiert. Nun kann mittels
einfacher Abfrage auf dieses Ergebnis des
Rechtstatus vom Anwenders geprüft
03-09 Rechteverwaltung für Ms SQL Server
werden. Befindet sich die zu prüfende
Tabelle nicht in der Abfrage so hat der
Anwender keinerlei Rechte hierauf, da in der
Tabelle SYSPROTECTS nur die vergebenen
Rechte gespeichert werden. Will man dies
ändern so braucht man nur aus dem
Objektkatalog SYSOBJECTS alle Tabellen
mit dem Ergebnis zu verknüpfen ( LEFT
OUTER JOIN ) und hat dann alle Tabellen
komplett mit den gewährten Rechten
dargestellt. Hierzu verwendet man die unten
aufgeführte SQL- Anweisung.
Diese Art der Rechtprüfung hat sich in der
Praxis schon häufig bewährt da der
Anwender hiermit vor den fehlenden
Berechtigungen aus der Applikation heraus
gewarnt werden kann um dann den
FoxX-Professional
Seite 2
Administrator zu verständigen. Diese
Abfrage gewährleistet aber nicht, dass
eventuell festgelegte Restriktionen auf
Feldebene erfasst wurden. Hierzu muss in
der Systemtabelle SYSPROTECTS die
Spalte „Columns“ ausgewertet werden in
welcher sich das Bitmuster der Felder
befindet! Ebenso muss angemerkt werden,
das diese Abfrage nur für Einzelanwender
und nicht für Gruppen- bzw. Rollenrechte
gilt!
Abfragen der Rechte auf alle Tabellen in der Datenbank:
SELECT SO.name,
ISNULL(MAX(PATINDEX('193',STR(SP.action,3,0))),0)
ISNULL(MAX(PATINDEX('195',STR(SP.action,3,0))),0)
ISNULL(MAX(PATINDEX('196',STR(SP.action,3,0))),0)
ISNULL(MAX(PATINDEX('197',STR(SP.action,3,0))),0)
FROM Sysobjects SO
LEFT JOIN Sysprotects SP
ON SO.id = SP.id
AND SP.uid IN ( SELECT uid FROM Sysusers
WHERE SID = SUSER_SID() )
AND SP.protecttype <> 206
GROUP BY SO.name,SO.xtype
HAVING SO.xtype = 'U'
Da das LEFT JOIN Ergebnis NULL-Werte
zurückliefert,
werden
diese
mittels
ISNULL()-Funktion in einen numerischen
Wert gewandelt ( aus NULL wird 0 ) und
können so Problemlos im Ergebnis
dargestellt werden. Die HAVING-Klausel
Sysobjects.xtype = 'U' sorgt dafür, das nur
die Tabellen angezeigt werden. Um z.B. alle
zugelassenen Sichten darzustellen wird
Sysobjects.xtype = 'V' angegeben. Aber
nochmals zum Verständnis. Diese Abfragen
gelten nur für gewährte Rechte an einen
einzelnen Anwender. Rechte welche durch
Rollen geerbt wurden können so nicht
erfasst
werden.
Ein
Tabelleneigner
(DataBaseOwner) wird seine Tabellen
immer lesen und schreiben können ohne ein
explizietes Recht darauf zu besitzen. Wird
eine Rolle angelegt und der Rolle Rechte auf
Tabellen gewährt (Grants), so erben die
Mitglieder dieser Rolle alle Rechte der Rolle.
In der Tabelle SYSUSERS kann in der
Spalte (Attribut) „issqlrole“ bzw. „isapprole“
gesehen werden welche Rollen existieren.
Mit SELECT name FROM SYSUSERS
WHERE issqlrole = 1 können alle Rollen
03-09 Rechteverwaltung für Ms SQL Server
AS
AS
AS
AS
SEL,
INS,
DEL,
UPDT
abgefragt werden. Die Existenz von
Applikationsrollen werden mittels SELECT
name FROM SYSUSERS WHERE isapprole
= 1 geprüft. Applikationsrollen sind sehr
interessante Rollen, da man nur mittels der
Applikation auf die Daten zugreifen kann.
Versucht ein Anwender einer Applikationsrolle mittels anderer Produkte auf die Daten
zuzugreifen so wird dieses vom SQL Server
blockiert. Nur die definierte Applikation darf
die Daten nutzen. Mittels Applikationsrollen
kann dann die Anwendungssicherheit
gesteigert werden.
Alle Rollenrechte erfassen
Um nun alle Rollenrechte zu erfassen
müssen wir unsere SQL- Abfrage um die
Systemtabelle SYSMEMBERS erweitern um
somit die Zuordnung des Anwenders zur
Rolle zu ermitteln. Hierzu ist die groupuid der
memberuid, welcher der uid des Anwenders
entspricht, gegenübergestellt. Somit erhalten
wir die groupid welchen der Anwender
zugeordnet ist in unsere Ergebnismenge.
FoxX-Professional
Seite 3
Abfrage der Rechte (SELECT / INSERT / UPDATE / DELETE) auf die Tabellen der Rolle(n)
denen ein Anwender zugeordnet ist. Hiermit werden nicht die Einzelrechte berücksichtigt!
SELECT SO.name,SO.xtype,
ISNULL(MAX(PATINDEX('193',STR(SP.action,3,0))),0) AS SEL,
ISNULL(MAX(PATINDEX('195',STR(SP.action,3,0))),0) AS INS,
ISNULL(MAX(PATINDEX('196',STR(SP.action,3,0))),0) AS DEL,
ISNULL(MAX(PATINDEX('197',STR(SP.action,3,0))),0) AS UPDT
FROM Sysobjects SO
LEFT JOIN Sysprotects SP
ON SO.id = SP.id
AND SP.uid IN ( SELECT groupuid FROM sysmembers
WHERE memberuid = ( SELECT uid FROM Sysusers WHERE SID =
SUSER_SID() ) AND groupuid >= 16400 )
AND SP.protecttype <> 206
GROUP BY SO.name,SO.xtype
HAVING SO.xtype = 'U'
Das Ergebnis wird in der folgenden Form dargestellt.
name
xtype SEL
INS
DEL
-----------kunden
positionen
artikel
plz
blz
vorlauf
dta_store
belege
----- ---U
1
U
1
U
1
U
1
U
1
U
1
U
0
U
1
---1
1
1
0
0
0
0
1
---0
1
0
0
0
0
0
1
Auch wenn durch mehrere Rollen die
Rechte auf die Tabellen für den Anwender
unterschiedlich vergeben wurden, wird das
höchste Tabellenrecht in der abgerufenen
Darstellung angezeigt. Wie zu erkennen ist
kann, in dem aufgeführten Beispiel, auf die
Tabelle dta_store nicht zugegriffen werden,
da das SELECT- Recht = 0 ist. Hier kann
eine Applikation durch das fehlende Recht
UPDT
----1
1
1
0
0
0
0  keine Rechte
1
mit einer Fehlermeldung abbrechen wobei
wir wieder am Eingangspunkt des Artikels
angelangt wären. Durch die im Artikel
angegebenen SQL- Abfragen kann der
Anwendungsentwickler die Rechte während
der Laufzeit kontrollieren und somit die
Fehlerquote im Berechtigungssektor um ein
vielfaches herabsetzen.
Eine erweiterte Abfrage welche sowohl die Rollen, als auch die Einzelrechte beinhaltet sieht
folgendermaßen aus:
SELECT SO.name,SO.xtype,
ISNULL(MAX(PATINDEX('193',STR(SP.action,3,0))),0) AS SEL,
ISNULL(MAX(PATINDEX('195',STR(SP.action,3,0))),0) AS INS,
ISNULL(MAX(PATINDEX('196',STR(SP.action,3,0))),0) AS DEL,
ISNULL(MAX(PATINDEX('197',STR(SP.action,3,0))),0) AS UPDT
FROM Sysobjects SO LEFT JOIN Sysprotects SP ON SO.id = SP.id
AND ( SP.uid IN ( SELECT groupuid FROM sysmembers WHERE memberuid = (
SELECT uid FROM Sysusers WHERE SID = SUSER_SID() ) AND groupuid >= 16400 )
OR SP.uid IN ( SELECT uid FROM Sysusers WHERE SID = SUSER_SID()) )
AND SP.protecttype <> 206 GROUP BY SO.name,SO.xtype
HAVING SO.xtype = 'U'
03-09 Rechteverwaltung für Ms SQL Server
FoxX-Professional
Seite 4
Zur Anregung hier nun eine Abfrage in
welcher mit Bitdarstellung in einer Spalte
gearbeitet wird. In der Bitreihe 8 4 2 1 ( 2^3
2^2 2^1 2^0 ) setzen wir SELECT = 2^0 =
1 , INSERT = 2^1 = 2 , DELETE = 2^2 =
4 und UPDATE = 2^3 = 8. Diese Reihe
liesse sich leicht für weitere Berechtigungen
erweitern. So lassen sich die Rechte in einer
Spalte
zusammenfassen.
In
einer
Applikation brauchte man nun, wenn alle
Rechte gefordert sind, den Wert 15
abzufragen ( SEL + INS + DEL + UPDT
= 1 + 2 + 4 + 8 = 15 ). Hat der Anwender
keine 15, so sind die erforderliche Rechte
nicht an ihn vergeben! Mittels BITAND()
und INT() Funktion lassen sich dann die
Rechte wieder ermitteln. Wollen wir z.B. das
UPDATE- Recht prüfen so schreiben wir
INT(BITAND( 15 , 8 )/8). 15 ist das
Ergebnis welches die Abfrage liefern könnte
und 8 das zu prüfende BIT ( 2^3 ) für das
UPDATE Recht. Ist das Ergebnis eine 1 so
ist an dieser Stelle ein BIT gesetzt und der
Anwender hat das Recht. Ist das Ergebnis
eine 0 so existiert kein UPDATE Recht.
SELECT LEFT(SO.name,30) Name,
ISNULL(MAX(PATINDEX('193',STR(SP.action,3,0))),0) * 1 +
ISNULL(MAX(PATINDEX('195',STR(SP.action,3,0))),0) * 2 +
ISNULL(MAX(PATINDEX('196',STR(SP.action,3,0))),0) * 4 +
ISNULL(MAX(PATINDEX('197',STR(SP.action,3,0))),0) * 8 AS Recht
FROM Sysobjects SO LEFT JOIN Sysprotects SP ON SO.id = SP.id
AND ( SP.uid IN ( SELECT groupuid FROM sysmembers WHERE memberuid = (
SELECT uid FROM Sysusers WHERE SID = SUSER_SID() ) AND groupuid >= 16400 )
OR SP.uid IN ( SELECT uid FROM Sysusers WHERE SID = SUSER_SID()) )
AND SP.protecttype <> 206 GROUP BY SO.name,SO.xtype
HAVING SO.xtype = 'U'
Abfrage der Rechte als Ergebnis
in einer Spalte:
und somit
aufspüren.
fehlende
Berechtigungen
Letztendlich erhalten wir eine Abfrage in
welcher aus allen Tabellen alle möglichen
Einzel- als auch Rollen- Rechte gelesen
werden. Mittels dieses Ergebnis kann der
Anwendungsentwickler mit ein paar
Routinen die Rechte des Anwenders prüfen
Zum Schluß sei noch anzumerken das einige
dieser SQL-Abfragen auch mit dem SQL
Server 6.5 (SP5a) funktionieren. Die SQLAbfragen, bei welchen die Rollen ausgelesen
werden, funktionieren aber nur mit SQL
Server 7 bzw. SQL Server 2000.
SELECT LEFT(SO.name,30) Name,
ISNULL(MAX(PATINDEX('193',STR(SP.action,3,0))),0) * POWER(2,0) +
ISNULL(MAX(PATINDEX('195',STR(SP.action,3,0))),0) * POWER(2,1) +
ISNULL(MAX(PATINDEX('196',STR(SP.action,3,0))),0) * POWER(2,2) +
ISNULL(MAX(PATINDEX('197',STR(SP.action,3,0))),0) * POWER(2,3) +
ISNULL(MAX(PATINDEX('198',STR(SP.action,3,0))),0) * POWER(2,4) +
ISNULL(MAX(PATINDEX('203',STR(SP.action,3,0))),0) * POWER(2,5) +
ISNULL(MAX(PATINDEX('207',STR(SP.action,3,0))),0) * POWER(2,6) +
ISNULL(MAX(PATINDEX('222',STR(SP.action,3,0))),0) * POWER(2,7) +
ISNULL(MAX(PATINDEX('224',STR(SP.action,3,0))),0) * POWER(2,8) +
ISNULL(MAX(PATINDEX('228',STR(SP.action,3,0))),0) * POWER(2,9) +
ISNULL(MAX(PATINDEX('233',STR(SP.action,3,0))),0) * POWER(2,10) +
ISNULL(MAX(PATINDEX('235',STR(SP.action,3,0))),0) * POWER(2,11) +
ISNULL(MAX(PATINDEX('236',STR(SP.action,3,0))),0) * POWER(2,12)
AS Recht
FROM Sysobjects SO LEFT JOIN Sysprotects SP
ON SO.id = SP.id
AND ( SP.uid IN ( SELECT groupuid FROM sysmembers WHERE memberuid = (
SELECT uid FROM Sysusers WHERE SID = SUSER_SID() ) AND groupuid >= 16400 )
OR SP.uid IN ( SELECT uid FROM Sysusers WHERE SID = SUSER_SID()) )
AND SP.protecttype <> 206
GROUP BY SO.name,SO.xtype
HAVING SO.xtype = 'U'
03-09 Rechteverwaltung für Ms SQL Server
FoxX-Professional
Seite 5
Herunterladen