5 Security-Todsünden in der Softwareentwicklung
Dirk PrimbsDeveloper EvangelistMicrosoft Deutschland [email protected]://blogs.msdn.com/dirkpr
Agenda 5 Sünden Demos Fazit
IT-SicherheitIT-Sicherheit
Richtlinien, Verfahren und Bewusstsein
Richtlinien, Verfahren und Bewusstsein
Betriebssystemhärtung,Betriebssystemhärtung, Authentifizierung, Authentifizierung, Patchverwaltung, HIDSPatchverwaltung, HIDS
Firewalls,Firewalls, VPN-VPN-QuarantäneQuarantäneSicherheitskräfte,Sicherheitskräfte, Schlösser,Schlösser, ÜberwachungsgeräteÜberwachungsgeräte
Netzwerksegmente,Netzwerksegmente, IPSec,IPSec, NIDSNIDS
AnwendungshärtunAnwendungshärtung,g, AntivirussoftwareAntivirussoftware
ACL,ACL, VerschlüsselungVerschlüsselung
BenutzerschulunBenutzerschulungg
Physische SicherheitPhysische Sicherheit
PerimeterPerimeter
Internes NetzwerkInternes Netzwerk
HostHost
AnwendungAnwendung
DatenDaten
Spot the security bug
error_status_t _RemoteActivation(WCHAR *pwszObjectName, ... ) { *phr = GetServerPath(pwszObjectName, &pwszObjectName); …}HRESULT GetServerPath(WCHAR *pwszPath, WCHAR **pwszServerPath ){ WCHAR * pwszFinalPath = pwszPath; WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH_FQDN + 1]; hr = GetMachineName(pwszPath, wszMachineName); *pwszServerPath = pwszFinalPath;}HRESULT GetMachineName( WCHAR * pwszPath, WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH_FQDN + 1]) { pwszServerName = wszMachineName; LPWSTR pwszTemp = pwszPath + 2; while ( *pwszTemp != L'\\' ) *pwszServerName++ = *pwszTemp++; !!!
Port 135 (Z.B. aus dem Internet)Port 135 (Z.B. aus dem Internet)
Sünde #1: Der Buffer Overrun
Buffer Overrun: Das Prinzip [1]
void main() { char myLongBuffer[256]; myFunction(myBuffer);}
void myFunction(char *myString) { char myShortBuffer[16]; strcpy(myShortBuffer, myString); }
Was passiert, wenn der übergebene String größer als 16 Zeichen ist?
Was passiert, wenn der übergebene String größer als 16 Zeichen ist?
Buffer Overrun: Das Prinzip [2] void main() { char myLongBuffer[256]; myFunction(myLongBuffer);}
StackStack
(bisheriger Stackinhalt)
256MyLongBuffer
Rücksprungadresse
Sonstige Daten
MyShortBuffer 16 Str
ing
sStr
ing
s
void myFunction(char *myString) { char myShortBuffer[16]; strcpy(myShortBuffer, myString); }
Daten sind zu lang !
MyShortBuffer 16256
MyShortBuffer
Gehackte Adresse
Gehackte AdresseViruscode
„Böser“ Inhalt von MyShortBuffer:
Rücksprung an gehackte Adresse…
Virus a
usführen
Virus a
usführen
Sta
ckSta
ck
Ein erprobter Ansatz
Quelle: West Virginia Office of Miners’ Health, Safety and Quelle: West Virginia Office of Miners’ Health, Safety and Training Training
Bergarbeiter mit Kanarienvogel (Welsh Miner‘s Canary)
Prinzip:Vogel tot =zuviel Methangas
Maßnahmen gegen BOs Bestimmte C/C++ Kommandos sind besonders
anfällig strcpy, gets, scanf, sprintf, strcat, …
BOs werden in Managed Code durch Laufzeitchecks verhindert.
Compilerswitch /GS aktiviert in Visual C/C++ verbessertes Stackhandling
Static Analysis mit Prefast
Compilerswitch /GSStackStack
(bisheriger Stackinhalt)
256MyLongBuffer
Rücksprungadresse
Security Cookie
Str
ing
sStr
ing
s
MyShortBuffer
Sta
ckSta
ck
Prolog: Alloziiert Speicher auf dem Stack für lokale Variablen
sub esp,20h
Epilog: Führt Rücksprung durch
add esp,20h ret
void myFunction(char *myString) { char myShortBuffer[16]; strcpy(myShortBuffer, myString); }
Prolog: Alloziiert Speicher auf dem Stack für lokale Variablen und speichert Zufallswert für Security Cookie (Canary) absub esp,24h mov eax,dword ptr [___security_cookie (408040h)] xor eax,dword ptr [esp+24h] mov dword ptr [esp+20h],eax Epilog: Prüft den Security Cookie (Canary) und führt anchließend Rücksprung durch mov ecx,dword ptr [esp+20h] xor ecx,dword ptr [esp+24h] add esp,24h jmp __security_check_cookie (4010B2h)
MyShortBuffer 16
Spot the security bug
void LookupPath(string computer, string path)void LookupPath(string computer, string path){{
const int max_size = 63;const int max_size = 63;byte len = (byte)(computer.Length + path.Length);byte len = (byte)(computer.Length + path.Length);
if (len > max_size) throw new SecurityException("Pfad zu lang!");if (len > max_size) throw new SecurityException("Pfad zu lang!");// irgendwas sinnvolles// irgendwas sinnvolles
}}
Sünde #2: Integer Overflow
Das Prinzip [1] Implizite und explizite Casts können
Werte unerwartet verändern In jeder gebräuchlichen
Programmiersprache finden sich derartige Überläufe
vorzeichenbehaftete Datentypen sind hauptsächlich anfällig
Das Prinzip [2] Vorzeichenbehaftete Datentypen
nutzen das erste Bit als Vorzeichen Beim Cast von unsignierte auf
signierte Datentypen ändert sich so die Bedeutung des Datums
Beim Upcast wird das oberste Bit um ein Vorzeichenbit erweitert
Demo: Arithmetic Overflows
Spot the security bug
CREATE PROCEDURE dbo.doQuery(@id nvarchar(128))CREATE PROCEDURE dbo.doQuery(@id nvarchar(128))ASAS DECLARE @query nchar(256)DECLARE @query nchar(256) SELECT @query=‚select ccnum from cust where id=‘‘‘ + @id + ‘‘‘‘SELECT @query=‚select ccnum from cust where id=‘‘‘ + @id + ‘‘‘‘ EXEC @queryEXEC @queryRETURNRETURN
Sünde #3: Command Injection
Das Prinzip Durch geschickte Wahl von
Benutzereingaben den Sinn damit arbeitender Operationen verändern
Prominente Vertreter: SQL Injection Format String Probleme Cross Site Scripting
Demo: Command Injection
Spot the security Bug
string status = "No";string status = "No";string sqlstring = "";string sqlstring = "";
try {try { // SQL Zugriffscode// SQL Zugriffscode} catch (SqlException se) {} catch (SqlException se) { Status = sqlstring + " failed\r\n";Status = sqlstring + " failed\r\n"; foreach (SqlError e in se.Errors)foreach (SqlError e in se.Errors) Status += e.Message + "\r\n";Status += e.Message + "\r\n";}}
if (Status.CompareTo("No") != 0) {if (Status.CompareTo("No") != 0) { Response.WriteLine(Status);Response.WriteLine(Status);}}
Sünde #4: Information Leakage
Lösung...try {try { // SQL Zugriffscode// SQL Zugriffscode} catch (SqlException se) {} catch (SqlException se) { Status = sqlstring + " failed\r\n";Status = sqlstring + " failed\r\n"; foreach (SqlError e in se.Errors)foreach (SqlError e in se.Errors) Status += e.Message + "\r\n";Status += e.Message + "\r\n";
WindowsIdentity user = WindowsIdentity.GetCurrent();WindowsIdentity user = WindowsIdentity.GetCurrent(); WindowsPrincipal prin = new WindowsPrincipal(user);WindowsPrincipal prin = new WindowsPrincipal(user);
if (prin.IsInRole(WindowsBuiltInRole.Administrator)) if (prin.IsInRole(WindowsBuiltInRole.Administrator)) Response.WriteLine(Status);Response.WriteLine(Status); else {else { Response.Write("An error occurred, please bug your admin");Response.Write("An error occurred, please bug your admin"); EventLog.WriteEntry("SqlApp", Status, EventLogEntryType.Error);EventLog.WriteEntry("SqlApp", Status, EventLogEntryType.Error); }}
}}
Das Problem Dem Nutzer wird zu viel Information
präsentiert Versehentlich => z.B. Fehlermeldungen Absichtlich => Nutzerdaten
Warum ist das problematisch? Hacker können zusätzliche
Informationen erlangen die Angriffe erleichtern!
Datenschutz!
TMI – Too Much Information Benutzername oder Paßwort falsch? Versionsinformationen verwendeter
Software IP-Adressen, MAC-Adressen, etc... Pfade Genaue Fehlermeldungen
Abhilfe? Informationen zur Fehlersuche an
vertrauenswürdiger Stelle ablegen EventLog Ggf. Geeignet abgesichertes Logfile
Informationen nur an Administratoren ausgeben
Spot the security bug
Sünde #5: Schlechte Bedienbarkeit
Spot the security bug
Salopp übersetzt: Klick‘ „Ja“, und alles geht, klick‘ „Nein“ und Du hast nur Ärger mit der Seite
Zusammenfassung Viele Sicherheitsprobleme lassen sich
einfach verhindern Kein Vertrauen in Eingabedaten! Schon während der Planung mögliche
Angriffsszenarien berücksichtigen Das Gesamtsystem ist immer so
sicher wie sein schwächstes Glied
Weitere Informationen 19 Deadly Sins Of Software Security
ISBN 0-07-226085-8 Microsoft Security Developer Center
http://msdn.microsoft.com/security/
Fragen?