Quantcast
Channel: IT Security Lab » ms sql
Viewing all articles
Browse latest Browse all 2

Playing With Cache Plan in MS SQL

$
0
0

Keeping sensitive data in database in plain text is extremely stupid and dangerous - everybody knows it. It's a sin. It should be prohibited, and all DBAs and developers who made such horrible mistake may be publicly crucified by mad IT crowd, and for sure will go to a very hot part of Hell in their afterlife. ;) That's why every programmer (ok,  every more-or-less smart programmer, able to use Google) which desires to avoid such horrible consequences knows the typical solution. Here it comes. Imagine: I need to have passwords stored for authentication purposes. I can't keep it in a plain text in database (see above why). So what I can do: I may keep the hash of the password instead of the password in plain text. Then, in authentication procedure, user provides his password which is hashed again and then two hashes are compared. If they are equal - user is authenticated. Simple, isn't it. Same approach may be used when we are storing any other sensitive information, e.g. credit card numbers, etc.

But life is not so simple. And it is quite easy to make a mistake, because of... a good intentions. If you design the IT system, which is dealing with the databases, ideally you want to separate all DB-related functionality from the rest as much as possible. You probably would be happy use the DB engine for majority of the DB-related tasks, which is absolutely ok. So if there is a chance to use hashing functionality on database side - why not to use it, right? Well, in this particular case this is wrong and I will tell you why.

In MS SQL there is a nice way to get the hash of the data: function called HashBytes(). So if you want to store the credit card number by secure way you may execute something like this:

SELECT HashBytes('SHA1', '4268-2268-1003-2943')

or

SELECT HashBytes('MD5', '4268-2268-1003-2943')

which gives you:

0xF6DAF921E622914D73BC65F235B5333E

Looks fine, isn't it? So considering everything above we should feel reasonably safe by executing something like this, right:

INSERT INTO credit_cards (card_number) VALUES (HashBytes('MD5', '4268-2268-1003-2943'))

So this is not safe, my friend. Because the DB engine compiles the query before execution, optimizes it etc. - it temporarily stores the plain text of the entire SQL  statement in its internal tables for a further processing, and well, this data can be happily retrieved from those tables.

Let's see this example. Ok, so we have stored credit card number this way:

INSERT INTO credit_cards (card_number) VALUES (HashBytes('MD5', '4268-2268-1003-2943'))

Let's imagine that some smart-ass just got unauthorised access to our database, enumerated tables and discovered some juicy stuff: the table called "credit_cards" (oh yea, baby!). Happy day for the attacker, indeed! So what the guy is doing? Of course:

SELECT top 10 card_number FROM credit_cards

What he sees (throwing curses, for sure):

So is everything tip-top? Well, not quite. Atttacker may try to execute the following query:

SELECT st.text, stat.creation_time, stat.last_execution_time
FROM sys.dm_exec_cached_plans AS plans
OUTER APPLY sys.dm_exec_sql_text(plan_handle) AS st
JOIN sys.dm_exec_query_stats AS stat ON stat.plan_handle = plans.plan_handle
WHERE cacheobjtype = 'Compiled Plan'
ORDER BY stat.last_execution_time DESC

This gives him a chance to access the text of the last SQL queries compiled by DB engine.

There are several limitations for such operation, but in this case the important thing is that attacker is still able to view something that he should not. Quick solution: you should store the data which is already hashed or encrypted:

INSERT INTO credit_cards (card_number) VALUES ('F6DAF921E622914D73BC65F235B5333E')

More information about it: MSDN: Plan Caching in SQL Server 2008. Have fun, boys-n-girls. :)


Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images