“walk in” slide. august 14-15 2006 hardening the box: xbox 360 and windows vista security...

Download “WALK IN” SLIDE. August 14-15 2006 Hardening the Box: Xbox 360 and Windows Vista Security Michael Howard Software Security Guy Microsoft Corp

If you can't read please download the document

Upload: delilah-lloyd

Post on 18-Jan-2018

221 views

Category:

Documents


0 download

DESCRIPTION

August Agenda

TRANSCRIPT

WALK IN SLIDE August Hardening the Box: Xbox 360 and Windows Vista Security Michael Howard Software Security Guy Microsoft Corp. August Agenda Securing software requires: Good design Writing more secure code in the first place Prohibiting banned functionality Static analysis tools Security testing Reducing attack surface A good base of defenses August A Sample Scenario An imaginary game server Runs as SYSTEM Enumerates and hashes saved games to send to the user Saved game file name comes from a valid user over UDP In some code examples, error checking is removed for brevity August Startup() EnumAndHashFiles() GetFileFromUser() HashOneFile() AddFileDataToList() SYSTEM 30,000 ft. View of the Code UDP Gimme da saved game August ServiceMain() Startup() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() VOID WINAPI Startup(DWORD dwArgc,LPTSTR* lpszArgv) { // Initialization code // Setup threads // Create UDP listener while (true) { // Get directory from user over RPC wchar_t *wszDir = GetDirFromUser(); EnumAndHashFiles(wszDir); } August ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() ServiceMain() VOID WINAPI Startup(DWORD dwArgc,LPTSTR* lpszArgv) { // Initialization code // Setup threads // Create UDP listener while (true) { // Get directory from user over RPC wchar_t *wszDir = GetDirFromUser(); EnumAndHashFiles(wszDir); } Run as network service August ServiceMain() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR* lpszArgv) { // Initialization code // Setup threads // Create UDP listener HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); LPCWSTR wszPrivs [] = { SE_TAKE_OWNERSHIP_NAME, SE_DEBUG_NAME, SE_CREATE_TOKEN_NAME, SE_ASSIGNPRIMARYTOKEN_NAME, SE_TCB_NAME, SE_SECURITY_NAME, SE_LOAD_DRIVER_NAME, SE_SYSTEMTIME_NAME, SE_BACKUP_NAME, SE_RESTORE_NAME, SE_SHUTDOWN_NAME, SE_AUDIT_NAME}; DropUnusedPrivs(wszPrivs,_countof(wszPrivs)); while (true) { // Get directory from user over RPC wchar_t *wszDir = GetDirFromUser(); EnumAndHashFiles(wszDir); } Terminate if a heap overflow occurs Drop unneeded privileges August EnumAndHashFiles() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool EnumAndHashFiles(wchar_t *wszPath) { bool fRet = false; wchar_t wszPath2[128]; wcscpy(wszPath2,(wchar_t*)wszPath); wcscat(wszPath2,L"\\*.*"); if (!CryptAcquireContext(&g_hProv, NULL,NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return false; WIN32_FIND_DATA ffd; HANDLE h = FindFirstFile(wszPath2,&ffd); while (h != INVALID_HANDLE_VALUE) { wchar_t wszFilename[MAX_PATH]; _snwprintf(wszFilename, sizeof(wszFilename), L"%s\\%s", wszPath,ffd.cFileName); HashOneFile(wszFilename); if (!FindNextFile(h,&ffd)) break; } CryptReleaseContext(g_hProv,0); FindClose(h); return fRet; } August EnumAndHashFiles() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool EnumAndHashFiles(__in_z wchar_t *wszPath) { bool fRet = false; wchar_t wszPath2[128]; wcscpy(wszPath2,(wchar_t*)wszPath); wcscat(wszPath2,L"\\*.*"); if (!CryptAcquireContext(&g_hProv, NULL,NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return false; WIN32_FIND_DATA ffd; HANDLE h = FindFirstFile(wszPath2,&ffd); while (h != INVALID_HANDLE_VALUE) { wchar_t wszFilename[MAX_PATH]; _snwprintf(wszFilename, sizeof(wszFilename), L"%s\\%s", wszPath,ffd.cFileName); HashOneFile(wszFilename); if (!FindNextFile(h,&ffd)) break; } CryptReleaseContext(g_hProv,0); FindClose(h); return fRet; } Add SAL annotation to detect bugs August EnumAndHashFiles() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool EnumAndHashFiles(__in_z wchar_t *wszPath) { bool fRet = false; wchar_t wszPath2[128]; wcscpy_s(wszPath2,__countof(wszPath2),(wchar_t*)wszPath); wcscat_s(wszPath2,__countof(wszPath2),L"\\*.*"); if (!CryptAcquireContext(&g_hProv, NULL,NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return false; WIN32_FIND_DATA ffd; HANDLE h = FindFirstFile(wszPath2,&ffd); while (h != INVALID_HANDLE_VALUE) { wchar_t wszFilename[MAX_PATH]; swprintf_s(wszFilename, sizeof(wszFilename), L"%s\\%s", wszPath,ffd.cFileName); HashOneFile(wszFilename); if (!FindNextFile(h,&ffd)) break; } CryptReleaseContext(g_hProv,0); FindClose(h); return fRet; } Add SAL annotation to detect bugs Replace Banned APIs August EnumAndHashFiles() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool EnumAndHashFiles(__in_z wchar_t *wszPath) { bool fRet = false; wchar_t wszPath2[128]; wcscpy_s(wszPath2,__countof(wszPath2),(wchar_t*)wszPath); wcscat_s(wszPath2,__countof(wszPath2),L"\\*.*"); if (!CryptAcquireContext(&g_hProv, NULL,NULL, GetCryptoProvider(), CRYPT_VERIFYCONTEXT)) return false; WIN32_FIND_DATA ffd; HANDLE h = FindFirstFile(wszPath2,&ffd); while (h != INVALID_HANDLE_VALUE) { wchar_t wszFilename[MAX_PATH]; swprintf_s(wszFilename, sizeof(wszFilename), L"%s\\%s", wszPath,ffd.cFileName); HashOneFile(wszFilename); if (!FindNextFile(h,&ffd)) break; } CryptReleaseContext(g_hProv,0); FindClose(h); return fRet; } Add SAL annotation to detect bugs Replace Banned APIs Crypto Agility Get crypto provider from configuration August EnumAndHashFiles() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool EnumAndHashFiles(__in_z wchar_t *wszPath) { bool fRet = false; wchar_t wszPath2[128]; wcscpy_s(wszPath2,__countof(wszPath2),(wchar_t*)wszPath); wcscat_s(wszPath2,__countof(wszPath2),L"\\*.*"); if (!CryptAcquireContext(&g_hProv, NULL,NULL, GetCryptoProvider(), CRYPT_VERIFYCONTEXT)) return false; WIN32_FIND_DATA ffd; HANDLE h = FindFirstFile(wszPath2,&ffd); while (h != INVALID_HANDLE_VALUE) { wchar_t wszFilename[MAX_PATH]; swprintf_s(wszFilename, __countof(wszFilename), L"%s\\%s", wszPath,ffd.cFileName); HashOneFile(wszFilename); if (!FindNextFile(h,&ffd)) break; } CryptReleaseContext(g_hProv,0); FindClose(h); return fRet; } Add SAL annotation to detect bugs Replace Banned APIs Static Analysis: Byte count vs. character count mismatch Crypto Agility Get crypto provider from configuration August Not so fast Whats SAL? August Standard Annotation Language Used by static analysis tools such as /analyze Benefits of adding annotations to your code: Help the tools find harder to find bugs The process of adding annotations finds bugs! Bugs found are low noise August SAL at Work void FillString( TCHAR* buf, size_t cchBuf, TCHAR ch) { for (size_t i = 0; i < cchBuf; i++) { buf[i] = ch; } These two arguments are related, but the compiler does not know! August SAL at Work void FillString( __out_ecount(cchBuf) TCHAR* buf, size_t cchBuf, TCHAR ch) { for (size_t i = 0; i < cchBuf; i++) { buf[i] = ch; } August SAL at Work __out_ecount(cchBuf) Out buffer, function will write to the buffer. Other examples include __in and __inout Element count. Other example includes bcount, byte count. __checkReturn __bcount_opt(_Size) malloc(__in size_t _Size); Optional, can be NULL Must check return value August SAL at Work Warning C6386: Buffer overrun: accessing 'argument 1', the writable size is 200*2' bytes, but '420' bytes might be written: Lines: 33, 34 Warning C6387: 'argument 1' might be '0': this does not adhere to the specification for the function 'FillString': Lines: 33, 34 void FillString( __out_ecount(cchBuf) TCHAR* buf, size_t cchBuf, TCHAR ch) { for (size_t i = 0; i < cchBuf; i++) { buf[i] = ch; } void main() { TCHAR *buff = malloc(200 * sizeof(TCHAR)); FillString(buff,210,_T(x)); } August HashOneFile() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool HashOneFile(wchar_t *wszFilename) { HANDLE hFile = CreateFile(wszFilename, GENERIC_READ,0,NULL, OPEN_EXISTING,0,NULL); if (INVALID_HANDLE_VALUE == hFile) return false; HCRYPTHASH hHash = NULL; if (CryptCreateHash(g_hProv,CALG_SHA1,0,0,&hHash)) { const int cbBuff = 16384; BYTE *pBuff = new BYTE[cbBuff]; while (true) { DWORD cbRead = 0; BOOL fReadOK = ReadFile(hFile,pBuff,cbBuff,&cbRead,NULL); if (!cbRead) break; CryptHashData(hHash,pBuff,cbRead,0); } DWORD cbHash = 160 / 8; BYTE bHash[160 / 8]; CryptGetHashParam(hHash,HP_HASHVAL,&bHash[0],&cbHash,0); AddFileDataToList(wszFilename,bHash,cbHash); free(pBuff); CryptDestroyHash(hHash); } CloseHandle(hFile); return true; } August HashOneFile() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool HashOneFile(__in_z wchar_t *wszFilename) { HANDLE hFile = CreateFile(wszFilename, GENERIC_READ,0,NULL, OPEN_EXISTING,0,NULL); if (INVALID_HANDLE_VALUE == hFile) return false; HCRYPTHASH hHash = NULL; if (CryptCreateHash(g_hProv,CALG_SHA1,0,0,&hHash)) { const int cbBuff = 16384; BYTE *pBuff = new BYTE[cbBuff]; while (true) { DWORD cbRead = 0; BOOL fReadOK = ReadFile(hFile,pBuff,cbBuff,&cbRead,NULL); if (!cbRead) break; CryptHashData(hHash,pBuff,cbRead,0); } DWORD cbHash = 160 / 8; BYTE bHash[160 / 8]; CryptGetHashParam(hHash,HP_HASHVAL,&bHash[0],&cbHash,0); AddFileDataToList(wszFilename,bHash,cbHash); free(pBuff); CryptDestroyHash(hHash); } CloseHandle(hFile); return true; } Add SAL annotation to detect bugs August HashOneFile() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool HashOneFile(__in_z wchar_t *wszFilename) { HANDLE hFile = CreateFile(wszFilename, GENERIC_READ,0,NULL, OPEN_EXISTING,0,NULL); if (INVALID_HANDLE_VALUE == hFile) return false; HCRYPTHASH hHash = NULL; if (CryptCreateHash(g_hProv,GetHashAlg(),0,0,&hHash)) { const int cbBuff = 16384; BYTE *pBuff = new BYTE[cbBuff]; while (true) { DWORD cbRead = 0; BOOL fReadOK = ReadFile(hFile,pBuff,cbBuff,&cbRead,NULL); if (!cbRead) break; CryptHashData(hHash,pBuff,cbRead,0); } DWORD cbHash = 160 / 8; BYTE bHash[160 / 8]; CryptGetHashParam(hHash,HP_HASHVAL,&bHash[0],&cbHash,0); AddFileDataToList(wszFilename,bHash,cbHash); free(pBuff); CryptDestroyHash(hHash); } CloseHandle(hFile); return true; } Add SAL annotation to detect bugs Replace Banned hash function Crypto-Agility Get hash alg from configuration August HashOneFile() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() bool HashOneFile(__in_z wchar_t *wszFilename) { HANDLE hFile = CreateFile(wszFilename, GENERIC_READ,0,NULL, OPEN_EXISTING,0,NULL); if (INVALID_HANDLE_VALUE == hFile) return false; HCRYPTHASH hHash = NULL; if (CryptCreateHash(g_hProv,GetHashAlg(),0,0,&hHash)) { const int cbBuff = 16384; BYTE *pBuff = new BYTE[cbBuff]; while (true) { DWORD cbRead = 0; BOOL fReadOK = ReadFile(hFile,pBuff,cbBuff,&cbRead,NULL); if (!cbRead) break; CryptHashData(hHash,pBuff,cbRead,0); } DWORD cbHash = 160 / 8; BYTE bHash[160 / 8]; CryptGetHashParam(hHash,HP_HASHVAL,&bHash[0],&cbHash,0); AddFileDataToList(wszFilename,bHash,cbHash); delete [] pBuff; CryptDestroyHash(hHash); } CloseHandle(hFile); return true; } Compiled code detects integer overflow automatically in ::new Static analysis spotted mismatch between new/delete [] (was free) Crypto-Agility Get hash alg from configuration Add SAL annotation to detect bugs Replace Banned hash function August AddFileDataToList() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() void AddFileDataToList(wchar_t *wszName, BYTE *pHash, size_t cbHash) { // snip } August AddFileDataToList() ServiceMain() EnumAndHashFiles() GetDirFromUser() HashOneFile() AddFileDataToList() void AddFileDataToList(__in_z wchar_t *wszName, __in_bcount(cbHash) BYTE *pHash, size_t cbHash) { // snip } Add SAL annotation to detect bugs August Required Compiler Settings Compile with /GS Detect some forms of stack-based buffer overrun at runtime If using EH then link with /SafeSEH Protect exception handlers Link with /NXCOMPAT Tested on a Data Execution Protection (DEP, or NX) compatible computer August Fuzz Testing The service consumes: Files from the file system UDP data (file and directory name) from a user So we must fuzz both bool EnumAndHashFiles(__in_z wchar_t *wszPath) { bool fRet = false; wchar_t wszPath2[128]; wcscpy(wszPath2,(wchar_t*)wszPath); wcscat(wszPath2,L"\\*.*"); wszPath is untrusted Buffer overflow when path is greater than 128 chars long August D-Day is nearly here! User account control (UAC) enabled Your users will no longer be admins by default! Parental Controls requires child be a non- admin Allow parents to enforce limits on usage Know childrens activities Extensible by ISVs NOT A SECURITY FEATURE! August UAC Dos and Donts Dont assume that the user installing game is the player Do perform game system-wide configuration during setup Do perform firewall operations during setup Be nice: let the user know! And that doesnt mean turning off the firewall! Dont perform admin tasks during 1 st run Per-user stuff must be done at 1 st run August UAC Dos and Donts Do write user data to user directories CSIDL_LOCAL_APPDATA, _PERSONAL, _COMMON_APPDATA If using Windows installer, use MSI patching (it does UAC hot-patching) Do sign your installer Dont sign your installer with a self-issued certificate Do test as an installer and as a user August Invisible Vista Defenses you get for free Firewall is on by default Data Execution Protection (DEP/NX) Supported by all AMD CPUs and most newer Intel CPUs (its more common than you think!) Some BIOSs disable by default :-( Service Hardening Network Access Policy for services mitigates rogue code running in the process from opening outbound ports August Random Vista Defenses you get for free Address Space Layout Randomization Windows APIs commonly used by malware load at unpredictable addresses You can opt-in your code too (link with /DYNAMICBASE) Stack base is randomized per thread Heap is toughened Randomized base address Check-summed Terminate on heap corruption August What You Should Do Start removing banned APIs Use static analysis tools, such as /analyze VSTS 2005 and Windows Development Kit Compile with SAL-annotated headers Add SAL to your own private headers Compile with /GS Link with /SafeSEH, /NXCompat and /DynamicBase Run and test on Windows Vista With DEP and UAC enabled Use PageHeap and AppVerifier August Original Xbox Security Tales Its just a buffer overrun in a game Load game code of an original Xbox title did not correctly handle buffer overruns Bug used by hackers to overwrite the title signature public key in memory Via a crafted invalid save game One single title programming error led to Xbox 1 softmod Enabled offline cheating and game piracy (and not just against the title containing the programming error) Need to do better in Xbox 360 August Lessons Learned Game Development Kit APIs automatically protect game data Maintaining Xbox 360 as a closed system All native code applications must be certified and signed by Microsoft No arbitrary network access from or to Xbox 360 Chances of malware, worm or virus intrusion low Hardware-protected multilayered security system Better protection against buffer overruns and other attacks against their persisted or in-memory code Resilient against application programming errors Extended Live security system August Security You Get For Free Secure boot system Validated and certified executables Automatic network encryption/authentication Live security system counteracting cheating Automatic protection of HDD cache and MU content August Protect Against Cheating Persisted game configuration data on DVD should be protected Multilevel security approach to protecting game data (in addition to DVD protection mechanisms) Put game configuration data in resource section of executable Protect config files with authenticated hash values Put hash values in Xex, and validate hashes before permitting the load to succeed August More Anti-Cheating Measures Protect against DMA attacks Upcoming feature: protected data pages Allocated pages are protected by the Xbox 360 security system Protects security-relevant in-memory game state Utility Partition (hard-drive cache) is automatically integrity protected Use XContentCreate with confidence Get integrity validation for free Lock content to machine/profile when possible Game save Web sharing can lead to achievements/gamer score cheating August Fuzz Testing Fuzz testing subjects program interfaces to random or semi-random data input Fuzz testing has been very successful for Xbox 360 team You can use it too! Fuzz test APIs that take input state not under title control Fuzz testing is one of the most successful ways to discover buffer overruns Buffer overruns on Xbox 360 could still lead to illicit data page manipulation Cheating still possible via buffer overruns August Security Development Constraints No dynamic native code generation Creating native code on the fly is a high security risk Only cryptographically signed native code is allowed to execute on the console Protects against game code tampering Homebrewed code not entirely excluded: Hobbyists will be able to write managed code to run on Xbox 360 Stack memory is not executable Protection against buffer overrun attacks against the stack August Summary Questions? Sample Manifest DirectX SDK Sample Program. ... August Resources Windows Vista SDK User Account Control Guidelines y/en-us/dnlong/html/AccProtVista.aspy/en-us/dnlong/html/AccProtVista.aspy/en-us/dnlong/html/AccProtVista.asp Authenticode Signing for Game Developers library/en- us/direct x9_c/Authenticode_Signing_for_Game_Developers.asplibrary/en- us/direct x9_c/Authenticode_Signing_for_Game_Developers.asplibrary/en- us/direct x9_c/Authenticode_Signing_for_Game_Developers.asp August Resources Best Security Practices in Game Development us/directx9_c/Best_Security_Practices_in_Game_Development.aspus/directx9_c/Best_Security_Practices_in_Game_Development.aspus/directx9_c/Best_Security_Practices_in_Game_Development.asp Gaming with Least-Privileged User Accounts us/directx9_c/Gaming_with_Least_Privileged_User_Accounts.aspus/directx9_c/Gaming_with_Least_Privileged_User_Accounts.aspus/directx9_c/Gaming_with_Least_Privileged_User_Accounts.asp Patching Methods in Windows XP and Vista us/directx9_c/Patching_Methods_in_Windows_XP_and_Vista.aspus/directx9_c/Patching_Methods_in_Windows_XP_and_Vista.aspus/directx9_c/Patching_Methods_in_Windows_XP_and_Vista.asp August Summary of Vista Defenses DefenseComments /GSReduces the chance that stack-based exploits work /SafeSEHReduce the chance that exception handler compromises work Heap Hardening and failfastReduce the chance that heap-based exploits work ASLRReduce the chance that return to libc exploits work Service HardeningReduces the chance that networking exploit code can open a socket Reduced Service PrivilegeReduces exploit code damage potential Data Execution ProtectionReduces the chance that exploit code will work in data segments Stack RandomizedReduces the predictability of stack addresses 2006 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary. DirectX Developer CenterGame Development MSDN ForumsXbox 360 CentralXNA Web site End Slide