| Introduction |
xxiii |
| PART I CONTEMPORARY SECURITY |
|
| 1 The Need for Secure Systems |
3 |
| Applications on the Wild Wild Web |
5 |
| The Need for Trustworthy Computing |
7 |
| Getting Everyone’s Head in the Game |
7 |
| Using Tact
to Sell Security to the Organization |
8 |
| Using Subversion |
11 |
| Some Ideas for Instilling a Security
Culture |
13 |
| Get the Boss
to Send an E-Mail |
14 |
| Nominate a
Security Evangelist |
15 |
| The Attacker’s Advantage and the Defender’s
Dilemma |
19 |
| Principle #1:
The defender must defend all points; the attacker can choose the weakest
point. |
19 |
| Principle #2:
The defender can defend only against known attacks; the attacker can probe
for unknown vulnerabilities. |
20 |
| Principle #3:
The defender must be constantly vigilant; the attacker can strike at will. |
20 |
| Principle #4:
The defender must play by the rules; the attacker can play dirty. |
21 |
| Summary |
21 |
| 2 The Proactive Security Development Process |
23 |
| Process Improvements |
25 |
| The Role of Education |
26 |
| Resistance
to Mandatory Training |
29 |
| Ongoing Training |
29 |
| Advancing the
Science of Security |
29 |
| Education Proves
the More Eyes Fallacy |
31 |
| Now the Evidence! |
31 |
| Design Phase |
32 |
| Security Questions
During Interviews |
33 |
| Define the
Product Security Goals |
34 |
| Security Is
a Product Feature |
37 |
| Making Time
for Security |
40 |
| Threat Modeling
Leads to Secure Design |
41 |
| Build End-of-Life
Plans for Insecure Features |
41 |
| Setting the
Bug Bar |
41 |
| Security Team
Review |
43 |
| Development Phase |
43 |
| Be Hardcore
About Who Can Check In New Code (Check-Ins Checked) |
43 |
| Security Peer
Review of New Code (Check-Ins Checked) |
44 |
| Define Secure
Coding Guidelines |
44 |
| Review Old
Defects |
44 |
| External Security
Review |
45 |
| Security Push |
45 |
| Be Mindful
of Your Bug Counts |
46 |
| Keep Track
of Bug Metrics |
46 |
| No Surprises
and No Easter Eggs! |
47 |
| Test Phase |
47 |
| Shipping and Maintenance Phases |
47 |
| How Do You
Know When You’re Done? |
47 |
| Response Process |
48 |
| Accountability |
49 |
| Summary |
49 |
| 3 Security Principles to Live By |
51 |
| SD3: Secure by Design, by
Default, and in Deployment |
51 |
| Secure by Design |
51 |
| Secure by Default |
53 |
| Secure in Deployment |
53 |
| Security Principles |
54 |
| Learn from
Mistakes |
54 |
| Minimize Your
Attack Surface |
57 |
| Employ Secure
Defaults |
57 |
| Use Defense
in Depth |
59 |
| Use Least Privilege |
60 |
| Backward Compatibility
Will Always Give You Grief |
62 |
| Assume External
Systems Are Insecure |
63 |
| Plan on Failure |
64 |
| Fail to a Secure
Mode |
64 |
| Remember That
Security Features != Secure Features |
66 |
| Never Depend
on Security Through Obscurity Alone |
66 |
| Don’t Mix Code
and Data |
67 |
| Fix Security
Issues Correctly |
67 |
| Summary |
68 |
| 4 Threat Modeling |
69 |
| Secure Design Through Threat Modeling
|
70 |
| Assemble the
Threat-Modeling Team |
72 |
| Decompose the
Application |
73 |
| Determine the
Threats to the System |
83 |
| Rank the Threats
by Decreasing Risk |
93 |
| Choose How
to Respond to the Threats |
106 |
| Choose Techniques
to Mitigate the Threats |
107 |
| Security Techniques |
108 |
| Authentication
|
109 |
| Authorization
|
114 |
| Tamper-Resistant
and Privacy-Enhanced Technologies |
115 |
| Protect Secrets,
or Better Yet, Don’t Store Secrets |
116 |
| Encryption,
Hashes, MACs, and Digital Signatures |
116 |
| Auditing |
117 |
| Filtering,
Throttling, and Quality of Service |
118 |
| Least Privilege
|
118 |
| Mitigating the Sample Payroll Application
Threats |
118 |
| A Cornucopia of Threats and Solutions
|
120 |
| Summary |
124 |
| PART II SECURE CODING TECHNIQUES |
|
| 5 Public Enemy #1: The Buffer Overrun |
127 |
| Stack Overruns |
129 |
| Heap Overruns |
138 |
| Array Indexing Errors |
144 |
| Format String Bugs |
147 |
| Unicode and ANSI Buffer Size Mismatches
|
153 |
| A Real Unicode
Bug Example |
154 |
| Preventing Buffer Overruns |
155 |
| Safe String
Handling |
156 |
| A Word of Caution
About String-Handling Functions |
166 |
| The Visual C++ .NET /GS Option |
167 |
| Summary |
170 |
| 6 Determining Appropriate Access Control |
171 |
| Why ACLs Are Important |
171 |
| A Diversion:
Fixing the Registry Code |
173 |
| What Makes Up an ACL? |
175 |
| A Method of Choosing Good ACLs |
178 |
| Effective Deny
ACEs |
180 |
| Creating ACLs |
181 |
| Creating ACLs
in Windows NT 4 |
181 |
| Creating ACLs
in Windows 2000 |
185 |
| Creating ACLs
with Active Template Library |
189 |
| Getting the ACE Order Right |
191 |
| Be Wary of the Terminal Server and
Remote Desktop SIDs |
193 |
| NULL DACLs and Other Dangerous ACE
Types |
195 |
| NULL DACLs
and Auditing |
197 |
| Dangerous ACE
Types |
197 |
| What If I Can’t
Change the NULL DACL? |
198 |
| Other Access Control Mechanisms |
199 |
| .NET Framework
Roles |
199 |
| COM+ Roles
|
201 |
| IP Restrictions
|
202 |
| SQL Server
Triggers and Permissions |
203 |
| A Medical Example
|
203 |
| An Important
Note About Access Control Mechanisms |
205 |
| Summary |
206 |
| 7 Running with Least Privilege |
207 |
| Least Privilege in the Real World |
208 |
| Viruses and
Trojans |
209 |
| Web Server
Defacements |
210 |
| Brief Overview of Access Control |
211 |
| Brief Overview of Privileges |
211 |
| SeBackupPrivilege
Issues |
212 |
| SeRestorePrivilege
Issues |
215 |
| SeDebugPrivilege
Issues |
215 |
| SeTcbPrivilege
Issues |
216 |
| SeAssignPrimaryTokenPrivilege
and SeIncreaseQuotaPrivilege Issues |
217 |
| SeLoadDriverPrivilege
Issues |
217 |
| SeRemoteShutdownPrivilege
Issues |
217 |
| SeTakeOwnershipPrivilege
Issues |
217 |
| Brief Overview of Tokens |
218 |
| How Tokens, Privileges, SIDs, ACLs,
and Processes Relate |
218 |
| SIDs and Access
Checks, Privileges and Privilege Checks |
219 |
| Three Reasons Applications Require
Elevated Privileges |
220 |
| ACL Issues
|
220 |
| Privilege Issue
|
221 |
| Using LSA Secrets
|
221 |
| Solving the Elevated Privileges Issue
|
222 |
| Solving ACL
Issues |
222 |
| Solving Privilege
Issues |
223 |
| Solving LSA
Issues |
223 |
| A Process for Determining Appropriate
Privilege |
223 |
| Step 1: Find
Resources Used by the Application |
224 |
| Step 2: Find
Privileged APIs Used by the Application |
224 |
| Step 3: Which
Account Is Required? |
226 |
| Step 4: Get
the Token Contents |
226 |
| Step 5: Are
All the SIDs and Privileges Required? |
232 |
| Step 6: Adjust
the Token |
233 |
| Low-Privilege Service Accounts in Windows
XP and Windows .NET Server 2003 |
248 |
| The Impersonate Privilege and Windows
.NET Server 2003 |
250 |
| Debugging Least-Privilege Issues |
251 |
| Why Applications
Fail as a Normal User |
251 |
| How to Determine
Why Applications Fail |
252 |
| Summary |
258 |
| 8 Cryptographic Foibles |
259 |
| Using Poor Random Numbers |
259 |
| The Problem:
rand |
260 |
| Cryptographically
Random Numbers in Win32 |
262 |
| Cryptographically
Random Numbers in Managed Code |
268 |
| Cryptographically
Random Numbers in Web Pages |
269 |
| Using Passwords to Derive Cryptographic
Keys |
269 |
| Measuring the
Effective Bit Size of a Password |
270 |
| Key Management Issues |
272 |
| Long-Term and
Short-Term Keys |
274 |
| Use Appropriate
Key Lengths to Protect Data |
274 |
| Keep Keys Close
to the Source |
276 |
| Key Exchange
Issues |
279 |
| Creating Your Own Cryptographic Functions
|
281 |
| Using the Same Stream-Cipher Encryption
Key |
283 |
| Why People
Use Stream Ciphers |
284 |
| The Pitfalls
of Stream Ciphers |
284 |
| What If You
Must Use the Same Key? |
287 |
| Bit-Flipping Attacks Against Stream
Ciphers |
289 |
| Solving Bit-Flipping
Attacks |
290 |
| When to Use
a Hash, Keyed Hash, or Digital Signature |
290 |
| Reusing a Buffer for Plaintext and
Ciphertext |
296 |
| Using Crypto to Mitigate Threats |
297 |
| Document Your Use of Cryptography |
298 |
| 9 Protecting Secret Data |
299 |
| Attacking Secret Data |
300 |
| Sometimes You Don’t Need to Store a
Secret |
301 |
| Creating a
Salted Hash |
302 |
| Using PKCS
#5 to Make the Attacker’s Job Harder |
303 |
| Getting the Secret from the User |
305 |
| Protecting Secrets in Windows 2000
and Later |
305 |
| A Special Case:
Client Credentials in Windows XP |
309 |
| Protecting Secrets in Windows NT 4
|
311 |
| Protecting Secrets in Windows 95, Windows
98, Windows Me, and Windows CE |
315 |
| Getting Device
Details Using PnP |
316 |
| Not Opting for a Least Common Denominator
Solution |
320 |
| Managing Secrets in Memory |
321 |
| A Compiler
Optimization Caveat |
322 |
| Encrypting
Secret Data in Memory |
326 |
| Locking Memory to Prevent Paging Sensitive
Data |
327 |
| Protecting Secret Data in Managed Code
|
329 |
| Managing Secrets
in Memory in Managed Code |
335 |
| Raising the Security Bar |
336 |
| Storing the
Data in a File on a FAT File System |
337 |
| Using an Embedded
Key and XOR to Encode the Data |
337 |
| Using an Embedded
Key and 3DES to Encrypt the Data |
337 |
| Using 3DES
to Encrypt the Data and Storing a Password in the Registry |
337 |
| Using 3DES
to Encrypt the Data and Storing a Strong Key in the Registry |
337 |
| Using 3DES
to Encrypt the Data, Storing a Strong Key in the Registry, and ACLing the
File and the Registry Key |
338 |
| Using 3DES
to Encrypt the Data, Storing a Strong Key in the Registry, Requiring the
User to Enter a Password, and ACLing the File and the Registry Key |
338 |
| Trade-Offs When Protecting Secret Data
|
338 |
| Summary |
339 |
| 10 All Input Is Evil! |
341 |
| The Issue |
342 |
| Misplaced Trust |
343 |
| A Strategy for Defending Against Input
Attacks |
345 |
| How to Check Validity |
347 |
| Tainted Variables in Perl |
349 |
| Using Regular Expressions for Checking
Input |
350 |
| Be Careful
of What You FindDid You Mean to Validate? |
352 |
| Regular Expressions and Unicode |
353 |
| A Regular Expression Rosetta Stone
|
358 |
| Regular Expressions
in Perl |
358 |
| Regular Expressions
in Managed Code |
359 |
| Regular Expressions
in Script |
360 |
| Regular Expressions
in C++ |
360 |
| A Best Practice That Does Not Use Regular
Expressions |
361 |
| Summary |
362 |
| 11 Canonical Representation Issues |
363 |
| What Does Canonical Mean, and
Why Is It a Problem? |
364 |
| Canonical Filename Issues |
364 |
| Bypassing Napster
Name Filtering |
364 |
| Vulnerability
in Apple Mac OS X and Apache |
365 |
| DOS Device
Names Vulnerability |
365 |
| Sun Microsystems
StarOffice /tmp Directory Symbolic-Link Vulnerability |
366 |
| Common Windows
Canonical Filename Mistakes |
367 |
| Canonical Web-Based Issues |
373 |
| Bypassing AOL
Parental Controls |
373 |
| Bypassing eEye’s
Security Checks |
374 |
| Zones and the
Internet Explorer 4 "Dotless-IP Address" Bug |
374 |
| Internet Information
Server 4.0 ::$DATA Vulnerability |
375 |
| When is a Line
Really Two Lines? |
377 |
| Yet Another
Web IssueEscaping |
378 |
| Visual Equivalence Attacks and the
Homograph Attack |
382 |
| Preventing Canonicalization Mistakes
|
383 |
| Don’t Make
Decisions Based on Names |
383 |
| Use a Regular
Expression to Restrict What’s Allowed in a Name |
383 |
| Stopping 8.3
Filename Generation |
385 |
| Don’t Trust
the PATHUse Full Path Names |
385 |
| Attempt to
Canonicalize the Name |
386 |
| Calling CreateFile
Safely |
390 |
| Web-Based Canonicalization Remedies
|
391 |
| Restrict What
Is Valid Input |
391 |
| Be Careful
When Dealing with UTF-8 |
391 |
| ISAPIsBetween
a Rock and a Hard Place |
392 |
| A Final Thought: Non-File-Based Canonicalization
Issues |
393 |
| Server Names
|
393 |
| Usernames |
394 |
| Summary |
396 |
| 12 Database Input Issues |
397 |
| The Issue |
398 |
| Pseudoremedy #1: Quoting the Input
|
401 |
| Pseudoremedy #2: Use Stored Procedures
|
402 |
| Remedy #1: Never Ever Connect as sysadmin
|
403 |
| Remedy #2: Building SQL Statements
Securely |
404 |
| Building SQL
Stored Procedures Securely |
406 |
| An In-Depth Defense in Depth Example
|
407 |
| Summary |
411 |
| 13 Web-Specific Input Issues |
413 |
| Cross-Site Scripting: When Output Turns
Bad |
413 |
| Sometimes the
Attacker Doesn’t Need a <SCRIPT> Block |
417 |
| The Attacker
Doesn’t Need the User to Click a Link! |
418 |
| Other XSS-Related Attacks |
418 |
| XSS Attacks
Against Local Files |
418 |
| XSS Attacks
Against HTML Resources |
420 |
| XSS Remedies |
421 |
| Encoding Output
|
422 |
| Adding Double
Quotes Around All Tag Properties |
422 |
| Inserting Data
in the innerText Property |
423 |
| Forcing the
Codepage |
423 |
| The Internet
Explorer 6.0 SP1 HttpOnly Cookie Option |
424 |
| Internet Explorer
"Mark of the Web" |
425 |
| Internet Explorer
<FRAME SECURITY> Attribute |
426 |
| ASP.NET 1.1
ValidateRequest configuration option |
427 |
| Don’t Look for Insecure Constructs
|
428 |
| But I Want Users to Post HTML to My
Web Site! |
430 |
| How to Review Code for XSS Bugs |
431 |
| Other Web-Based Security Topics |
431 |
| eval()
Can Be Bad |
431 |
| HTTP Trust
Issues |
432 |
| ISAPI Applications
and Filters |
433 |
| Be Wary of
"Predictable Cookies" |
436 |
| SSL/TLS Client
Issues |
437 |
| Summary |
438 |
| 14 Internationalization Issues |
439 |
| The Golden I18N Security Rules |
440 |
| Use Unicode in Your Application |
440 |
| Prevent I18N Buffer Overruns |
441 |
| Words and Bytes
|
442 |
| Validate I18N |
443 |
| Visual Validation
|
443 |
| Do Not Validate
Strings with LCMapString |
443 |
| Use CreateFile
to Validate Filenames |
443 |
| Character Set Conversion Issues |
444 |
| Use MultiByteToWideChar with
MB_PRECOMPOSED and MB_ERR_INVALID_CHARS |
444 |
| Use WideCharToMultiByte with
WC_NO_BEST_FIT_CHARS |
445 |
| Comparison and Sorting |
448 |
| Unicode Character Properties |
448 |
| Normalization |
450 |
| Summary |
451 |
| PART III EVEN MORE SECURE CODING TECHNIQUES |
|
| 15 Socket Security |
455 |
| Avoiding Server Hijacking |
456 |
| TCP Window Attacks |
463 |
| Choosing Server Interfaces |
464 |
| Accepting Connections |
464 |
| Writing Firewall-Friendly Applications
|
470 |
| Use One Connection
to Do the Job |
471 |
| Don’t Require
the Server to Connect Back to the Client |
471 |
| Use Connection-Based
Protocols |
472 |
| Don’t Multiplex
Your Application over Another Protocol |
472 |
| Don’t Embed
Host IP Addresses in Application-Layer Data |
473 |
| Make Your Application
Configurable |
473 |
| Spoofing and Host-Based and Port-Based
Trust |
473 |
| IPv6 Is Coming! |
474 |
| Summary |
476 |
| 16 Securing RPC, ActiveX Controls, and DCOM |
477 |
| An RPC Primer |
478 |
| What Is RPC? |
478 |
| Creating RPC
Applications |
479 |
| How RPC Applications
Communicate |
481 |
| Secure RPC Best Practices |
482 |
| Use the /robust
MIDL Switch |
483 |
| Use the
[range] Attribute |
483 |
| Require Authenticated
Connections |
484 |
| Use Packet
Privacy and Integrity |
489 |
| Use Strict
Context Handles |
491 |
| Don’t Rely
on Context Handles for Access Checks |
492 |
| Be Wary of
NULL Context Handles |
493 |
| Don’t Trust
Your Peer |
494 |
| Use Security
Callbacks |
495 |
| Implications
of Multiple RPC Servers in a Single Process |
497 |
| Use Mainstream
Protocols |
499 |
| Secure DCOM Best Practices |
499 |
| DCOM Basics |
500 |
| Application-Level
Security |
502 |
| DCOM User Contexts |
502 |
| Programmatic
Security |
505 |
| Sources and
Sinks |
508 |
| An ActiveX Primer |
509 |
| Secure ActiveX Best Practices |
509 |
| What ActiveX
Components Are Safe for Initialization and Safe for Scripting? |
510 |
| Best Practices
for Safe for Initialization and Scripting |
511 |
| Summary |
515 |
| 17 Protecting Against Denial of Service Attacks
|
517 |
| Application Failure Attacks |
517 |
| CPU Starvation Attacks |
521 |
| Memory Starvation Attacks |
529 |
| Resource Starvation Attacks |
530 |
| Network Bandwidth Attacks |
532 |
| Summary |
533 |
| 18 Writing Secure .NET Code |
535 |
| Code Access Security: In Pictures |
537 |
| FxCop: A "Must-Have" Tool
|
539 |
| Assemblies Should Be Strong-Named |
540 |
| Strong-Named
Assemblies and ASP.NET |
542 |
| Specify Assembly Permission Requirements
|
542 |
| Request Minimal
Permission Set |
543 |
| Refuse Unneeded
Permissions |
544 |
| Request Optional
Permissions |
544 |
| Overzealous Use of Assert |
545 |
| Further Information Regarding Demand
and Assert |
547 |
| Keep the Assertion Window Small |
549 |
| Demands and Link Demands |
550 |
| An Example
LinkDemand Security Bug |
551 |
| Use SuppressUnmanagedCodeSecurityAttribute
with Caution |
552 |
| Remoting Demands |
553 |
| Limit Who Uses Your Code |
554 |
| No Sensitive Data in XML or Configuration
Files |
555 |
| Review Assemblies That Allow Partial
Trust |
556 |
| Check Managed Wrappers to Unmanaged
Code for Correctness |
557 |
| Issues with Delegates |
558 |
| Issues with Serialization |
558 |
| The Role of Isolated Storage |
559 |
| Disable Tracing and Debugging Before
Deploying ASP.NET Applications |
561 |
| Do Not Issue Verbose Error Information
Remotely |
561 |
| Deserializing Data from Untrusted Sources |
562 |
| Don’t Tell the Attacker Too Much When
You Fail |
562 |
| Summary |
564 |
| PART IV SPECIAL TOPICS |
|
| 19 Security Testing |
567 |
| The Role of the Security Tester |
567 |
| Security Testing Is Different |
568 |
| Building Security Test Plans from a
Threat Model |
569 |
| Decompose the
Application |
570 |
| Identify the
Component Interfaces |
570 |
| Rank the Interfaces
by Potential Vulnerability |
572 |
| Ascertain the
Data Structures Used by Each Interface |
573 |
| Attacking Applications
with STRIDE |
573 |
| Attacking with
Data Mutation |
575 |
| Before Testing
|
587 |
| Building Tools
to Find Flaws |
588 |
| Testing Clients with Rogue Servers
|
606 |
| Should a User See or Modify That Data?
|
607 |
| Testing with Security Templates |
607 |
| When You Find a Bug, You’re Not Done!
|
609 |
| Test Code Should Be of Great Quality
|
610 |
| Test the End-to-End Solution |
611 |
| Determining Attack Surface |
611 |
| Determine Root
Attack Vectors |
611 |
| Determine Bias
For Attack Vectors |
612 |
| Count the Biased
Vectors in the Product |
612 |
| Summary |
613 |
| 20 Performing a Security Code Review |
615 |
| Dealing with Large Applications |
617 |
| A Multiple-Pass Approach |
618 |
| Low-Hanging Fruit |
619 |
| Integer Overflows |
620 |
| A Related Issue:
Integer Underflows |
624 |
| Checking Returns |
624 |
| Perform an Extra Review of Pointer
Code |
625 |
| Never Trust the Data |
625 |
| Sumary |
626 |
| 21 Secure Software Installation |
627 |
| Principle of Least Privilege |
628 |
| Clean Up After Yourself! |
630 |
| Using the Security Configuration Editor |
630 |
| Low-Level Security APIs |
638 |
| Using the Windows Installer |
638 |
| Summary |
640 |
| 22 Building Privacy into Your Application |
641 |
| Malicious vs. Annoying Invasions of
Privacy |
642 |
| Major Privacy Legislation |
643 |
| Personally
Identifiable Information |
643 |
| The EU Directives
on Data Protection |
643 |
| Safe Harbor
Principles |
644 |
| Other Privacy
Legislation |
646 |
| Privacy vs. Security |
646 |
| Building a Privacy Infrastructure |
647 |
| The Role of
the Chief Privacy Officer |
648 |
| The Role of
the Privacy Advocate |
648 |
| Designing Privacy-Aware Applications |
649 |
| Including Privacy
in the Development Process |
649 |
| Exploring Privacy
Features |
652 |
| Summary |
662 |
| 23 General Good Practices |
663 |
| Don’t Tell the Attacker Anything |
663 |
| Service Best Practices |
663 |
| Security, Services,
and the Interactive Desktop |
664 |
| Service Account
Guidelines |
665 |
| Don’t Leak Information in Banner Strings
|
667 |
| Be Careful Changing Error Messages
in Fixes |
668 |
| Double-Check Your Error Paths |
668 |
| Keep It Turned Off! |
668 |
| Kernel-Mode Mistakes |
668 |
| High-Level
Security Issues |
669 |
| Handles |
670 |
| Symbolic Links
|
670 |
| Quota |
670 |
| Serialization
Primitives |
670 |
| Buffer-Handling
Issues |
671 |
| IRP Cancellation
|
673 |
| Add Security Comments to Code |
674 |
| Leverage the Operating System |
674 |
| Don’t Rely on Users Making Good Decisions
|
675 |
| Calling CreateProcess Securely |
675 |
| Do Not Pass
NULL for lpApplicationName |
677 |
| Use Quotes
Around the Path to Executable in lpCommandLine |
677 |
| Don’t Create Shared/Writable Segments
|
677 |
| Using Impersonation Functions Correctly
|
678 |
| Don’t Write User Files to \Program
Files |
678 |
| Don’t Write User Data to HKLM
|
679 |
| Don’t Open Objects for FULL_CONTROL
or ALL_ACCESS |
679 |
| Object Creation Mistakes |
679 |
| Care and Feeding of CreateFile
|
681 |
| Creating Temporary Files Securely |
682 |
| Implications of Setup Programs and
EFS |
686 |
| File System Reparse Point Issues |
686 |
| Client-Side Security Is an Oxymoron
|
687 |
| Samples Are Templates |
688 |
| Dogfood Your Stuff! |
688 |
| You Owe It to Your Users If… |
689 |
| Determining Access Based on an Administrator
SID |
689 |
| Allow Long Passwords |
690 |
| Be Careful with _alloca |
691 |
| ATL Conversion
Macros |
691 |
| Don’t Embed Corporate Names |
692 |
| Move Strings to a Resource DLL |
693 |
| Application Logging |
693 |
| Migrate Dangerous C/C++ to Managed
Code |
694 |
| 24 Writing Security Documentation and Error Messages
|
695 |
| Security Issues in Documentation |
695 |
| The Basics
|
696 |
| Threat Mitigation
Through Documentation |
697 |
| Documenting
Security Best Practices |
698 |
| Security Issues in Error Messages |
700 |
| A Typical Security Message |
700 |
| Information Disclosure Issues |
701 |
| Informed Consent |
702 |
| Progressive
Disclosure |
704 |
| Be Specific
|
705 |
| Consider Not
Asking the Question |
706 |
| Usability Test
Your Security Messages |
707 |
| A Note When Reviewing Product Specifications
|
708 |
| Security Usability |
708 |
| Summary |
709 |
| PART V APPENDIXES |
|
| A Dangerous APIs |
713 |
| B Ridiculous Excuses We’ve Heard |
723 |
| C A Designer’s Security Checklist |
729 |
| D A Developer’s Security Checklist |
731 |
| E A Tester’s Security Checklist |
737 |
| A Final Thought |
739 |
| ANNOTATED BIBLIOGRAPHY |
741 |
| INDEX |
747 |