SQLSecurity Checklist   
 
http://www.sqlsecurity.com

1. Make sure the latest OS and SQL Server Service Packs/Hot-Fixes are applied.  This goes without saying but I'll say it anyway for completeness.
 
2. Evaluate and choose a network protocol library that allows for maximum security but doesn’t break functionality. Since SQL Server 2000 it's becoming increasingly obvious that Microsoft intends TCP/IP to be the net-lib of choice. The question now is really whether to use SSL for SQL Server access or not.
 
3. Secure the “sa” and “probe” (SQL 6.5) accounts with strong passwords. Assign a strong password and lock away the password in a secure location. Note: The probe account is used for performance analysis and distributed transactions. Assigning a password to this account can break functionality when used in standard security mode.
 
4. Use a low-privilege user account for SQL Server service rather than LocalSystem or Administrator. This account should olny have minimal rights (note that Run as a Service Right will be required) and should help contain (but not stop) an attack to the server in case of compromise. Notice that when using Enterprise Manager to make this change, the ACLs on files, the registry, and user rights are done for you automatically.
 
5. Make sure all SQL Server data and system files are installed on NTFS partitions and the appropraite ACLs are applied. If someone should gain access to the OS, make sure that the necessary permissions are in place to prevent a catastrophe.  
 
6. Drop master..Xp_cmdshell if you can do without it. If using SQL 6.5, at least use the SQLExecutieCmdExec account option in “Server Options” to limit the rights when non-“sa” users use xp_cmdshell.  

In any isql/osql window (or Query Analyzer):

use master
exec sp_dropextendedproc 'xp_cmdshell'

For the SQLExecutiveCmdExec check the following KB article first:

http://support.microsoft.com/support/kb/articles/Q159/2/21.asp

If you don't need xp_cmdshell the PLEASE drop it.  Sleep better.  Just remember that a system administrator can always add it back if need be.  This is good and bad - an intruder may find it missing an simply add it back.  Consider removing the underlying dll as well but test first since the same dll is used for several procedures. To find other procedures using the same dll try:

First get the dll.

select o.name,c.text from dbo.syscomments c, dbo.sysobjects o where c.id = o.id and o.name = 'xp_cmdshell' 

Second, find the other extended stored procs using that same dll.

select o.name,c.text from dbo.syscomments c, dbo.sysobjects o where c.id = o.id and c.text = 'xplog70.dll' 

Use can use this method with any other procedures you wish to drop in the following steps. 

 
7. Drop OLE automation stored procedures if you can do without them (warning - some Enterprise Manager features may be lost when these stored procedures are dropped) . These include:

Sp_OACreate 

Sp_OADestroy 

Sp_OAGetErrorInfo 

Sp_OAGetProperty 

Sp_OAMethod 

Sp_OASetProperty 

Sp_OAStop

If you decide to drop procedures then script it so that you can add them back en-masse if you need full functionality in the future.  Remember, what we're doing here is locking down a production app - your development platform should be done on machines elsewhere.

 
8. Drop registry access procedures that you don’t need. (Same warnings as above) These include:

Xp_regaddmultistring 

Xp_regdeletekey 

Xp_regdeletevalue 

Xp_regenumvalues 

Xp_regremovemultistring 

Note : I used to list xp_regread/xp_regwrite here but removal of these procedures breaks several key features including log truncation and service pack installation so their removal is not recommended.

 
9. Delete other system stored procedures that you believe could pose a threat. There are quite a few of them, and this could take some time. Be careful not to do this on a production server first. Test on a development machine so you don’t break any functionality.  Below is a list of the ones we recommend you assess:

sp_sdidebug
xp_availablemedia
xp_cmdshell
xp_deletemail
xp_dirtree
xp_dropwebtask
xp_dsninfo
xp_enumdsn
xp_enumerrorlogs
xp_enumgroups
xp_enumqueuedtasks
xp_eventlog
xp_findnextmsg
xp_fixeddrives
xp_getfiledetails
xp_getnetname
xp_grantlogin
xp_logevent
xp_loginconfig
xp_logininfo
xp_makewebtask
xp_msver xp_perfend
xp_perfmonitor
xp_perfsample
xp_perfstart
xp_readerrorlog
xp_readmail
xp_revokelogin
xp_runwebtask
xp_schedulersignal
xp_sendmail
xp_servicecontrol
xp_snmp_getstate
xp_snmp_raisetrap
xp_sprintf
xp_sqlinventory
xp_sqlregister
xp_sqltrace
xp_sscanf
xp_startmail
xp_stopmail
xp_subdirs
xp_unc_to_drive
xp_dirtree 

 
 
10. Disable Default Login under “Security Options” in Enterprise Manager (SQL 6.5 only). When using Integrated security, this keeps unauthorized users from accessing the server without a valid entry in the syslogins table. 
11. Remove the Guest user from databases to keep unauthorized users out.  The exception to this is the master and tempdb databases as the guest account is required. 
12. Disable SQL Mail capability unless absolutely necessary. Leaving it open gives a potential attacker another means of delivering potential trojans, viruses, or simply launching a particularly nasty denial of service attack.
 
13. Check master..Sp_helpstartup for trojan procedures. Make sure no one has placed a backdoor here. Use Sp_unmakestartup to remove any rogue procedures.
 
14. Check master..Sp_password for trojan code. Compare your production scripts to the default script on a fresh installation and keep that code handy. 
15. Enable logging of all user access.  Do this from Enterprise Manager or by entering the following into the Query Analyzer as 'sa':
xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'SOFTWARE\Microsoft\MSSQLServer\MSSQLServer',N'AuditLevel', REG_DWORD,3

Before the drop the procedure of course ;-]

 
16. Rewrite applications to use more user-defined stored procedures and views so general access to tables can be removed. You should also see some performance improvement here as query execution plans won’t be performed as often. 
17. Remove unneeded network protocol libraries. 
18. Physically secure the SQL Server. Lock it behind a door and lock away the key while you’re at it.  Someone sitting in front of the server will always find a way. 
19. Set up a scheduled task to run:
findstr /C:"Login Failed" \mssql7\log\*.*'

and redirect to the output to a text file or email so you can monitor failed login attempts. This also provides a good way for administrators to document attacks. There are also many third-party tools for analyzing NT event logs. Note: You may need to change the path for the log files based on your installation and SQL Server version.
 
20. Set alerts to log failed object access and logins. Go to “Manage SQL Server Messages” in Enterprise Manager and search for any messages relating to permission denial (start by searching for “Login Failed” or “denied”). Make sure any messages you’re interested in are logged to the event log. Next, set up an alert on that message or severity level 14 to send an email or page to an operator who can quickly react to the issue.
 
21. Make sure roles at the server and database levels are only assigned to the users who need them. While the SQL Server 7 security model has many enhancements, it also adds the extra layer of permissions that we must monitor to make sure no one has been given more access than they need or that they’ve already circumvented security to elevate themselves. 
 
22. Frequently check group or role memberships and make sure to assign permissions by group so your auditing tasks can be simplified. Make sure the public group can’t issue SELECT statements against system tables while you’re at it. 
23. Take the time to audit for logins with null passwords. Use the following code to check for null passwords:
Use master
Select name,
      Password
from syslogins
where password is null
order by name
 
24. Make use of integrated security if feasible in your organization. By using integrated security, you can greatly simplify administration by relying on the OS security and saving yourself from maintaining two separate security models.  This also keeps passwords out of connection strings. 
25. Check access permissions for all non-“sa”s on stored procs and extended stored procs. Use the following query to periodically query which procedures have public access: (Use “type” instead of “xtype” for SQL 6.5):
Use master
Select sysobjects.name
From sysobjects, sysprotects
Where sysprotects.uid = 0
AND xtype IN ('X','P')
AND sysobjects.id = sysprotects.id
Order by name
 
26. Use integrated security when accessing Enterprise Manager. In the past, Enterprise Manager has been found to store the “sa” password in plaintext in the registry when in standard security mode. Note: Even if you change modes, the password remains in the registry. Use regedit and check this key:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\
MSSQLServer\SQLEW\Registered Server\
SQL 6.5

Currently the data is buried (and apparently encrypted although I have not taken a long hard look) in

HKEY_USERS\{yourSID}\Software\Microsoft\Microsoft SQL Server\80\Tools\SQLEW\Registered Servers X\SQL Server Group

(The "SQL Server Group" is the default but you may have created custom groups so change the location accordingly)
 
27. Develop an audit plan and make monthly security reports available to IT administration that includes any new exploits, successful attacks, backup storage protection, and object access failure statistics. 
28. Never allow users to log on to the SQL Server interactively.  This tip goes for any server.   Once a user can interactively log into a server, there are myriad of privilege escalation attacks that can be used to obtain Administrative access.   
30. Do your best to limit ad-hoc access to the SQL Server. There are many things a user can query inside the SQL Server even with minimal privileges.  Don't give them the chance if you don't have to.