Tag: "sicherheit"

SQL Server Row- and Cell-Level Security – Disclosure vulnerability // Schwachstellen in Zeilen-basierter Sicherheit

 

(de)
Es ist Zeit für einen weiteren Artikel zum Thema Sicherheit.
Und durch einen Forum Thread zu „Datengesteuerter Sicherheit“ mittels der IS_MEMBER(), USER_NAME(), SUSER_SNAME() – Funktionen kam ich auf die Idee, ein kurzes Beispiel zu zeigen, wie sich solche Konstrukte leicht umgehen lassen und die geschützten/verborgenen Daten offengelegt werden können, wenn sie nicht mit weiteren Mitteln gesichert werden.
Sehen wir uns ein Beispiel an.

(en)
It’s time for another post on security matters.
And through a forum-thread on data-driven security by the means of views using the IS_MEMBER(), USER_NAME(), SUSER_SNAME() – functions, I came up with the idea of giving a short example how such constructs can easily be circumvented and the protected/hidden data become disclosed, when not being secured by further means.
So let’s look at an example.

Im Folgenden werden wir ein recht verbreitetes Szenario sehen, wie Sicherheit auf Zeilenebene / Row-Level Security (und auch Zellenebene/Cell-Level Security) implementiert werden kann.

Die Architektur ist recht einfach:
Eine Tabelle enthält Datenzeilen, von welchen einige von einer bestimmten Gruppe Personen gelesen werden darf, und andere Zeilen von anderen Personen – jeweils exklusiv.
Um das zu erreichen, wird eine Sicht angelegt. Diese Sicht muss natürlich denselben Besitzer haben, so dass der Prinzipal Berechtigungen auf die Sicht alleine erhalten kann, und durch die Besitzerkette an die Daten gelangt.
Innerhalb der Sicht ist eine Where-Klause, die einen Filter auf ein bestimmtes Attribut in der Tabelle enthält, durch das der Benutzer der aktuellen Sitzung erkannt wird und ausschließlich die Daten zurückgeliefert werden, die seiner Rollen-Mitgliedschaft entsprechen.
Natürlich gibt es auch komplexere Designs mit Zwischentabellen und mehrfachen Rollenmitgliedschaften/Rechten, aber am Ende teilen alle dieselbe Schwachstelle, die ich demonstrieren werde.
Im Folgenden zunächst ein Diagramm der Architektur.

In the following we will see a quite common scenario of how Row-Level Security (and also Cell-Level Security) can be implemented.

The architecture is quite simple:
A table is holding rows of data, some of which are supposed to be readable by a certain group of people, and other rows by other people – in each case exclusively.
In order to achieve this, a view is created. This view naturally must have the same owner, so the principal can be granted permissions on nothing but the view and get to the data by means of the ownership-chain.
Within the view there is a Where-clause which contains a filter on a certain attribute in the table, by which the user of the current session is detected and returned solely the data which matches his role-membership.

Of course there are also more complex designs with intermediate tables and multi-role-memberships/permissions, but it all comes down sharing the same vulnerability which I am about to demonstrate.

First of all here's a diagram of the high-level architecture:

 SQL_Row_Level_Security_Schema

 

Sehen wir uns das ganze also an.
Die Einrichtung Tabelle und der Sicht, inklusive 2er Beispieldatensätze:

So let’s see it in action.
The Setup of the Table and the View including 2 sample data rows:

 SQL_Row_Level_Security_Table_View_Setup

Die Spalte „Role“ wird von der Sicht verwendet, um die jeweilige Zeile, unter Verwendung der IS_MEMBER()-Funktion nur Mitgliedern der jeweils hinterlegten Datenbankrolle durchzureichen.

The column “Role” is used by the view to return the respective row by using the IS_MEMBER()-function only to members of the respectively stored database-role.

 SQL_Row_Level_Security_Table_View

Benutzer, Rollen und Berechtigungen:

User(s), Roles and Permissions:

 SQL_Row_Level_Security_User_Roles_Permissions

Erinnern wir uns, was die Tabelle enthält:

Now, remember what our table contains:

 SQL_Row_Level_Security_Data

In einer heilen Welt, vor dem Sündenfall, wäre dies ausreichend.
(Nachdem wir uns als „Andreas“, der Mitglied der Datenbankrolle RoleAlpha ist, einloggen) würden unsere Abfragen wie folgt aussehen, und lediglich die Zeilen zurückliefern, die der RoleAlpha „gehören“:

So in an innocent world, before the fall of mankind, this would be sufficient.
(After logging in as “Andreas”, who is member of the RoleAlpha database-role) our queries would look like this and only return the rows which “belong” to RoleAlpha:

 SQL_Row_Level_Security_Query

- Natürlich wird die Funktion User_Name() nur für Demo-Zwecke eingesetzt.
Ergebnis:

- Of course the function User_Name() is only used for demo-purposes.
Result:

 SQL_Row_Level_Security_Filtered_Data

Angriff
Aber Andreas spielt nicht fair. Er ist neugierig, was sonst noch in der Tabelle stehen könnte.
Also schreibt er eine Abfrage wie diese:

Attack
But, Andreas does not play nice.  He is curious on what else might be in the table.
So he crafts a query like this:

 SQL_Row_Level_Security_Attack

Und das Ergebnis ist:

And the result is:

 SQL_Row_Level_Security_Disclosure

Nicht „schön“, aber wir haben, was wir wollten: die „geschützten“ Daten.

Der bereits geschulte Leser erkennt diese Form des Angriffs vielleicht aus einem anderen Bereich wieder: SQL Injection.
Es ist eine Form des alten Freundes „Error Based Attack“ oder „Error Disclosure“, die auch bei schlecht geschriebenen Webanwendungen zum Zuge kommt. Das habe ich u.a. 2013 auf diversen Konferenzen gezeigt (Vortragsreihe).
Der Kontext ist ein wenig anders, aber die Idee dahinter ist dieselbe.

Not exactly “pretty”, but we got what we want: the “protected” data.

The well-educated reader may remember this kind of attack from a different area as well: SQL Injection.
It’s a form of the old fried “error based attack” or “error-disclosure”, which can also be used for badly written web-applications. I have also shown that amongst others in 2013 at several conferences (series of sessions).
The context is a little bit different, but the idea is the same.

 Security-Gate-Fail

Einigen kommt das Bild vielleicht schon bekannt vor :-)

Stellt sicher, dass das nicht Euer "Vorgarten" ist!

Wo wir davon reden:

To some, this picture may already look familiar :-)

Make sure it’s not your "front-yard"!

Speaking of which:

 

Schutzmaßnahmen

Was kann man gegen solche Angriffe tun?
Im Wesentlichen stehen einem 3 bekannte Möglichkeiten zur Verfügung:

1) Einsatz von gespeicherten Prozeduren, die alle Fehler abfangen, oder, wenn man unbedingt mit Sichten Arbeiten möchte, der Einsatz einer dazwischengeschalteten Multi-Statement-Tabellenwertfunktion

2) Datenverschlüsselung (Nicht TDE!)

3) Ähnlich wie 1, Aufbau einer Mittelschicht in der Anwendung, die derartiges unterbindet.

Und schlussendlich sollte man für kritische Daten auch über eine Überwachungslösung nachdenken.

Security-measures

What can prevent such forms of attack?
Essentially there are 3 well-known methods at hand:

1) The use of stored procedures which catch all errors, or, if one really wants to use views for some reason, using of a multi-statement table valued function which will be put between.

2) Data encryption (Not TDE!)

3) Similar to 1, implementation of a mid-tier in the application which prohibits such actions.

Finally one should also think about an Auditing solution for critical data.

Die hier gezeigte Technik der Row-Level Disclosure ist nicht wirklich etwas Neues, wird aber gerne immer mal vergessen.
Nachlesen kann man darüber zum Beispiel auch in diesem (alten, aber immer noch zutreffenden) Whitepaper:

The technique of Row-Level Disclosure shown above isn’t really new, but frequently forgotten about.
One can read about this, for example, in this (old, but still applicable) whitepaper:

Implementing Row- and Cell-Level Security in Classified Databases Using SQL Server 2005

 

Happy securing,

Andreas

 

Wer sich ermuntert fühlt, nun einmal richtig in das Thema „Sicherheit mit SQL Server“ einzusteigen, für den habe ich auch 3 erstklassige Trainings im Angebot:

If you now feel encouraged to really dive into the subject of “Security with SQL Server”, I do have 3 first-class Trainings on offer:

Für Beginner, die hier einen guten Überblick erhalten und Grundlegende Kenntnisse erlernen:

For Starters, who gain a good overview and learn essential knowledge in the basics:

(SES) SQL Server Security Essentials for Developers & Administrators (1 day)
3. April 2014 in Düsseldorf

Für Administratoren, die fortgeschrittene Sicherheitskonzepte umsetzen müssen:

For Administrators that have to implement advanced security concepts:

(SIA) Securityworkshop for SQL Server Administrators (advanced) (1 day)
4. April 2014 in Düsseldorf

Für Entwickler, die fortgeschrittene Sicherheitskonzepte umsetzen müssen:

For Developers that have to implement advanced security concepts:

(SID) Securitysworkshop for SQL Server Developers (advanced) (1 day)
24. April 2014 in Düsseldorf

Security-Check-Script & Survey: SQL Server Security - Database-Owners, critical Permissions and role membership / Sicherheitsprüfungs-Script & Umfrage: SQL Server Datenbankbesitzer, kritische Rechte und Rollenmitgliedschaft

(de)
In dieser Umfrage möchte ich einmal in einem größeren Kreis ermitteln, welche Accounts typischerweise als Datenbankbesitzer eingetragen werden. Die kumulierten Ergebnisse werde ich anschließend hier veröffentlichen um sie mit der Community zu teilen, zusammen mit einigen Empfehlungen hinsichtlich Sicherheits-Härtung.

Dabei interessieren vor allem bestimmte serverweite Berechtigungen nicht nur des verwendeten Logins selber, sondern auch, falls er Mitglied einer (custom) Server Role ist, bestimmte, kritische Rechte dieser Rolle.

Wer meine Vorträge zum Thema „Sicherheit in SQL Server“ in den letzten Jahren, und insbesondere der im Sommer 2013 gestarteten Reihe „SQL Server Attacked“ verfolgt hat, wird sich vielleicht hat erinnern, wie ich dort auch gezeigt habe, wie man aus einer Datenbank ausbrechen und volle Systemrechte erlangen kann („Privilegien Erweiterung“) – basierend auf einer Kombination von Datenbankbesitzer, -Konfiguration und Impersonierung.

Hier stelle ich nun einen T-SQL Script zur Verfügung, welcher

  • Den jeweiligen Datenbankbesitzer aller Datenbanken ermittelt
  • Ungültige/Fehlende Datenbankbesitzer erkennt
  • Anzeigt, ob der Besitzer direkt über sicherheitskritische systemweite Rechte verfügt
  • Mitgliedschaft in hochprivilegierten Server-Rollen anzeigt – inklusive der benutzerdefinierten Serverrollen (ab SQL 2012 möglich)
  • Die kritischen Datenbankeinstellungen „Vertrauenswürdig“ und „Datenbankverkettung“ anzeigt.

Und hier ist der Script:

(en)
In this survey, I would like to explore in a greater radius which accounts are typically used as database owners. I will subsequently publish the cumulated results here to share them with the community together with some recommendations for hardening security.

In this instance, particular server-wide permissions both of the used account as well as, in case of membership of a (custom) Server Role, critical permissions of that role, are of interest.

Those who have followed my presentations on the topic “Security in SQL Server” in the last years, and especially the „SQL Server Attacked“ series launched in the summer of 2013, may remember how I had also demonstrated there how to break out of a database and be granted full system rights (“Elevation of privileges”), - based on a combination of database owner, configuration and impersonation.

Here, I am providing a T-SQL Script which

  • Identifies the respective database owners of all databases
  • Detects invalid/missing database owners
  • Indicates whether the owner directly possesses security-critical system-wide rights
  • Indicates membership in high privilege Server Roles – including the user defined Server Roles (possible since SQL 2012)
  • Indicates the critical database configurations “trustworthy” and “database chaining”.

Here you can find the script:

 

Server 1: http://j.mp/13_SQL_DBO_Survey
Server 2: gallery.technet.microsoft.com/scriptcenter/Database-Owners-role-3af181f5/

 

- Er sollte auf allen SQL Servern ab der Version 2005 funktionieren (getestet 2008-2014).

Zum Zwecke der Umfrage bitte ich Euch, die anonymisierten Ergebnisse (am Besten in Excel-Format) an die Email survey@SarpedonQualityLab.com zu senden, oder auch hier in den Kommentaren zu posten.
Zum Zwecke der Anonymisierung kann man einfach die letzten 3 Spalten aus dem Resultset auslassen – diese haben für eine statistische Erhebung auch keinen Nutzen sondern sind nur für Eure internen Zwecke bestimmt :-).

Hier seht ihr ein Beispiel-Ergebnis:

-           It should be working on all SQL Servers since the 2005 version (tested: 2008-2014).

For the purpose of the survey, I would like to ask you to send the anonymized results (preferably in excel-format) to the email survey@SarpedonQualityLab.com, or as well post them here in the comments.

For anonymization purposes, you can simply leave out the last three columns from the result set – these are not of use to a data collection and only meant for your internal usage :-).

Here, you can see a sample result:

Database_Ownership_Permissions_Sample_Result

 -> click to enlarge

Mehrere Einträge für dieselbe Datenbank entstehen, wenn der Datenbankbesitzer – oder seine Serverrolle(!) über mehrere, der von mir als sicherheitskritisch klassifizierten Rechte verfügt. Diese stehen dann in der Spalte login_permission bzw. role_permission. Hinter den Kürzeln verbergen sich:
ALLG = ALTER ANY LOGIN
ALSR = ALTER ANY SERVER ROLE
CL  = CONTROL SERVER
XA  = EXTERNAL ACCESS ASSEMBLY
(mehr dazu auch hier: CONTROL SERVER vs. sysadmin/sa: permissions, system procedures, DBCC, automatic schema creation and privilege escalation - caveats).

Die Inhalte der Spalten DatabaseNo, database_owner und external_owner sind absichtlich allgemein gehalten – die exakten Namen sind wie gesagt in den letzten 3 Spalten zu finden.

Die Spalte db_owner_valid zeigt an, ob die Datenbank einen gültigen Besitzer hat. In diesem Fall besteht ein match zwischen dem „externen Besitzer“ und dem in der Datenbank selber hinterlegten. In der Spalte external_owner steht nur ob dieser „externe Besitzer“ sa ist oder nicht – der genaue Login steht dann in *External_Owner.Der Script speichert keine Daten dauerhaft im System ab und beseitigt seine temporären Zwischenergebnisse selbst.

Ich hoffe, ihr findet die Auswertung hilfreich – und ich hoffe, ihr könnt die (anonymisierten) Ergebnisse mit der Community teilen. Ich werde keine Email speichern oder verwenden, sondern nur die anonymisierten Abfrageergebnisse.

Ich bedanke mich für eure Teilnahme und Unterstützung der Community!
Ich verspreche, die kumulierten Ergebnisse in den nächsten Monaten zusammen mit entsprechenden Hinweisen auf Best & Bad Practices sowie auf möglichen Einfallstoren für Privilegienerweiterungs-Angriffen zu veröffentlichen.

Multiple entries for the same database occur when the database owner – or his serverrole(!) possess multiple of the permissions which I classified as security-wise critical. These are listed in the column login_permission respectively role_permission. The codes stand for:
ALLG = ALTER ANY LOGIN
ALSR = ALTER ANY SERVER ROLE
CL  = CONTROL SERVER
XA  = EXTERNAL ACCESS ASSEMBLY
(you can read more on that here: CONTROL SERVER vs. sysadmin/sa: permissions, system procedures, DBCC, automatic schema creation and privilege escalation - caveats).

The contents of the columns DatabaseNo, database_owner and external_owner are left general on purpose – the exact names can be found in the last 3 columns s mentioned above.

The column db_owner_valid indicates, whether the database has a valid owner. In this case there is a match between the „external owner“ and the one stored within the database itself. The column external_owner only shows whether that „external owner“ is sa or not –the exact Login is shown in *External_Owner.

The script does not permanently save any data in the system and removes its temporary intermediary results by itself.

I hope you find the report useful and I hope you can share the (anonymized) results with the community.
I will not store or use any email but only use the anonymized Query-results.

 Thank you in advance for your participation and support of the community!
I promise to publish the cumulated results with according details on best & bad practices as well as on to possible gateways to elevation of privilege attacks in the next months.

 

Andreas

Where are the scripts to the session „SQL Attacked/Hacking SQL Server“ ? ;-)

Wo sind die Scripte zu dem Vortrag „SQL Attacked/Hacking SQL Server“ ? ;-)

(de)
Im Anschluss an die Vorträge aus meiner „Hacking SQL Server“-Reihe „SQL Server Sicherheit „SQL Attack..ed“ – Angriffszenarien auf SQL Server („SQL Server Hacken“)“, die ich bisher bereits auf den SQLSaturdays Rheinland, Istanbul, auf der SQLRally Amsterdam und in vielen Regionalgruppen der PASS Deutschland zeigte, kommt öfters die Frage auf, ob ich den gezeigten Code öffentlich verfügbar mache. Da Twitter sich als Diskussionsmedium nicht so eignet (schöne Grüße an @DirkHondong und @FrankGeisler ;-) ), das Thema aber doch etwas mehr Beachtung verdient, möchte ich darauf in einigen Sätzen eingehen.

(en)
Subsequent to the lectures from my “Hacking SQL Server” series “Security Session „SQL Attack..ed“ – Attack scenarios on SQL Server ("Hacking SQL Server")” which I have already given at the SQLSaturdays Rheinland, Istanbul, at the SQLRAlly Amsterdam and at many regional groups of PASS Germany, more often than not the question arises whether I make the presented code available to the public. With Twitter not being that suitable a medium of discussion (greetings to @DirkHondong and @FrankGeisler ;-)), yet the topic deserving some more attention, I will get into the matter in the following.

Der Hintergrund, das ich die dafür entwickelten Scripts nicht veröffentliche, ist eigentlich recht einfach: ich zeige darin unter anderem Angriffsvarianten und Techniken, die so noch nicht dokumentiert oder in der „Szene“ bekannt sind(?).

Und da ich die frei verfügbaren SQL-Injection- und allgemein „Hacking“/DoS -Tools ein wenig kenne, möchte ich vermeiden, denjenigen, die diese entwickeln, neue Ideen zu geben um Server in die Knie zu zwingen. Das bringt keinem (aus der SQL Server Community) etwas (- höchstens "Auftragshackern", aber "leider" habe ich da keine Aktien drinnen ;-) ).

-           Die meisten SQL-Injection-Varianten sind übrigens auch wirklich gut im Netz dokumentiert, und eine einfache Suche wird eine Vielfalt an Code-Beispielen zutage bringen. Es macht kaum einen Unterschied, welche Vorlage man verwendet, man muss so und so noch Anpassungen vornehmen. ;-)

Im Gegensatz zu landläufiger Meinung, glaube ich nicht daran, dass jeder alle „Hacking“-Techniken selber durchführen können muss. Ich denke das ist häufig ein Vorwand, sicherheitsbedenkliche Aktionen pauschal zu rechtfertigen.

Ich bin der Ansicht, dass es genügt, zu wissen/gesehen zu haben, wo man angreifbar sein kann, und das es wichtiger ist, die Zeit darauf zu verwenden, die Skills für die Sicherung zu entwickeln.

Um selber zu „Hacken“, ist das übrigens eine gute Voraussetzung (und der Unterschied zum sogenannten „Script-Kiddie“). Nur das man dann einfach noch mehr Kenntnisse benötigt.

In aller Regel sehe ich jedoch eher einen Mangel an Kenntnissen über die Zusammenhänge in der Sicherheitsarchitektur von SQL Server, auf den ich mich naturgemäß fokussiere, sowie natürlich dem darunterliegenden Windows-Server und der Domain-Architektur allgemein.
„Hacken“ zu können bringt für sich gesehen erst einmal gar nichts. Das kann man, wenn man alles bekannte abgesichert hat immer noch angehen. Wenn das nötig ist, befindet man sich in dem grauen Bereich von „Penetration Testing“.

The background to why I don’t make public the scripts developed for this purpose is actually quite simple: in the scripts, I am showing attack variants and techniques, among others, which have not been documented or are not known within the “scene” (?).

And since I am a little familiar with the discretionary SQL injection and “Hacking”/DoS tools in general I would like to avoid giving those parties developing these tools new ideas for bringing servers down. This wouldn’t be of use to anyone (from the SQL Server community) (- except maybe to “contract hackers,” but I’m “afraid” I don’t hold any stocks in there ;-)).

-           By the way, most of the SQL injection variants are very well documented in the internet, and a simple search will spill out a variety of code examples. It will hardly make a difference which template one is using, as one will need to make adaptions anyway. ;-)

In contrast to general opinion, I do not believe that everyone needs to be able to carry out all “hacking” techniques by themselves. I think this is often used as a blanket pretext for justifying security-wise questionable actions.

I am of the opinion that it is sufficient to know/have seen where one can be vulnerable, and that it is more important to invest the time into developing skills for protection.

And this is a good prerequisite for “hacking” oneself (and the difference to the so-called “script kiddie”). Only that even more knowledge will be required then. 

In principle, however, I am rather observing a lack of knowledge of the correlations in the security architecture of SQL Server on which I am by nature focusing, as well as, of course, the Windows Server beneath it and the domain architecture in general.

To be able to “hack” alone is of no avail. Once one has covered everything known, one can still get to that. If this is necessary, one will end up in the grey area of “penetration testing.”

Das eigentliche Ziel meiner Vorträge/“Shows“(?) ist die "Awareness/Wahrnehmung", und Verbesserung der Sensibilität für das Thema Sicherheit im Sinne von:

„Habe ich das alles schon einmal bedacht?“
„Könnte ich doch noch Lücken haben und ein leichtes Angriffsziel sein, ohne es bislang gemerkt zu haben?“

Nicht:

"Um meine SQL Server Umgebung sicherer zu machen, möchte ich mich selber im „Hacken“ versuchen."

Ich hoffe das macht Sinn für Euch :-)

In jedem Fall ist eine offene Diskussion zu diesem Thema durchaus in meinem Sinne.

The actual goal of my lectures/ “shows” (?) is the “awareness/perception,” and the enhancement of sensitivity for the topic of security in the sense of:

“Have I taken all this into consideration?”
“Could I still have gaps and be an easy target without having noticed up to now?”

Not:

“In order to make my SQL Server environment more secure I would like to dabble in ‘hacking.’”

I hope this makes sense to you J

Either way, an open discussion on this topic is absolutely along my lines.

 

Happy securing

Andreas

PS: Aus diesem Grunde biete ich ja schon seit einigen Jahren immer wieder den Security Essential für die PASS Deutschland an – aber wie wir wissen, zieht das Thema „Sichern“ einfach weniger als „Hacken“ ;-)

Und für diejenigen, die die Grundlagen schon beherrschen, aber komplexere Anforderungen oder kritischere Umgebungen haben, kommen dann die Master-Classes zum Thema Sicherheit: www.sarpedonqualitylab.com/SQL_Master-Classes.htm

PS: For those who already know the basics, but have more complex requirements or critical environments, there are the Master-Classes on Security: en.sarpedonqualitylab.com/SQL_Master-Classes.htm

Security-Session: “SQL Server under Attack” this November @ SQL Rally Amsterdam – privilege elevation, DoS-attack via SQL Injection and more.. live action

Sicherheits-Vortrag “SQL Server under Attack” diesen November @ SQL Rally Amsterdam – Privilegienerweiterung, DoS-Attack via SQL Injection und mehr.. live Action

(de)
Ok, dieses Jahr wird das bei Weitem aktivste in Sachen Sprecher auf internationalen Konferenzen sein:
Nach 6 Konferenzen letztes Jahr, inklusive SQL Rally Nordic, die mir sehr gefallen hat, musste ich mich entscheiden zwischen noch einmal SQL Rally Nordic, SQL Rally Amsterdam oder gar beiden.
ich habe mich für die SQL Rally Amsterdam entschieden, da diese neu ist, und weil ich dem holländischen Chapter Leader versprochen habe, eine Session einzureichen. Daher dieses Jahr keine SQL Rally Nordic.

-           Da ich dieses Jahr auf bereits 7 Konferenzen gesprochen habe, inklusive 1,5 Tagen PreCon (www.andreas-wolter.com/sql-conferences/sql-conferences-2013.htm ) + 3 noch aufkommende Konferenzen (PASS Summit Charlotte USA, TechNet Berlin Germany, PASS Camp Darmstadt Germany), sind 11 Konferenzen 2013 wirklich eine Menge. Auch wenn man bedenkt, dass meine Kunden doch hin und wieder ganz froh sind, wenn ich Zeit für sie habe :-).

(en)
Alright, this is going to be the by far most active year in terms of speaking at international conferences:
After 6 conferences last year, including SQL Rally Nordic, which I really liked a lot, I had to decide between SQL Rally Nordic again or SQL Rally Amsterdam or even both.
I decided for SQL Rally Amsterdam, because it is new, and because I promised the Dutch Chapter leader, to hand in a session. So this year no SQL Rally Nordic.

-           Having spoken at already 7 conference this year, including 1.5 days of PreCon (www.andreas-wolter.com/sql-conferences/sql-conferences-2013.htm ) + 3 more coming up (PASS Summit Charlotte USA, TechNet Berlin Germany, PASS Camp Darmstadt Germany), 11 conferences in 2013 really is a lot. Also considering once in a while my customers are actually happy if I have time for them :-).

 Speaker_SQL_Rally_Amsterdam

SQL Rally Amsterdam bietet eine Auswahl von 5 (!) hochwertigen PreCons am 6. Nov. und 3 parallelen Vortrags-Tracks am 7.-8. Nov. an: BI Platform Architecture, Development and Administration, Enterprise Database Administration and Deployment, Database and Application Development mit vielen bekannten internationalen Sprechern, MCMs und MVPs.

 

Ich selber werde “SQL Attack(ed)” – SQL Server Under Attack präsentieren. Ein demo-geladener Sicherheits-Vortrag mit 2 neu-entwickelten Privilegienerweiterung und DoS-Attack Techniken, ausgeführt via SQL-Injection, in den Hauptrollen, die ich persönlich diesen Sommer in Vorbereitung auf den SQLSaturday Germany/Rheinland entwickelt habe und auch schon auf dem SQLSaturday in Istanbul gezeigt habe.

Wer also einige Gründe, Sicherheits-Maßnahmen ernst zu nehmen, live und in Aktion sehen möchte: schaut vorbei!

SQL Rally Amsterdam offers a choice of 5 (!) real high quality PreCons on Nov. 6th and 3 parallel session tracks on Nov. 7th-8th.: BI Platform Architecture, Development and Administration, Enterprise Database Administration and Deployment, Database and Application Development with many well-known international speakers, MCMs and MVPs.

 

I will be presenting “SQL Attack(ed)” – SQL Server Under Attack. A demo-loaded security session featuring 2 newly developed privilege elevation and DoS-attack techniques, executed via SQL-Injection, that I personally developed this summer in preparation of SQLSaturday Germany/Rheinland and also shown at SQLSaturday in Istanbul.

So if you want to see some reasons for taking security measures like permissions serious, live and in action, check it out!

 

CU in Amsterdam

 

Andreas

CONTROL SERVER vs. sysadmin/sa: permissions, system procedures, DBCC, automatic schema creation and privilege escalation - caveats

CONTROL SERVER gegen Sysadmin/sa: Berechtigungen, Systemprozeduren, DBCC, automatische Schema-Erstellung und Privilegienausweitung - Fallstricke

(DE)

Seit SQL Server 2005 gibt es die Serverweite Berechtigung CONTROL SERVER. Prinzipiell eine Alternative zur sysadmin-Mitgliedschaft, blieb sie dennoch nicht viel mehr als ein Ladenhüter – kaum bekannt und noch weniger verwendet.

Einer der Hauptgründe dafür war die fehlende Möglichkeit, dieses Recht einer Gruppe von Prinzipalen/Logins auf Server-Ebene zu geben.

Seit SQL Server 2012 ist es ja nun möglich, eigene Server-Rollen zu definieren, so dass diese Berechtigung nun immer mehr Verwendung findet.

Dennoch ist sie kein vollständiger Ersatz für sysadmin. Warum das so ist wo die Unterschiede liegen und wo es sogar ein Risiko sein kann, möchte ich im Folgenden für meine Leser festhalten und demonstrieren.

(EN)

Since SQL Server 2005, the server wide permission CONTROL SERVER has been existing. In principle being an alternative to sysadmin-membership, it did not turn out to be much more than a shelf warmer. - Little known and even less used.

One of the main reasons for this was the absence of an option to grant this permission to a group of principals/Logins on server-level.

Since SQL Server 2012, it has been possible to define custom server-roles, so now this permission is used more and more.

However, it is no complete replacement for sysadmin. In the following, I want to demonstrate to my readers exactly why this is, where the differences are and where it can even be a risk.

Grundlegende Kenntnisse über das Verhalten von sysadmin und dbo setze ich als hinreichend bekannt voraus, und konzentriere mich auf das, was bei der Verwendung von CONTROL SERVER anders ist.

I will take as a given basic knowledge about the behavior of sysadmin and dbo and therefore focus on the things that are different when using CONTROL SERVER.

 

Zunächst wird ein neuer Login, „DBA_TheDude“, angelegt – das Passwort natürlich streng meinen Richtlinien (für Blogs) entsprechend. ;-)

Es folgen eine neue Serverrolle, „Role_DBA“, in die der Login als Mitglied aufgenommen wird.

Und da diese Rolle für Administratoren gedacht ist, erhält sie die weitest-möglichen Rechte: CONTROL SERVER.

First of all, a new Login, „DBA_TheDude“, is created – the password of course adhering strongly to my rules (for blogs). ;-)

This is followed by a new server role “Role_DBA” to which the Login will be added as a member.

And since this role is meant for administrators, it receives the most extensive permission: CONTROL SERVER.

USE [master]
GO

CREATE LOGIN DBA_TheDude WITH PASSWORD=N'www', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
GO

CREATE SERVER ROLE [Role_DBA]

ALTER SERVER ROLE [Role_DBA]
ADD MEMBER DBA_TheDude

GRANT CONTROL SERVER TO [Role_DBA]
GO

CREATE DATABASE ControlServer_Schema_Demo
GO

Als nächstes melden wir uns als DBA am System an und lassen uns „die (effektiven) Rechte verlesen“ :-)

Next we log onto the system as DBA and have "our (effective) rights" displayed. :-)

EXECUTE AS LOGIN = 'DBA_TheDude'

SELECT entity_name, permission_name
FROM sys.fn_my_permissions(NULL,
NULL)
entity_name

entity_name

permission_name

server

CONNECT SQL

server

SHUTDOWN

server

CREATE ENDPOINT

server

CREATE ANY DATABASE

server

CREATE AVAILABILITY GROUP

server

ALTER ANY LOGIN

server

ALTER ANY CREDENTIAL

server

ALTER ANY ENDPOINT

server

ALTER ANY LINKED SERVER

server

ALTER ANY CONNECTION

server

ALTER ANY DATABASE

server

ALTER RESOURCES

server

ALTER SETTINGS

server

ALTER TRACE

server

ALTER ANY AVAILABILITY GROUP

server

ADMINISTER BULK OPERATIONS

server

AUTHENTICATE SERVER

server

EXTERNAL ACCESS ASSEMBLY

server

VIEW ANY DATABASE

server

VIEW ANY DEFINITION

server

VIEW SERVER STATE

server

CREATE DDL EVENT NOTIFICATION

server

CREATE TRACE EVENT NOTIFICATION

server

ALTER ANY EVENT NOTIFICATION

server

ALTER SERVER STATE

server

UNSAFE ASSEMBLY

server

ALTER ANY SERVER AUDIT

server

CREATE SERVER ROLE

server

ALTER ANY SERVER ROLE

server

ALTER ANY EVENT SESSION

server

CONTROL SERVER


Klingt gut. Scheint Nichts zu fehlen.
Oder doch?

Vergleichen wir es mal mit der Liste aller Rechte, die es auf Server-Ebene überhaupt gibt:

Sounds good. Nothing seems to be missing at first glance.
Or does it?

Let’s compare it to the list of all permissions which exist on server-scope:

SELECT class_desc COLLATE Latin1_General_CI_AI, permission_name COLLATE Latin1_General_CI_AI
FROM sys.fn_builtin_permissions('SERVER')
EXCEPT

SELECT
entity_name, permission_name
FROM sys.fn_my_permissions(NULL,
NULL)

-->

(0 row(s) affected)

Ok, also wir haben wirklich alle Rechte, die man (auf Serverebene) vergeben kann.
Das ist auch dokumentiert:
Permissions (Database Engine)
und hier: GRANT Server Permissions (Transact-SQL)

Diese Berechtigungen und Kommandos funktionieren auch wie dokumentiert.

Wie sieht es aber mit gespeicherten Systemprozeduren aus?

Ok, we really do have all permissions which can be granted (at server scope).
This is also documented:
Permissions (Database Engine)
and here: GRANT Server Permissions (Transact-SQL)

Those permissions and commands really do work as documented.

But how about system stored procedures?

exec sp_readerrorlog

-->

Msg 15003, Level 16, State 1, Procedure sp_readerrorlog, Line 11
Only members of the securityadmin role can execute this stored procedure.

Warum das jetzt?

Ganz einfach. Sicher ist es den meisten noch gut aus SQL Server 2000-Zeiten bekannt, dass sicherheitskritische Systemprozeduren einen Check auf Mitgliedschaft in bestimmten Rollen enthalten. Und das tun die meisten derer auch heute noch. Ein Artefakt der damaligen unflexiblen Rechte-Verwaltung, kann man sagen.

Wenn man in den Code der sp_readerrorlog schaut, wird es dort genau so gemacht:

Why ist that now?

Quite simple. Most do probably remember from SQL 2000 times, that security wise critical system procedures include a check for membership in certain roles. And most of them still do the same today. One can call it an artefact of the then inflexible permission-management.

When we look into the code of sp_readerrorlog, this is what is being done there as well:

if (not is_srvrolemember(N'securityadmin') = 1)
begin
raiserror(15003,-1,-1, N'securityadmin'
return (1)
end

...

exec sys.xp_readerrorlog...

Okay.
Natürlich könnten wir diesen Code umgehen und die xp_readerrorlog direkt aufrufen.

In der GUI-Anzeige im Management Studio hilft uns das nicht, wir können es als manuellen Workaround verwenden.

Weitere Systemprozeduren, die über SSMS aufgerufen werden und die Ausführung verweigern sind unter anderem:
sp_addumpdevice - für Backup-Devices
sp_enum_oledb_providers – wird beim Konfigurieren und Betrachten von Linked Servers verwendet.

sp_addlinkedserver lässt sich dafür ohne Probleme ausführen – nur eben nicht über die GUI wegen eben genannter Prozedur.

Die Einrichtung von Database-Mail über die GUI bleibt ebenfalls den sysadmins vorbehalten. Via Script sollte es jedoch funktionieren (ungetestet).

Auch die Konfiguration des Distributors für die Replikation mittels sp_adddistributor ist ohne den sysadmin-Bit nicht möglich.
Andere Replikationskonfigurationsaufgaben sind teilweise sogar über die GUI möglich.

Unter SQL Server 2005 – 2008R2 gibt es für das Hinzufügen/Entfernen von (Server-)Rollenmitgliedern nur die Prozedur sp_addsrvrolemember / sp_dropsrvrolemember. Diese führt ebenfalls eine Serverrollen-Mitgliedschafts-Prüfung durch. - Unter SQL Server 2012 ist diese Prozedur aus Rückwärtskompatibilitätsgründen noch vorhanden, jedoch wurde dieser Check aus dem Code entfernt. Damit verhält sie sich in dieser Hinsicht somit wie der direkte Aufruf von ALTER SERVER ROLE {RoleName} ADD MEMBER {Loginname}.

Das gleiche gilt für sp_addrolemember / sp_droprolemember für Datenbankrollen.

Okay.
Of course we can go round this code by calling xp_readerrorlog directly.

This does not help in the GUI-presentation in Management Studio but we can use it as a manual workaround.

Among other system procedures that are called via SSMS and refuse execution are:
sp_addumpdevice - for backup-devices
sp_enum_oledb_providers – is used for viewing and configuring Linked Servers.

sp_addlinkedserver on the other hand can be executed without problems – just not via the GUI because of the just mentioned procedure.

Setting up Database-Mail via the GUI is also reserved for sysadmins. It should work via script though (untested).

Also the configuration of the distributor for replication by means of sp_adddistributor is not possible without the sysadmin bit.
Other replication tasks are partially possible even via the GUI.

Under SQL Server 2005 – 2008R2, to add/remove (server) role members, solely the system procedure sp_addsrvrolemember / sp_dropsrvrolemember exists. This one also conducts a server-role-membership-check. - Under SQL Server 2012 this procedure still exists for backwards-compatibility reasons, but this specific check has been removed from the code. Thereby it now behaves like the direct call of ALTER SERVER ROLE {RoleName} ADD MEMBER {Loginname}.

Same applies to sp_addrolemember / sp_droprolemember for database roles.

 

Soweit zu Systemprozeduren. Eigentlich ziemlich simpel, wenn man die Hintergründe kennt.

Daher, wo möglich: DDL-Kommandos verwenden, wie seit SQL Server 2005 nahegelegt wird.

Randnotiz: Es gibt mindestens 7 Variationen der Prüfung auf sysadmin-Mitgliedschaft. :-) :-(

Eine Kostprobe:

So much for system stored procedures. Quite simple after all, if you know the background.

Therefore, wherever possible: use DDL-commands, as it is advised since SQL Server 2005.

Side-note: there are at least 7 variations for the check of sysadmin-membership. :-) :-(

A taster:

IF IS_SRVROLEMEMBER('sysadmin') != 1
IF
is_srvrolemember('securityadmin') = 0
IF
(is_srvrolemember('sysadmin') <> 1)
IF
(is_srvrolemember(N'sysadmin') <> 1 )
IF
(not is_srvrolemember(N'sysadmin') = 1)
IF
(ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0)
IF
isnull(is_srvrolemember('sysadmin'),0) = 1

Die häufigsten Fehlermeldungen, die dann ggfls. ausgelöst werden, sind:

The most frequent error messages which are triggered if applicable are:

EN:

message_id

text

14126

You do not have the required permissions to complete the operation.

14260

You do not have sufficient permission to run this command. Contact your system administrator.

15003

Only members of the %s role can execute this stored procedure.

15247

User does not have permission to perform this action.

21089

Only members of the sysadmin fixed server role can perform this operation.

22904

Caller is not authorized to initiate the requested action. DBO privileges are required.

DE:

message_id

text

14126

Sie haben nicht die erforderlichen Berechtigungen, um den Vorgang abzuschließen.

14260

Sie haben nicht die erforderliche Berechtigung, um diesen Befehl auszuführen. Wenden Sie sich an den Systemadministrator.

15003

Nur Mitglieder der %1!-Rolle können diese gespeicherte Prozedur ausführen.

15247

Der Benutzer besitzt nicht die Berechtigung zum Ausführen dieser Aktion.

21089

Nur Mitglieder der festen Serverrolle 'sysadmin' können diesen Vorgang ausführen.

22904

Der Aufrufer ist nicht zum Initiieren der angeforderten Aktion berechtigt. Es sind DBO-Privilegien erforderlich.


Eine vollständige Liste aller Prozeduren, die auf sysadmin-Rollenmitgliedschaft prüfen, folgt am Ende.

A complete list of procedures that check for sysadmin-membership is included at the end of this post.


Kommen wir zu einem anderen wichtigen Bereich:

DBCC-Kommandos

Let’s come to another important area:

DBCC commands

DBCC CHECKDB

-->

Msg 7983, Level 14, State 36, Line 1
User 'public' does not have permission to run DBCC checkdb for database 'master'.

Das geht ja gut los.

Die „Regel“ ist bei DBCC noch einfacher:
Fast jedes DBCC-Kommando prüft auf sysadmin.

Von DBCC CHECKDB über DBCC LOGINFO bis zu DBCC TRACEON. Also auch durchaus wertvolle Kommandos auch für den externen Support.
- Tatsächlich ist selbst DBCC HELP nur für sysadmins zugelassen...

Die einzigen Ausnahmen, die mir bekannt sind:
DBCC SHOW_STATISTICS

  • man muss jedoch mindestens ddl_admin oder Besitzer der Tabelle sein

DBCC DETACHDB

  • das ist ein spezieller Fall, da es über sp_detach_db ausgeführt wird
  • db_owner oder dbo der datenbank ist ausreichend

DBCC FREEPROCCACHE und DBCC SQLPERF

  • Diese setzen lediglich die ALTER SERVER STATE Berechtigung voraus.

DBCC DROPCLEANBUFFERS wiederum setzt die sysadmin-Rollenmitgliedschaft voraus.

Diese Berechtigungen sind übrigens recht gut dokumentiert.

That’s a good start, isn’t it..

The „rule“ for DBCC is even simpler:
Almost every DBCC-command checks for sysadmin.

From DBCC CHECKDB via DBCC LOGINFO to DBCC TRACEON. Thus some quite valuable commands also for external support.
- In fact even DBCC HELP is only allowed for sysadmins...

The only exceptions known to me are:
DBCC SHOW_STATISTICS

  • one needs to be at least ddl_admin or owner of the table

DBCC DETACHDB

  • this is a special case, since it's executed via sp_detach_db
  • db_owner or dbo of the database is sufficient

DBCC FREEPROCCACHE and DBCC SQLPERF

  • Those require only the ALTER SERVER STATE permission.

DBCC DROPCLEANBUFFERS on the other hand requires sysadmin-role membership.

Those permissions are documented quite well by the way.

 

Datenbankberechtigungen

Mit CONTROL SERVER hat ein Prinzipal auch vollen Zugriff auf alle Datenbanken.
Fast, aber auch nur fast wie sysadmins, die bekanntlich auf den „dbo“ gemappt werden.

Logins mit lediglich CONTROL SERVER-Berechtigung werden nicht(!) zu dbo gemapped.

Welche Auswirkungen das hat, sieht man im Folgenden:

Database permissions

With CONTROL SERVER, a principal has full access to all databases.
Almost, but only almost like sysadmins, which are, as is well-known, mapped to “dbo”.

Logins with merely CONTROL SERVER permission are not(!) mapped to dbo.

The consequences of this can be seen in the following:

USE ControlServer_Schema_Demo
GO

SELECT USER_NAME()

-->

DBA_TheDude

CREATE TABLE dbo.DemoTable1_dbo(id int)
GO

CREATE TABLE DemoTable2_NoSchemaSpecified(id int)
GO

SELECT name, schema_id FROM sys.tables
SELECT
* FROM sys.schemas

-->

Control_Server_Table_Schema

-->
Control_Server_Schema

SSMS:

Control Server Table Schema SSMS

Control_Server_Schema_SSMS

Was ist passiert?

Erinnern Sie sich noch an das pre-SQL 2012 Problem, das man Windows-Gruppen kein Default Schema zuweisen konnte? Und was passierte, wenn ein Entwickler über solch eine Gruppe vergaß, beim Anlegen eines Objektes das Schema anzugeben?

Richtig. Das ist genau das gleiche: es wurde ein Schema mit dem Login-Namen des Entwicklern angelegt. Eine reine Freude für spätere Aufräumarbeiten, die „richtigen falschen“ Schemas zu identifizieren und zu löschen.
Dieses Issue (eines der am höchsten votierten
Connect-Items) wurde mit SQL Server 2012 ja gelöst.

Leider wurde dabei verpasst, auch die Behandlung von CONTROL SERVER Berechtigten anzupassen. Dazu hatte ich ebenfalls ein Connect-Item erstellt.: „Login with CONTROL SERVER Permission Creating an Object without specifying Schema leads to creation of new Schema with Login-Name”. - Leider zu spät. :-/

Vermutlich wird dazu ein identischer Code-Block verwendet, denn genau wie in dem Windows-Gruppen-Szenario ist dieses implizite Anlegen des Schemas nicht abfangbar.

Fazit: Immer ein Schema angeben, wenn man als CONTROL Server Berechtigter Objekte anlegt – am besten einfach wirklich immer ein Schema angeben (es gibt noch andere Gründe dafür).

What happened?

Do you remember the pre-SQL 2012 problem, that windows groups could not be assigned a default schema? And what happened if a developer forgot to specify a schema when creating an object?

Right. This is exactly the same: a schema with the Login-Name of the developer has been created. A true joy for later clean-up, to identify and drop the „right wrong” schemas.
This Issue (one of the most voted
Connect-Items
) has been resolved with SQL Server 2012.

Unfortunately the handling of the CONTROL SERVER permission has been overlooked to be fixed. I did create a connect item:Login with CONTROL SERVER Permission Creating an Object without specifying Schema leads to creation of new Schema with Login-Name”. – Unfortunately too late. :-/

Probably an identical code-block is being used for that, since just like in the Windows-Group scenario, this implicit creation of the schema is uncatchable.

Conclusion: Always specify a schema when creating an object as a CONTROL SERVER granted principal – best: always specify a schema. (there are other reasons for that, too)

 

Privilege-Escalation-Risiko:

Abschließen möchte ich mit einem sicherheitstechnisch extrem wichtigen Hinweis:

Logins mit CONTROL SERVER Berechtigung können standardmäßig JEDEN Login impersonifizieren. JEDEN. Also auch alle Sysadmins und sa selber! – Und auch wenn SQL Authentifizierung nicht aktiv ist!

Und so lässt sich das wunderbar ausnutzen:

Privilege-Escalation-risc:

I want to wind up with a security-wise extremely important hint:

Logins with CONTROL SERVER permission can impersonate EVERY Login. ALL OF THEM. Thus also all sysadmins and sa itself! – And even if SQL authentication is not active!

And this is how this can be exploited marvellously:

ALTER SERVER ROLE sysadmin
ADD MEMBER DBA_TheDude

--> No

EXEC sp_addsrvrolemember'DBA_TheDude', 'sysadmin';

--> No

EXECUTE AS LOGIN = 'sa';

ALTER SERVER ROLE sysadmin
ADD MEMBER DBA_TheDude

--> “Thank you”

REVERT;

-->

Control_Server_sysadmin_escalation

Wer sich also gegenüber dieser Form von Privilege-Escalation schützen möchte, muss das impersonate (mithilfe von DENY) verbieten.
- Und warum sollte man das nicht wollen, würde es doch ggfl. das gesamte Konzept von CONTROL SERVER in Frage stellen (?! ) -
Denn das ist der finale und entscheidende Unterschied:

Sysadmin-Mitglieder können nicht mit DENY eingeschränkt werden. Prinzipale mit bloßer CONTROL SERVER Berechtigung jedoch schon.

So funktionieren alle reinen DDL/DML Kommando-Berechtigungen eben.

Also, um es noch einmal klar zu sagen, da es so entscheidend ist:
Ein Login mit CONTROL SERVER Recht macht nur dann Sinn, wenn ihm gleichzeitig verboten wird, andere sysadmins (oder am besten: alle Logins) zu impersonifizieren. Andernfalls kann man ihn gleich zum sysadmin machen!

Dummerweise geht das nur über "DENY IMPERSONATE ON LOGIN::[Loginname]". Denn IMPERSONATE ist hierarchisch direkt CONTROL SERVER untergeordnet!

Who wants to protect himself from this form of privilege escalation must DENY impersonating.
- And why would you not want to do that since this eventually would put the whole concept of CONTROL SERVER in question (?!) -
Because this is the final and crucial difference:

Sysadmin-members cannot be restricted anything via DENY. Principals with mere CONTROL SERVER permissions yet can.

This is how all plain DDL/DML commands work.

So, to say it clearly again, because this is vital:
A Login with CONTROL SERVER Permission only makes sense, when at the same time it is explicitely denied impersonation of any sysadmin (or better: any Logins). Otherwise you may as well just make him sysadmin right away!

Unfortunately this only works via "DENY IMPERSONATE ON LOGIN::[Loginname]". This is because IMPERSONATE is hierarchically a direct subordinate of CONTROL SERVER!

USE master

DENY IMPERSONATE ON LOGIN::sa TO [DBA_TheDude]

 

Bei einer sich ändernden Liste an Systemadministratoren hat man ein Problem, wenn man nicht an dieses Deny denkt! (Nächstes Risiko!)

- Spätestens an dieser Stelle sollte man sich mit dem Überwachungs-Feature von SQL Server befassen.

For a changing list of system administrators one has a real problem, in case of not remembering this crucial Deny! (Next risk!)

- At the latest at this point one should address the Auditing feature of SQL Server.


Mein Fazit und Lessons-learned daher:

CONTROL-SERVER selber ist eine konsequente Fortführung der Bemühungen des Sicherheits-Teams, SQL Server sicherheitstechnisch noch einfacher und damit robuster zu machen.

Jedoch ist aus dem Grund der Impersonate-Rechte eine Privilege Escalation zu sysadmin sehr einfach. Um diese zu verhindern, sollte man gut mit der Berechtigungs-Hierarchie von SQL Server vertraut sein. – Wie immer: „Wissen schafft Sicherheit.“

Was wirklich schmerzt, ist, das eines der besten Anwendungsszenarien: Rechte für Support-Personal, intern oder Extern.
Das Fehlen der Möglichkeit, DBCC-Kommandos direkt zu berechtigen, macht uns hier einen Strich durch die Rechnung. Wenn man nicht jedes wichtige DBCC-Kommando in eine eigene Prozedur wrappen und somit berechtigen möchte, führt am sysadmin in diesen Anwendungsfällen nichts vorbei. (!)

Im Endeffekt ist eine strikte „Separation of Duties“, die Funktionstrennung auf verschiedene „Rollen“ das eherne Ziel.

Hier kann man dazu Nachlesen – auch das „SQL Server Separation of Duties Framework“ von codeplex, mit vielen guten Ideen kann ich empfehlen einmal anzusehen:

My conclusion and lessions-learned therefore are:

CONTROL SERVER itself is a consistent continuation of the efforts of the security team to make SQL Server even simpler and thereby more robust.

Because of the impersonate-permissions, a privilege escalation is really simple. In order to prevent this, one should be familiar with the permission hierarchy of SQL Server. – As always: “Knowledge leads to security.”

What really does hurt, is one of the best application cases: Permissions for support-personnel, internal or external.
The missing possibility to grant permissions to DBCC directy throws a monkey wrench in our plans. If one does not want to create a procedure as wrapper for every important DBCC command, there is no way around sysadmin in those scenarios. (!)

In the end, a strict “separation of duties” is the iron goal.

Here you can read more about it – you should also check out the “SQL Server Separation of Duties Framework” on codeplex with many good ideas:

http://blogs.technet.com/b/fort_sql/archive/2011/09/12/separation-of-duties-for-dba-s.aspx

Update 04-2014:

Mit SQL Server 2014 wird CONTROL Server etwas sicherer. Hier kann man mehr zu den neuen Möglichkeiten lesen:

New Permissions in SQL Server 2014: IMPERSONATE ANY LOGIN, SELECT ALL USER SECURABLES, CONNECT ANY DATABASE and the old CONTROL SERVER

Update 04-2014:

With SQL Server 2014 CONTROL Server becomes a bit safer. You can read more on the new possibilities here:

New Permissions in SQL Server 2014: IMPERSONATE ANY LOGIN, SELECT ALL USER SECURABLES, CONNECT ANY DATABASE and the old CONTROL SERVER

Eine Ablösung des „sa" ist übrigens nicht geplant, jedoch sinkt mit jedem Release die Anzahl der Szenarien, wo sa/sysadmin zwingend benötigt wird.

A displacement of „sa“ is not planned by the way, but with every release the scenarios where sa/sysadmin is imperatively needed become less.

 
 

Happy securing,

Andreas

 

Anbei die komplette Liste aller Systemprozeduren unter SQL Server 2012, die auf sysadmin-Rollenmitgliedschaft prüfen (171 – gegenüber 173 unter SQL Server 2008R2. SQL Server 2014 CTP1 ist noch das Gleiche):

(Hinweis: Insgesamt 197 Systemprozeduren prüfen auf Serverrollenmitgliedschaft, wie diskadmin oder serveradmin usw.)

Enclosed the list of all system procedures under SQL Server 2012 that check for sysadmin-role membership (171 – vs. 171 under SQL server 2008. SQL Server 2014 CTP 1 still the same):

(Hint: Altogether 197 system procedures check for server role membership like diskadmin or serveradmin and so on)


Module_Name

fn_yukonsecuritymodelrequired

sp_add_agent_parameter

sp_add_agent_profile

sp_adddatatype

sp_adddistributiondb

sp_adddistributor

sp_addqreader_agent

sp_addsubscriber

sp_addsubscriber_schedule

sp_addtabletocontents

sp_attachsubscription

sp_cdc_cleanup_change_table

sp_cdc_disable_db

sp_cdc_disable_table

sp_cdc_drop_job

sp_cdc_enable_db

sp_cdc_enable_table

sp_cdc_restoredb

sp_cdc_vupgrade

sp_certify_removable

sp_change_agent_parameter

sp_change_agent_profile

sp_change_subscription_properties

sp_change_users_login

sp_changedistpublisher

sp_changedistributiondb

sp_changedistributor_password

sp_changedistributor_property

sp_changemergesubscription

sp_changeqreader_agent

sp_changereplicationserverpasswords

sp_changesubscriptiondtsinfo

sp_checkinvalidivarticle

sp_copysubscription

sp_create_removable

sp_cycle_errorlog

sp_dbcmptlevel

sp_dbmmonitoraddmonitoring

sp_dbmmonitorchangealert

sp_dbmmonitordropalert

sp_dbmmonitordropmonitoring

sp_dbmmonitorhelpalert

sp_dbmmonitorhelpmonitoring

sp_dbmmonitorresults

sp_dbmmonitorupdate

sp_dbremove

sp_drop_agent_parameter

sp_drop_agent_profile

sp_dropdatatypemapping

sp_dropdistpublisher

sp_dropdistributiondb

sp_dropdistributor

sp_dropmergepullsubscription

sp_droppullsubscription

sp_dropsubscriber

sp_dsninfo

sp_enumdsn

sp_flush_commit_table_on_demand

sp_generate_agent_parameter

sp_get_distributor

sp_get_Oracle_publisher_metadata

sp_getagentparameterlist

sp_getdefaultdatatypemapping

sp_grant_publication_access

sp_help_agent_default

sp_help_agent_parameter

sp_help_agent_profile

sp_helpdistpublisher

sp_helpdistributor

sp_helpmergesubscription

sp_helpqreader_agent

sp_helpreplicationdboption

sp_identitycolumnforreplication

sp_IHValidateRowFilter

sp_IHXactSetJob

sp_link_publication

sp_monitor

sp_MSadd_distribution_agent

sp_MSadd_logreader_agent

sp_MSadd_merge_agent

sp_MSadd_snapshot_agent

sp_MSadd_subscriber_schedule

sp_MSadd_tracer_history

sp_MSadd_tracer_token

sp_MScdc_cleanup_job

sp_MScdc_db_ddl_event

sp_MScdc_ddl_event

sp_MSchange_distribution_agent_properties

sp_MSchange_logreader_agent_properties

sp_MSchange_merge_agent_properties

sp_MSchange_snapshot_agent_properties

sp_MSchangedynamicsnapshotjobatdistributor

sp_MSchangedynsnaplocationatdistributor

sp_MScheck_pull_access

sp_MScleanupmergepublisher_internal

sp_MSclear_dynamic_snapshot_location

sp_MScreate_dist_tables

sp_MSdbuserpriv

sp_MSdeletefoldercontents

sp_MSdrop_6x_replication_agent

sp_MSdrop_merge_agent

sp_MSdrop_snapshot_dirs

sp_MSdropmergedynamicsnapshotjob

sp_MSdynamicsnapshotjobexistsatdistributor

sp_MSenumallpublications

sp_MSfetchAdjustidentityrange

sp_MSfix_6x_tasks

sp_MSforce_drop_distribution_jobs

sp_MSget_agent_names

sp_MSget_jobstate

sp_MSget_oledbinfo

sp_MSget_publication_from_taskname

sp_MSgetdbversion

sp_MSgetmaxsnapshottimestamp

sp_MShelp_repl_agent

sp_MShelp_replication_status

sp_MShelp_snapshot_agent

sp_MShelpconflictpublications

sp_MShelpdynamicsnapshotjobatdistributor

sp_MShelplogreader_agent

sp_MShelpsnapshot_agent

sp_MShelptranconflictcounts

sp_MSinit_publication_access

sp_MSreinit_failed_subscriptions

sp_MSremoveoffloadparameter

sp_MSrepl_backup_complete

sp_MSrepl_backup_start

sp_MSrepl_createdatatypemappings

sp_MSrepl_dropdatatypemappings

sp_MSrepl_enumarticlecolumninfo

sp_MSrepl_enumpublications

sp_MSrepl_enumpublishertables

sp_MSrepl_enumsubscriptions

sp_MSrepl_enumtablecolumninfo

sp_MSrepl_getdistributorinfo

sp_MSrepl_startup_internal

sp_MSreplagentjobexists

sp_MSreplcheck_permission

sp_MSreplcheck_pull

sp_MSreplcheck_subscribe

sp_MSreplcheck_subscribe_withddladmin

sp_MSreplcopyscriptfile

sp_MSreplremoveuncdir

sp_MSsetalertinfo

sp_MSSetServerProperties

sp_MSsetupnosyncsubwithlsnatdist

sp_MSsetupnosyncsubwithlsnatdist_cleanup

sp_MSsetupnosyncsubwithlsnatdist_helper

sp_MSstartdistribution_agent

sp_MSstartmerge_agent

sp_MSstartsnapshot_agent

sp_MSstopdistribution_agent

sp_MSstopmerge_agent

sp_MSstopsnapshot_agent

sp_MSupdate_agenttype_default

sp_oledbinfo

sp_procoption

sp_removedbreplication

sp_removesrvreplication

sp_replication_agent_checkup

sp_replicationdboption

sp_resetstatus

sp_restoredbreplication

sp_SetAutoSAPasswordAndDisable

sp_setdefaultdatatypemapping

sp_updatestats

sp_validatelogins

sp_vupgrade_mergeobjects

sp_vupgrade_replication

sp_vupgrade_replsecurity_metadata

xp_repl_convert_encrypt_sysadmin_wrapper

1 2