SQL Server Management Studio: How to edit MD5 value - sql-server

I have table [user], created in SQL Server Management Studio, with this structure:
id int PRIMARY NOT NULL
login varchar(255) NOT NULL
password varchar(32) NOT NULL
Now, I want to insert first user into database. Right click to table [user], choose Edit top 200 rows and type new user values into the grid:
id | login | password
1 | admin | MD5('admin')
But after save, inserted password is MD5('admin'), but I expect the 21232f297a57a5a743894a0e4a801fc3 hash.
How can I do that in Microsoft SQL Server Management Studio?
Thanks
P.S. I am using SQL Server 2008 Express 10.50.1600.1 and Microsoft SQL Server Management Studio 10.50.1600.1.

hash values are byte arrays, not character strings. Use VARBINARY column type.
Do not insert MD5 of unsalted passwords. It takes 2.96 seconds to reverse crack online the hash to the password. Use a properly salted password and write the salt in the table.
Right click to table [user], choose Edit top 200 rows and type new user values into the grid. Well, what do you expect? The table edit is a feature to enter values, and if you enter the string MD5('admin') then the value in the table will be... MD5('admin'). It is not an interactive function evaluator (aside from MD5 not being a SQL Server function...)
Do not reinvent the wheel, specially do not reinvent a security wheel if you don't speak fluent crypto. Most frameworks have modules for membership management. Eg. Introduction to Membership.

You cannot run queries in grid tables, you have to run query to do update. To calculate MD5 you can use:
CONVERT(VARCHAR(32), HashBytes('MD5', 'admin'), 2)

The Edit Top 200 Rows feature is for interactive data entry, where only values are accepted, not expressions that need to be evaluated before being stored.
If you want the actual value inserted to be the result of an expression, use a query window to insert the data. (I don't know if you used the Edit feature merely because you wanted to try that functionality or for some other reason, but if that was because you didn't know how to insert data using SQL, take a look at this manual.)
Also, as #Damien has correctly noted, there's no MD5 function in Transact-SQL. There is one called HASHBYTES, which can use various hashing algorithms, including MD5. But the result of this function is varbinary, not varchar. For MD5 specifically, it is varbinary(16). To store the direct result of HASHBYTES, therefore, you'll need to change the type of the password column accordingly.
So, change the type of the column, then open a new query window and type in a command (or statement) to insert the data. The one that should do the job for you might look something like this:
INSERT INTO user (id, login, password)
VALUES (1, 'admin', HASHBYTES('MD5', 'admin'));
To be fair, you may omit changing the column type, in which case you'll need to replace the simple HASHBYTES call like above with one like in #Garath's answer. Whether you really need to store the hashes as varchar(32) instead of varbinary(16) is an entirely different question, though.

Related

REST Backend with specified columns, SQL questions

I'm working with a new REST backend talking to a SQL Server. Our REST api allows for the caller to pass in the columns/fields they want returned (?fields=id,name,phone).
The idea seems very normal. The issue I'm bumping up against is resistance to dynamically generating the SQL statement. Any arguments passed in would be passed to the database using a parameterized query, so I'm not concerned about SQL injection.
The basic idea would be to "inject" the column-names passed in, into a SQL that looks like:
SELECT <column-names>
FROM myTable
ORDER BY <column-name-to-sort-by>
LIMIT 1000
We sanitize all column names and verify their existence in the table, to prevent SQL injection issues. Most of our programmers are used to having all SQL in static files, and loading them from disk and passing them on to the database. The idea of code creating SQL makes them very nervous.
I guess I'm curious if others actually do this? If so, how do you do this? If not, how do you manage "dynamic columns and dynamic sort-by" requests passed in?
I think a lot of people do it especially when it comes to reporting features. There are actually two things one should do to stay on the safe side:
Parameterize all WHERE clause values
Use user input values to pick correct column/table names, don't use the user values in the sql statement at all
To elaborate on item #2, I would have a dictionary where Key is a possible user input and Value is a correponding column/table name. You can store this dictionary wherever you want: config file, database, hard code, etc. So when you process user input you just check a dictionary if the Key exists and if it does you use the Value to add a column name to your query. This way you just use user input to pick required column names but don't use the actual values in your sql statement. Besides, you might not want to expose all columns. With a predefined dictionary you can easily control the list of available columns for a user.
Hope it helps!
I've done similar to what Maksym suggests. In my case, keys were pulled directly from the database system tables (after scrubbing the user request a bit for syntactic hacks and permissions).
The following query takes care of some minor injection issues through the natural way SQL handles the LIKE condition. This doesn't go as far as handling permissions on each field (as some fields are forbidden based on the log-in) but it provides a very basic way to retrieve these fields dynamically.
CREATE PROC get_allowed_column_names
#input VARCHAR(MAX)
AS BEGIN
SELECT
columns.name AS allowed_column_name
FROM
syscolumns AS columns,
sysobjects AS tables
WHERE
columns.id = tables.id AND
tables.name = 'Categories' AND
#input LIKE '%' + columns.name + '%'
END
GO
-- The following only returns "Picture"
EXEC get_allowed_column_names 'Category_,Cat%,Picture'
GO
-- The following returns both "CategoryID and Picture"
EXEC get_allowed_column_names 'CategoryID, Picture'
GO

Encryption on the fly

here is something interesting that I have been asked. It has to do with the encryption of data in a non encrypted database.
The story has as follows. We have a database, not encrypted and also none column encrypted in any of its tables. Now, we'd like to control the trafic of the data depending on who is asking for this. Let me explain more clear:
We have a table with the name: table1
This table has one column with the name: SName
We'd like to reach the following result. A user connected to the SQL Server Management Studio if runs the following query:
select * from table1
to take no result or if he/she takes a result, this result to be scrambled.
Now from inside the application the table should exchange data from/to the application in the normal mode.
Do you know if there is a setting, or an implementation or an external tool that can provide this functionality?
I think that this is quite interesting case!
Thank you.
Use permissions to stop that person reading the table at all.
Or use a VIEW to hide the table and have a WHERE clause in that that applies a filter silently: this could refer to another table with a list of approved users.
This isn't really an encryption (well, obfuscation in this case) issue.

Convert varchar to a double in DataSet TableAdapter Fill

In SQL Server 2008, I have a strongly typed data set with a table:
TABLE
ID (Guid)
Value (varchar(50))
This this table, Value actually represents an encrypted value on the database, which becomes decrypted after reading from this table on my server.
In Visual Studio; I have a Dataset with my table, which looks like:
TABLE
ID (Guid)
Value (float)
I want to know if there is a way, in a DataSet, to call my decryption methods on Value when I am calling my Fill Query on the TableAdapter for this Table.
Is there anyway to extend the DataSet XSD to support this sort of data massaging when reading data?
In addition to this, is there a way when inserting/updating records in this table to write strings to encrypted values?
NOTE:
All Encrypt/Decryption code is being performed on the client to the database, not on the database itself.
The Fill() method is going to execute whatever SQL is in the SelectCommand property of the DataAdapter. It's certainly possible to customize the SQL to "massage" data as it comes in.
Your issue is made more complex by the need to execute some .NET decryption. If you really want to do this and it is of high value to you, you could install a .NET assembly in the SQL Server database. Once this was done, you should be able to specify a custom SelectCommand that calls the code in your ,NET assembly to decrypt the data at select-time.
But that seems like an awful lot of work for very little reward. It's probably easier and more efficient to simply post-process the dataset and decrypt there. :)

How would I encrypt string data in SQL server 2008 while keeping the ability to query over it?

I have a database that will be hosted by a third party. I need to encrypt strings in certain columns, but I do not want to loose the ability to query over the encrypted columns.
I have limited control over the SQL instance (I have control over the database I own, but not to any administrative functions.)
I realize that I can use a .net encryption library to encrypt the data before it is inserted into the table, but I would then loose the ability to query the data with sql.
I like using SQL Server's key management: http://technet.microsoft.com/en-us/library/bb895340.aspx . After you have a key setup then its really easy to use:
To insert records you do this:
insert into PatientTable values ('Pamela','Doc1',
encryptByKey(Key_GUID('secret'),'111-11-1111'),
encryptByKey(Key_GUID('secret'),'Migraine'))
To select the record back out its really simple:
select Id, name, Docname
from PatientTable where SSN=encryptByKey(Key_GUID('secret'),SSN)
The cipher text will always be the same so it is much more efficient to compare the cipher text's instead of going though and decrypting each one.
if you use the same encryption key you could encrypt your search query string and match against that. Say my password is runrun i encrypt it to ZAXCXCATXCATXCA then when i want to search for a user with password runrun encrypt it first and it will match the table entry.
AFAIK, Most RDBMS do not support this, what I usually see is either:
A) The DB query API encrypts the data with a key that only the local server knows before it is sent to the remote db and decrypts when it's received.
or
B) The remote database stores everything encrypted with a key that it knows (probably at run time, given physically by an admin, or it's given the key with the query).
A will let you use the database without letting the owners know what's being stored, but you wont be able to do queries on the actual encrypted data other than maybe equality. B only protects against physical server theft (server has to be off though or they can get the key from memory...).
What I assume you want is called Private Information Retrieval. It's a fairly young field, I don't think you're going to find a decent implementation at the moment.
You could generate a hash (such as Md5 ) and store the hash value in the db. When you query you can select * from [my table] where value = {md5 hash}

How to enter long SQL text sample data with Visual Studio?

The Server Explorer built into Visual Studio is a nice way to connect to your database, view existing data, and edit data. Very useful for entering sample data into a database for testing and development purposes.
However, what if you have a "text" column and want to enter a long text field? For example, I have a text column in which I want to store a multi-line XML value. I'd like to be able to do multi-line editing from within the table data viewer.
I can't figure out how to do that? Does anyone know if it can be done, and if so, how?
I don't think it's possible. Management Studio display multi-lines text as one string.
I don't think the editor supports multi-line input or editing. However, you can enter multiple line data by creating a simple INSERT statement. For example:
CREATE TABLE TableA (
id INT IDENTITY PRIMARY KEY,
data VARCHAR(MAX)
)
INSERT INTO TableA (data) VALUES
('row 1
row 2
row 3')
Then, just select the entire INSERT statement and all of the data, and hit F5 to execute it.
Also, FWIW, the TEXT data type has been deprecated; VARCHAR(MAX) is the replacement (it's better for many reasons).

Resources