<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>tinyint.com &#187; SQL</title>
	<atom:link href="http://www.tinyint.com/index.php/category/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tinyint.com</link>
	<description>An engineering and development &#60;em&#62;Factory of Knowledge&#60;/em&#62;™</description>
	<lastBuildDate>Mon, 09 Aug 2010 19:41:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>sp_help_revlogin cleaned up and revised with roles</title>
		<link>http://www.tinyint.com/index.php/2009/07/08/sp_help_revlogin-cleaned-up-and-revised-with-roles/</link>
		<comments>http://www.tinyint.com/index.php/2009/07/08/sp_help_revlogin-cleaned-up-and-revised-with-roles/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 23:19:02 +0000</pubDate>
		<dc:creator>tcnolan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[revlogin]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[sql 2005]]></category>

		<guid isPermaLink="false">http://www.tinyint.com/?p=81</guid>
		<description><![CDATA[When working with SQL Server there are often times where you will need to script your logins over to another server such as when you have database mirroring or log shipping configured for certain databases.   This is such a common thing that Microsoft provides in-depth instructions on how to do this as well as [...]]]></description>
			<content:encoded><![CDATA[<p>When working with SQL Server there are often times where you will need to script your logins over to another server such as when you have database mirroring or log shipping configured for certain databases.   This is such a common thing that Microsoft provides in-depth instructions on how to do this as well as the T-SQL code required to do it, which you can read more about here: <a href="http://support.microsoft.com/kb/918992" target="_blank">http://support.microsoft.com/kb/918992</a>.  The script they provide is missing a few things so I took a little time to clean up the code, revise some of it, and add in a few of the missing pieces.</p>
<p>The three things that are overlooked in the Microsoft article that I have included are default language and default database (being mandatory) for logins as well as the scripting of roles.  The lack of the default language is pretty minor, but it&#8217;s something that could be important to people so I am including it in my script.  The lack of default databases being an option in the Microsoft script is not a big deal because it assumes you are scripting everything, but if you are only concerned with logins that are specific to a certain database you will get errors if you haven&#8217;t created that database on the target.  The lack of server roles is another important one that I have needed in previous configurations so it is also included here.  The resulting script is pretty long so you can check out the source of the revised procedure after the jump, which includes the sp_hexadecimal script from the Microsoft article.</p>
<p>Additionally, something just as important as the revlogin script itself is the question of <em>“Well now that I have this script, how do I schedule this to happen automatically for me instead of just generating more code that I have to execute on the target server?”</em> If you are asking that question then you might want to take a look at the next block of code.  In order to automate sp_help_revlogin there are a few options, but the one that I prefer over all else is using osql and a SQL Agent job with a single T-SQL step because it is very simple to implement in most server configurations.  The following script is relatively straight forward in that you only have one variable, the target server, to worry about.  The only pre-requisites being that xp_cmdshell is enabled and that the Windows account that the job is being executed under has sysadmin rights to both servers.  This script could easily be turned into a stored procedure but for the sake of brevity I have included it in its shortest form.</p>
<p><em><strong>Disclaimer: Use these scripts at your own risk!!</strong></em></p>
<pre class="brush: sql;">
-- Declare and set the target server...
DECLARE @TargetServer SYSNAME
SET @TargetServer = N'DB1.DOMAIN.LOCAL'

-- Define a temporary file to store the script output
DECLARE @guidfile VARCHAR(160)
SET @guidfile = '%TEMP%\' + CONVERT(SYSNAME, NEWID()) + '.txt'

-- execute sp_help_revlogin_roles and save the output to the temp file
DECLARE @cmd VARCHAR(8000)
SET @cmd = 'osql -E -n -h-1 -d master -w 8000 -Q &quot;exec sp_help_revlogin_roles&quot; -o &quot;' + @guidfile + '&quot;'
EXEC master.dbo.xp_cmdshell @cmd

-- execute the temp file on the target server
SET @cmd = 'osql -E -S ' + @TargetServer + ' -d master -w 8000 -i &quot;' + @guidfile + '&quot;' --' syntaxhighlighter fail <img src='http://www.tinyint.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />
EXEC master.dbo.xp_cmdshell @cmd

-- delete the temp file
SET @cmd = 'del &quot;' + @guidfile + '&quot;'
EXEC master.dbo.xp_cmdshell @cmd
</pre>
<p><span id="more-81"></span></p>
<p>Here is the code for the revised sp_help_revlogin which I renamed as sp_help_revlogin_roles to avoid confusion</p>
<pre class="brush: sql;">
USE master
GO

IF OBJECT_ID ('sp_hexadecimal') IS NOT NULL
	DROP PROCEDURE sp_hexadecimal
GO

CREATE PROCEDURE sp_hexadecimal
	@binvalue varbinary(256),
	@hexvalue varchar (514) OUTPUT
AS
BEGIN
	SET NOCOUNT ON
	DECLARE @charvalue varchar (514)
	DECLARE @i int
	DECLARE @length int
	DECLARE @hexstring char(16)

	SELECT @charvalue = '0x'
	SELECT @i = 1
	SELECT @length = DATALENGTH (@binvalue)
	SELECT @hexstring = '0123456789ABCDEF'

	DECLARE @tempint int
	DECLARE @firstint int
	DECLARE @secondint int
	WHILE (@i &lt;= @length)
	BEGIN
		SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
		SELECT @firstint = FLOOR(@tempint/16)
		SELECT @secondint = @tempint - (@firstint*16)
		SELECT @charvalue = @charvalue +
		SUBSTRING(@hexstring, @firstint+1, 1) +
		SUBSTRING(@hexstring, @secondint+1, 1)
		SELECT @i = @i + 1
	END

	SELECT @hexvalue = @charvalue
END
GO

USE master
GO

IF OBJECT_ID ('sp_help_revlogin_roles') IS NOT NULL
	DROP PROCEDURE sp_help_revlogin_roles
GO
CREATE PROCEDURE sp_help_revlogin_roles
	@login_name sysname=NULL,
	@databases bit=1,
	@roles bit=1
AS
BEGIN
	SET NOCOUNT ON
	DECLARE @name sysname
	DECLARE @role sysname
	DECLARE @type varchar (1)
	DECLARE @hasaccess int
	DECLARE @denylogin int
	DECLARE @is_disabled int
	DECLARE @PWD_varbinary  varbinary (256)
	DECLARE @PWD_string  varchar (514)
	DECLARE @SID_varbinary varbinary (85)
	DECLARE @SID_string varchar (514)
	DECLARE @is_policy_checked varchar (3)
	DECLARE @is_expiration_checked varchar (3)
	DECLARE @defaultdb sysname
	DECLARE @defaultlang sysname
	DECLARE @crlf varchar(2)
	DECLARE @return int

	SET @crlf = CHAR(13) + CHAR(10)

	PRINT '/* sp_help_revlogin script '
	PRINT '** Generated ' + CONVERT (varchar, GETDATE()) + ' on ' + @@SERVERNAME + ' */'
	PRINT ''
	PRINT '/* Begin Script Logins ------------------------- */'

	IF (@login_name IS NULL)
	BEGIN
		DECLARE rev_cursor CURSOR STATIC READ_ONLY FOR
			SELECT p.sid, p.name, p.type, p.is_disabled, ISNULL(p.default_database_name, 'master'), ISNULL(p.default_language_name, 'us_english'), l.hasaccess, l.denylogin
			FROM sys.server_principals p
			LEFT JOIN sys.syslogins l
				ON ( l.name = p.name )
			WHERE p.type IN ( 'S', 'G', 'U' )
				AND p.name &lt;&gt; 'sa'
	END
	ELSE
	BEGIN
		DECLARE rev_cursor CURSOR STATIC READ_ONLY FOR
			SELECT p.sid, p.name, p.type, p.is_disabled, ISNULL(p.default_database_name, 'master'), ISNULL(p.default_language_name, 'us_english'), l.hasaccess, l.denylogin
			FROM sys.server_principals p
			LEFT JOIN sys.syslogins l
				ON ( l.name = p.name )
			WHERE p.type IN ( 'S', 'G', 'U' )
				AND p.name = @login_name
	END

	OPEN rev_cursor

	FETCH NEXT FROM rev_cursor
		INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @defaultlang, @hasaccess, @denylogin

	IF (@@FETCH_STATUS = -1)
	BEGIN
		PRINT 'No login(s) found.'
		SELECT @return = -1
		GOTO Quit
	END

	WHILE (@@FETCH_STATUS = 0)
	BEGIN
		SELECT @name=LTRIM(RTRIM(@name))
		PRINT '-- Login: ' + @name
		IF (@type IN ( 'G', 'U'))
		BEGIN -- NT authenticated account/group
			PRINT 'IF NOT EXISTS ( SELECT * FROM sys.server_principals WHERE name = ''' + @name + ''' )'
			PRINT '	CREATE LOGIN ' + QUOTENAME( @name ) + ' FROM WINDOWS WITH DEFAULT_DATABASE = [' + @defaultdb + ']'
		END
		ELSE BEGIN -- SQL Server authentication
			-- obtain password and sid
			SET @PWD_varbinary = CAST( LOGINPROPERTY( @name, 'PasswordHash' ) AS varbinary (256) )
			EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT
			EXEC sp_hexadecimal @SID_varbinary, @SID_string OUT

			-- obtain password policy state
			SELECT @is_policy_checked =
				CASE is_policy_checked
					WHEN 1 THEN 'ON'
					WHEN 0 THEN 'OFF'
					ELSE NULL
				END
			FROM sys.sql_logins
			WHERE name = @name

			SELECT @is_expiration_checked =
				CASE is_expiration_checked
					WHEN 1 THEN 'ON'
					WHEN 0 THEN 'OFF'
					ELSE NULL
				END
			FROM sys.sql_logins
			WHERE name = @name

			PRINT
				'IF NOT EXISTS ( SELECT * FROM sys.server_principals WHERE name = ''' + @name + ''' )' + @crlf +
				'	CREATE LOGIN ' + QUOTENAME( @name ) + @crlf +
				'		WITH PASSWORD = ' + @PWD_string + ' HASHED, ' + @crlf +
				'		SID = ' + @SID_string + ', ' + @crlf +
				'		DEFAULT_LANGUAGE = [' + @defaultlang + ']' +
				CASE WHEN ( @is_policy_checked IS NOT NULL ) THEN ',' + @crlf + '		CHECK_POLICY = ' + @is_policy_checked END +
				CASE WHEN ( @is_expiration_checked IS NOT NULL ) THEN ',' + @crlf + '		CHECK_EXPIRATION = ' + @is_expiration_checked END +
				';'
		END

		IF (@denylogin = 1)
		BEGIN -- login is denied access
			PRINT 'DENY CONNECT SQL TO ' + QUOTENAME( @name )
		END
		ELSE IF (@hasaccess = 0)
		BEGIN -- login exists but does not have access
			PRINT 'REVOKE CONNECT SQL TO ' + QUOTENAME( @name )
		END
		IF (@is_disabled = 1)
		BEGIN -- login is disabled
			PRINT 'ALTER LOGIN ' + QUOTENAME( @name ) + ' DISABLE'
		END

		PRINT ' '
		PRINT ' '
		FETCH NEXT FROM rev_cursor
			INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @defaultlang, @hasaccess, @denylogin
	END
	PRINT '/* End Script Logins ------------------------- */'
	PRINT ' '
	PRINT ' '

	IF @databases=1
	BEGIN
		FETCH FIRST FROM rev_cursor
			INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @defaultlang, @hasaccess, @denylogin
		PRINT '/* Begin Script Default Databases ------------------------- */'
		WHILE (@@FETCH_STATUS=0)
		BEGIN
			PRINT '-- Login: ' + @name
			PRINT 'IF EXISTS ( SELECT * FROM sys.server_principals WHERE name = ''' + @name + ''' )'
			PRINT '	ALTER LOGIN ' + QUOTENAME( @name ) + ' WITH DEFAULT_DATABASE = [' + @defaultdb + ']'
			PRINT ' '

			FETCH NEXT FROM rev_cursor
				INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @defaultlang, @hasaccess, @denylogin
		END
		PRINT '/* End Script Default Databases ------------------------- */'
		PRINT ' '
		PRINT ' '
	END
	CLOSE rev_cursor
	DEALLOCATE rev_cursor

	IF @roles=1
	BEGIN
		PRINT '/* Begin Script Roles ------------------------- */'
		DECLARE rev_cursor CURSOR STATIC READ_ONLY FOR
			SELECT p1.name role_principal_name, p2.name member_principal_name FROM sys.server_role_members rm
			INNER JOIN sys.server_principals p1
				ON p1.principal_id=rm.role_principal_id
			INNER JOIN sys.server_principals p2
				ON p2.principal_id=rm.member_principal_id
			WHERE
				p2.type IN ( 'S', 'G', 'U' )
				AND p2.name &lt;&gt; 'sa'
			ORDER BY p2.principal_id
		OPEN rev_cursor

		FETCH NEXT FROM rev_cursor
			INTO @role, @name
		IF (@@FETCH_STATUS = -1)
		BEGIN
			PRINT '-- No role member(s) found.'
		END

		WHILE (@@FETCH_STATUS = 0)
		BEGIN
			PRINT 'EXEC master.dbo.sp_addsrvrolemember @loginame=''' + @name + ''', @rolename=''' + @role + ''''

			FETCH NEXT FROM rev_cursor
				INTO @role, @name
		END
		PRINT '/* End Script Roles ------------------------- */'
		PRINT ' '
		PRINT ' '

		CLOSE rev_cursor
		DEALLOCATE rev_cursor
	END

	SELECT @return = 0

	Quit:
		RETURN @return

END
GO
</pre>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.tinyint.com%2Findex.php%2F2009%2F07%2F08%2Fsp_help_revlogin-cleaned-up-and-revised-with-roles%2F&amp;linkname=sp_help_revlogin%20cleaned%20up%20and%20revised%20with%20roles"><img src="http://www.tinyint.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.tinyint.com/index.php/2009/07/08/sp_help_revlogin-cleaned-up-and-revised-with-roles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The problem with SQL Injection&#8230;</title>
		<link>http://www.tinyint.com/index.php/2009/03/23/the-problem-with-sql-injection/</link>
		<comments>http://www.tinyint.com/index.php/2009/03/23/the-problem-with-sql-injection/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 21:36:51 +0000</pubDate>
		<dc:creator>tcnolan</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[asp]]></category>
		<category><![CDATA[iis]]></category>
		<category><![CDATA[queries]]></category>
		<category><![CDATA[sql 2005]]></category>
		<category><![CDATA[sql injection]]></category>
		<category><![CDATA[xkcd]]></category>

		<guid isPermaLink="false">http://www.tinyint.com/?p=6</guid>
		<description><![CDATA[I know it&#8217;s an old comic, but XKCD really hit the nail on the head with this one.  It is something that I deal with on a regular basis and I think there are a lot of people out there who still don&#8217;t really understand the concept of SQL Injection, how it works, and how [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://xkcd.com/327/" target="_blank"><img class="alignnone" title="Exploits of a Mom - XKCD" src="http://imgs.xkcd.com/comics/exploits_of_a_mom.png" alt="Oh yes, Little Bobby Tables we call him." width="100%" /></a></p>
<p>I know it&#8217;s an old comic, but XKCD really hit the nail on the head with this one.  It is something that I deal with on a regular basis and I think there are a lot of people out there who still don&#8217;t really understand the concept of SQL Injection, how it works, and how to get away from it.  While working with a client who fell victim to a SQL Injection attack on their website, I wrote some information for them to take and use as reference for what SQL Injection is, how to prevent it, and what to do about it when it happens.  I have generalized that info and hopefully it can help some others.</p>
<p>If you look at the snippet below you have an example of what might show up in your IIS logs if you were hit by one of the many sql injection attacks that have been going around the internet recently. I have changed the information to be similar to one of these common attacks, but modified to be something non-malicious. You can read more about the common attacks that have been happening lately here: <a href="http://forums.iis.net/p/1148917/1867511.aspx" target="_blank">http://forums.iis.net/p/1148917/1867511.aspx</a> What the common attacks do, is they search through your entire database and find all varchar, nvarchar, text, and ntext values in every table in the database and update their values to include a reference to a malicious JavaScript on specific websites. Then, when your site displays the value of those fields, you end up displaying the malicious code to the visitors of your site through the new value inserted by the attack. Once that happens the JavaScript can take advantage of any unpatched vulnerabilities on the victims machine and possibly install a virus or spyware. Interestingly, some of these viruses will actually make it so as you are browsing websites it runs SQL injection tests on each of the pages you visit, and when it finds one it will exploit it the same way it was exploited upon you, making the victim the attacker.</p>
<pre class="brush: plain;">2009-03-123 14:59:33 209.73.25.65 GET /page.asp id=248;DECLARE%20@S%20VARCHAR(4000);SET%20@S=CAST(0x435245415445205441424C45205B64626F5D2E5B546573745D280D0A095B69645D205B696E745D204944454E5449545928312C3129204E4F54204E554C4C2C0D0A095B76616C7565315D205B766172636861725D2835313229204E4F54204E554C4C2C0D0A095B76616C7565325D205B6269745D204E4F54204E554C4C2C0D0A090D0A09434F4E53545241494E54205B504B5F546573745D205052494D415259204B455920434C5553544552454420280D0A09095B69645D204153430D0A0929205749544820280D0A09095041445F494E44455820203D204F46462C200D0A0909535441544953544943535F4E4F5245434F4D5055544520203D204F46462C200D0A090949474E4F52455F4455505F4B4559203D204F46462C200D0A0909414C4C4F575F524F575F4C4F434B5320203D204F4E2C200D0A0909414C4C4F575F504147455F4C4F434B5320203D204F4E0D0A0929204F4E205B5052494D4152595D0D0A29204F4E205B5052494D4152595D3B0D0A0D0A414C544552205441424C45205B64626F5D2E5B546573745D204144442020434F4E53545241494E54205B44465F546573745F76616C7565325D202044454641554C5420282831292920464F52205B76616C7565325D3B%20AS%20VARCHAR(4000));EXEC(@S);--|23|800a000d|Type_mismatch:_'[string:__248;DECLARE_@S_VARCH_]' 80 - 83.25.197.62 Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+5.1;+.NET+CLR+2.0.50727) 500 0 0
</pre>
<p>If this happens to your site, first and foremost you will need to restore your old data into your database to get back what was lost and to remove the dangerous scripts from your webpage so it doesn’t hurt any visitors. If you do not have the option of shutting your site down while you protect the code from SQL injection, it is best to restore the data afterwards, since it could end up being wasted time if someone does SQL injection after the data is restored and before you protect all of the code. Once you have the data restored or before if you can&#8217;t take down the site temporarily, you still have to update the vulnerable code on your web application(s). Keep in mind that the location of this code depends on how your site was developed and set up, but it could be anywhere that SQL is called to pull information to display on the site through a querystring telling the page to load a certain database record or where user input is allowed and not validated. These pages would be vulnerable and would need to be fixed.</p>
<p>The part of that querystring from the &#8220;;DECLARE&#8221; to the &#8220;&#8211;&#8221; is the actual SQL injection code. SQL Server will interperet that because the attacker put a semi-colon after the id number. This tells SQL &#8220;this is the end of the command, remaining text is a new command.&#8221; Then the &#8220;&#8211;&#8221; tells SQL that the rest is a comment so that in case you are doing other things like sorting the results or grouping anything will not be recognized and SQL will execute the whole command. The CAST part actually just takes a binary value and converts it to a string. The value above converts to the following block of code and just creates a dummy table, whereas a malicious attacker would be doing something much worse.</p>
<pre class="brush: sql;">CREATE TABLE [dbo].[Test](
[id] [int] IDENTITY(1,1) NOT NULL,
[value1] [varchar](512) NOT NULL,
[value2] [bit] NOT NULL,

CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED (
[id] ASC
) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY];

ALTER TABLE [dbo].[Test] ADD CONSTRAINT [DF_Test_value2] DEFAULT ((1)) FOR [value2];
</pre>
<p>The next snippet is a perfect example of vulnerable code that would allow SQL injection through. While I am using classic ASP for my example, it could really be any language that doesn&#8217;t have a built in mechanism for checking your SQL queries such as PHP, Perl, ASP.Net, etc. Any page which executes an ad hoc SQL query based on a query string passed in or user input, without being validated, will be vulnerable to SQL injection. Instead of using something like conn.execute(“select * from [table] where value=” &amp; request(“parameter”)) you should instead be either using a stored procedure to pass the value (see: <a href="http://www.asp101.com/samples/viewasp.asp?file=storedprocs.asp" target="_blank">http://www.asp101.com/samples/viewasp.asp?file=storedprocs.asp</a>) or at the very least you should be checking the query string parameter for validity before inserting it into your query.</p>
<pre class="brush: vb;">strSQL = &quot;select * from table_name where id_column=&quot; &amp; REQUEST(&quot;id&quot;) &amp; &quot; order by sort_column&quot;
SET objDB = objConn.EXECUTE ( strSQL )
</pre>
<p>While stored procedures are the best way to protect yourself, there are still instances where you could have a problem such as if you used a stored procedure where the code was actually generating a dynamic SQL statement internally based on parameters that were passed in, so you would have to protect those SPROCs as well from characters that can cause problems. See also: <a href="http://msdn.microsoft.com/en-us/library/ms161953.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/ms161953.aspx</a> and <a href="http://www.sqlsecurity.com/FAQs/SQLInjectionFAQ/tabid/56/Default.aspx" target="_blank">http://www.sqlsecurity.com/FAQs/SQLInjectionFAQ/tabid/56/Default.aspx</a> There are many &#8220;paged results&#8221; stored procedures around where you can say essentially &#8220;give me the records for page 4 when we have 50 records per page&#8221; and mose of these are vulnerable to the same issue because they make use of adhoc queries such as the one below. The following snippet shows an example of a stored procedure that would not save you here.</p>
<pre class="brush: sql;">CREATE PROCEDURE usp_mySelectFromNameTable
@mName varchar(50),
@mTable varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @query varchar(150)
SET @query = 'select id from ' + @mTable + ' where user_name=''' + @mName + ''''
EXEC(@query)
END
</pre>
<p>In the future, when writing code that will interface with your database, you should always be using parameterized queries for accessing information from the database. It takes a little extra code and effort, but in the long run you are much safer this way. If there were ever a case where you were storing usernames, passwords, and other personal data, in theory someone could use SQL injection to actually retrieve that information from your database and would have access to any other information available as well.</p>
<p>SQL Injection is a very real problem(<a href="http://news.google.com/news?hl=en&amp;q=sql+injection+attack" target="_blank">http://news.google.com/news?hl=en&amp;q=sql+injection+attack</a>) that is continually being exploited due to lazy programmers, sloppy coding, or sadly, sometimes when a developer is just rushed through a project and they forget. We all need to remember to do proper checks of our inputs and paramaterize our queries and hopefully this issue will be less of a problem&#8230; at least until the next technology comes out with a different way to exploit it.</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.tinyint.com%2Findex.php%2F2009%2F03%2F23%2Fthe-problem-with-sql-injection%2F&amp;linkname=The%20problem%20with%20SQL%20Injection%26%238230%3B"><img src="http://www.tinyint.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.tinyint.com/index.php/2009/03/23/the-problem-with-sql-injection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
