| Foreword | xvii |
| Acknowledgments | xix |
| Introduction | xxi |
| PART I CONTEMPORARY SECURITY | |
| 1 The Need for Secure Systems | 3 |
| Applications on the Wild Wild Web | 5 |
| Getting Everyone's Head in the Game | 7 |
| Using Tact to Sell Security to the Organization | 7 |
| Using Subversion | 11 |
| Some Ideas for Instilling a Security Culture | 13 |
| Get the Boss to Send an E-Mail | 13 |
| Nominate a Security Evangelist | 14 |
| 2 Designing Secure Systems | 19 |
| Two Common Security Mistakes | 19 |
| Why These Mistakes Are Made | 21 |
| Security Principles to Live By | 22 |
| Establish a Security Process | 23 |
| Define the Product Security Goals | 23 |
| Consider Security as a Product Feature | 24 |
| Learn from Mistakes | 25 |
| Use Least Privilege | 27 |
| Use Defense in Depth | 28 |
| Assume External Systems Are Insecure | 29 |
| Plan on Failure | 29 |
| Fail to a Secure Mode | 29 |
| Employ Secure Defaults | 31 |
| Remember That Security Features != Secure Features | 33 |
| Never Depend on Security Through Obscurity | 34 |
| Three Final Points | 34 |
| Security Design by Threat Modeling | 35 |
| Brainstorm the Known Threats to the System | 36 |
| Rank the Threats by Decreasing Risk | 43 |
| Choose How to Respond to the Threats | 44 |
| Choose Techniques to Mitigate the Threats | 45 |
| Security Techniques | 46 |
| Authentication | 46 |
| Authorization | 51 |
| Tamper-Resistant and Privacy-Enhanced Technologies | 52 |
| Protect Secrets, or Better Yet, Don't Store Secrets | 53 |
| Encryption, Hashes, MACs, and Digital Signatures | 53 |
| Auditing | 54 |
| Filtering, Throttling, and Quality of Service | 54 |
| Least Privilege | 54 |
| Back to the Example Payroll Application | 54 |
| A Cornucopia of Threats and Solutions | 57 |
| PART II SECURE CODING TECHNIQUES | |
| 3 Public Enemy #1: The Buffer Overrun | 63 |
| Static Buffer Overruns | 64 |
| Heap Overruns | 70 |
| Array Indexing Errors | 75 |
| Format String Bugs | 78 |
| Unicode and ANSI Buffer Size Mismatches | 78 |
| A Real Unicode Bug Example | 79 |
| Preventing Buffer Overruns | 80 |
| Safe String Handling | 81 |
| Good News on the Horizon! | 88 |
| 4 Determining Good Access Control | 89 |
| Why ACLs Are Important | 89 |
| A Diversion: Fixing the Registry Code | 91 |
| What Makes Up an ACL? | 93 |
| A Method of Choosing Good ACLs | 95 |
| Effective Deny ACEs | 98 |
| Creating ACLs | 99 |
| Creating ACLs in Windows NT 4 | 99 |
| Creating ACLs in Windows 2000 | 103 |
| Creating ACLs with Active Template Library | 106 |
| NULL DACLs and Other Dangerous ACE Types | 108 |
| NULL DACLs and Auditing | 110 |
| Dangerous ACE Types | 110 |
| What If I Can't Change the NULL DACL? | 111 |
| Other Access Control Mechanisms | 112 |
| IP Restrictions | 112 |
| COM+ Roles | 113 |
| SQL Server Triggers and Permissions | 114 |
| A Medical Example | 114 |
| An Important Note About Access Control Mechanisms | 116 |
| 5 Running with Least Privilege | 119 |
| Least Privilege in the Real World | 120 |
| Viruses and Trojans | 120 |
| Web Server Defacements | 121 |
| Brief Overview of Access Control | 122 |
| Brief Overview of Privileges | 122 |
| SeBackupPrivilege Issues | 123 |
| SeDebugPrivilege Issues | 126 |
| SeTcbPrivilege Issues | 126 |
| SeAssignPrimaryTokenPrivilege and SeIncreaseQuotaPrivilege Issues | 127 |
| Brief Overview of Tokens | 127 |
| How Tokens, Privileges, SIDs, ACLs, and Processes Relate | 128 |
| SIDs and Access Checks, Privileges and Privilege Checks | 129 |
| A Process for Determining Appropriate Privilege | 129 |
| Step 1: Find Resources Used by the Application | 130 |
| Step 2: Find Privileged APIs Used by the Application | 130 |
| Step 3: Which Account Is Required? | 131 |
| Step 4: Get the Token Contents | 132 |
| Step 5: Are All the SIDs and Privileges Required? | 138 |
| Step 6: Adjust the Token | 139 |
| When to Use Restricted Tokens | 143 |
| Low-Privilege Service Accounts in Windows XP and Windows .NET Server | 149 |
| Debugging Least-Privilege Issues | 151 |
| Why Applications Fail as a Normal User | 152 |
| How to Determine Why Applications Fail | 153 |
| 6 Cryptographic Foibles | 159 |
| Using Poor Random Numbers | 159 |
| The Problem: rand | 160 |
| A Remedy: CryptGenRandom | 162 |
| Using Passwords to Derive Cryptographic Keys | 165 |
| Measuring the Effective Bit Size of a Password | 166 |
| Poor Key Management | 168 |
| Keep Keys Close to the Source | 169 |
| Rolling Your Own Cryptographic Functions | 172 |
| Using the Same Stream-Cipher Encryption Key | 175 |
| Why People Use Stream Ciphers | 175 |
| The Pitfalls of Stream Ciphers | 176 |
| What If You Must Use the Same Key? | 179 |
| Bit-Flipping Attacks Against Stream Ciphers | 181 |
| Solving Bit-Flipping Attacks | 181 |
| When to Use a Hash, Keyed Hash, or Digital Signature | 182 |
| Reusing a Buffer for Plaintext and Ciphertext | 187 |
| 7 Storing Secrets | 189 |
| Attack Methods | 189 |
| Sometimes You Don't Need to Store a Secret | 190 |
| Creating a Salted Hash | 191 |
| Getting the Secret from the User | 192 |
| Storing Secrets in Windows 2000 and Windows XP | 192 |
| A Special Case: Client Credentials in Windows XP | 195 |
| Storing Secrets in Windows NT 4 | 197 |
| Storing Secrets in Windows 95, Windows 98, Windows Me, and Windows CE | 201 |
| Raising the Security Bar | 202 |
| Storing the Data in a File on a FAT File System | 202 |
| Using an Embedded Key and XOR to Encode the Data | 202 |
| Using an Embedded Key and 3DES to Encrypt the Data | 203 |
| Using 3DES to Encrypt the Data and Storing a Password in the Registry | 203 |
| Using 3DES to Encrypt the Data and Storing a Strong Key in the Registry | 203 |
| Using 3DES to Encrypt the Data, Storing a Strong Key in the Registry, and ACLing the File and the Registry Key | 203 |
| An Idea: Using External Devices to Encrypt Secret Data | 203 |
| A Sample Scenario Using PPCKey | 204 |
| A PPCKey Threat Model | 206 |
| 8 Canonical Representation Issues | 211 |
| What Does Canonical Mean, and Why Is It a Problem? | 212 |
| A Bit of History | 212 |
| Bypassing AOL Parental Controls | 212 |
| Bypassing Napster Name Filtering | 212 |
| Bypassing eEye's Security Checks | 213 |
| Vulnerability in Apple Mac OS X and Apache | 214 |
| Zones and the Internet Explorer 4 "Dotless-IP Address" Bug | 214 |
| Internet Information Server 4.0 ::$DATA Vulnerability | 215 |
| DOS Device Names Vulnerability | 217 |
| Sun Microsystems StarOffice /tmp Directory Symbolic-Link Vulnerability | 217 |
| Common Windows Canonicalization Mistakes | 219 |
| 8.3 Representation of Long Filenames | 219 |
| NTFS Alternate Data Streams | 220 |
| Trailing Characters | 221 |
| \\?\ Format | 222 |
| Directory Traversal and Using Parent Paths (..) | 222 |
| Absolute vs. Relative Filenames | 223 |
| Case-Insensitive Filenames | 223 |
| Device Names and Reserved Names | 223 |
| UNC Shares | 224 |
| Preventing Canonicalization Mistakes | 225 |
| Don't Make Decisions Based on Names | 225 |
| Use a Regular Expression to Restrict What's Allowed in a Name | 225 |
| Attempt to Canonicalize the Name | 229 |
| A Final Thought: Non-File-Based Canonicalization Issues | 233 |
| Server Names | 233 |
| Usernames | 234 |
| PART III NETWORK-BASED APPLICATION CONSIDERATIONS | |
| 9 Socket Security | 239 |
| Avoiding Server Hijacking | 239 |
| Choosing Server Interfaces | 246 |
| Accepting Connections | 247 |
| Writing Firewall-Friendly Applications | 252 |
| Use One Connection to Do the Job | 253 |
| Don't Require the Server to Connect Back to the Client | 253 |
| Use Connection-Based Protocols | 253 |
| Don't Multiplex Your Application over Another Protocol | 254 |
| Don't Embed Host IP Addresses in Application-Layer Data | 254 |
| Make Your Application Configurable | 254 |
| Spoofing and Host-Based and Port-Based Trust | 255 |
| 10 Securing RPC, ActiveX Controls, and DCOM | 257 |
| An RPC Primer | 258 |
| What Is RPC? | 258 |
| Creating RPC Applications | 259 |
| How RPC Applications Communicate | 260 |
| Secure RPC Best Practices | 262 |
| Use the /robust MIDL Switch | 262 |
| Use the [range] Attribute | 263 |
| Require Authenticated Connections | 263 |
| Use Packet Privacy and Integrity | 269 |
| Use Strict Context Handles | 270 |
| Don't Rely on Context Handles for Access Checks | 271 |
| Be Wary of NULL Context Handles | 272 |
| Don't Trust Your Peer | 274 |
| Use Security Callbacks | 274 |
| Implications of Multiple RPC Servers in a Single Process | 276 |
| Consider Adding an Annotation for Your Endpoint | 277 |
| Use Mainstream Protocols | 278 |
| Secure DCOM Best Practices | 278 |
| DCOM Basics | 278 |
| Application-Level Security | 280 |
| DCOM User Contexts | 281 |
| Programmatic Security | 283 |
| Sources and Sinks | 287 |
| An ActiveX Primer | 287 |
| Secure ActiveX Best Practices | 288 |
| What ActiveX Components Are Safe for Initialization and Safe for Scripting? | 288 |
| Best Practices for Safe for Initialization and Scripting | 289 |
| 11 Protecting Against Denial of Service Attacks | 293 |
| Application Failure Attacks | 293 |
| CPU Starvation Attacks | 297 |
| Memory Starvation Attacks | 303 |
| Resource Starvation Attacks | 304 |
| Network Bandwidth Attacks | 305 |
| 12 Securing Web-Based Services | 307 |
| Never Trust User Input! | 308 |
| User Input Vulnerabilities | 309 |
| User Input Remedies | 315 |
| Web-Specific Canonicalization Bugs | 322 |
| 7-Bit and 8-Bit ASCII | 323 |
| Hexadecimal Escape Codes | 323 |
| UTF-8 Variable-Width Encoding | 323 |
| UCS-2 Unicode Encoding | 325 |
| Double Encoding | 326 |
| HTML Escape Codes | 326 |
| Web-Based Canonicalization Remedies | 326 |
| Other Web-Based Security Topics | 330 |
| HTTP Trust Issues | 330 |
| ISAPI Applications and Filters | 332 |
| Don't Store Secrets in Web Pages | 334 |
| Do You Really Need to Use sa? Probably Not! | 338 |
| PART IV SPECIAL TOPICS | |
| 13 Writing Secure .NET Code | 341 |
| Buffer Overruns and the Common Language Runtime | 342 |
| Adding Your Own Security Error Handler | 345 |
| A Dose of Reality | 346 |
| Storing Secrets in .NET | 346 |
| Always Demand Appropriate Permissions | 351 |
| Overzealous Use of Assert | 352 |
| Further Information Regarding Demand and Assert | 354 |
| Don't Be Afraid to Refuse Permissions | 355 |
| Validate Data from Untrusted Sources | 356 |
| Be Thread-Aware in ASP.NET | 357 |
| Disable Tracing and Debugging Before Deploying ASP.NET Applications | 357 |
| Generating Good Random Numbers by Using the .NET Framework | 358 |
| Deserializing Data from Untrusted Sources | 359 |
| Don't Tell the Attacker Too Much When You Fail | 360 |
| SOAP Ponderings | 361 |
| Some Final Thoughts | 362 |
| 14 Testing Secure Applications | 363 |
| The Role of the Security Tester | 363 |
| Security Testing Is Different | 364 |
| Getting Started | 365 |
| Building the Security Test Plan | 366 |
| Decompose the Application | 367 |
| Identify Component Interfaces | 368 |
| Rank Interfaces by Their Relative Vulnerability | 369 |
| Ascertain Data Used by Each Interface | 370 |
| Find Security Problems by Injecting Faulty Data | 370 |
| Before Testing | 381 |
| Building Tools to Find Flaws | 381 |
| Testing Clients with Rogue Servers | 395 |
| Should a User See or Modify That Data? | 395 |
| Testing with Security Templates | 396 |
| Test Code Should Be of Great Quality | 397 |
| Test the End-to-End Solution | 398 |
| Slightly Off-Topic: Code Reviews | 398 |
| 15 Secure Software Installation | 399 |
| Principle of Least Privilege | 400 |
| Using the Security Configuration Editor | 401 |
| Low-Level Security APIs | 409 |
| 16 General Good Practices | 411 |
| Protecting Customer Privacy | 411 |
| Types of Collected User Data | 412 |
| Collecting User Data | 413 |
| Don't Tell the Attacker Anything | 414 |
| Double-Check Your Error Paths | 414 |
| Keep It Turned Off! | 415 |
| Kernel-Mode Mistakes | 415 |
| Using User-Mode Memory | 415 |
| Accessing Privileged Interfaces Through Unprotected IOCTLs | 416 |
| Consider Adding Security Comments to Code | 416 |
| Leverage the Operating System | 416 |
| Don't Rely on Users Making Good Decisions | 417 |
| Calling CreateProcess Securely | 417 |
| Do Not Pass NULL for lpApplicationName | 419 |
| Use Quotes Around the Path to Executable in lpCommandLine | 419 |
| Don't Create Shared/Writable Segments | 419 |
| Using Impersonation Functions Correctly | 420 |
| Don't Write User Files to \Program Files | 420 |
| Don't Write User Data to HKLM | 421 |
| Don't Open Objects for FULL_CONTROL or ALL_ACCESS | 421 |
| Object Creation Mistakes | 421 |
| Creating Temporary Files Securely | 423 |
| Client-Side Security Is an Oxymoron | 427 |
| Samples Are Templates | 427 |
| Dogfood Your Stuff! | 427 |
| You Owe It to Your Users If. | 428 |
| Determining Access Based on an Administrator SID | 428 |
| Allow Long Passwords | 430 |
| PART V APPENDIXES | |
| A Dangerous APIs | 433 |
| B The Ten Immutable Laws of Security | 437 |
| C The Ten Immutable Laws of Security Administration | 445 |
| D Lame Excuses We've Heard | 453 |
| A Final Thought | 459 |
| Annotated Bibliography | 461 |
| INDEX | 465 |