I have a database table that I want to confirm has not been tinkered with. My theory is to create a hash of static items and store that in the table. Then compare these when the data is required, for example....

  |  ID  | Creation_date       |  value   |   hash   |
  |  1   | 2012-11-30 13:59:48 |  10.99   | wd32d... |
  |  2   | 2012-11-30 14:08:48 |  10.00   | vadfv... |
  |  3   | 2012-11-30 15:10:48 |  13.00   | 43f3f... | 
  |  4   | 2012-11-30 16:13:48 |  12.00   | 6yg54... |

So the hash would be created by the combining the first 3 columns and a salt. Is this an effective method to achieve this? Is there a better way?

  • You do not need a salt for your purposes. You do not want to keep the HASH column in the same table because it can be tampered with just as easily as any other value can be. Keep another ID and HASH column on a separate database in another computer. – ponsfonze Jan 17 '13 at 20:23

Why a salt?

In my mind, a salt is a little add to make more flavour. Normaly, the salt is stored in same database than the hashed value himself.

Adding a salt won't add security and won't minimise chance of collision. At all, if collisions are possible, they will just be moved! Don't think you may compensate bad hash method by adding salt!

If you combine first 3 fields with such a secret phrase, you'll be able to make the verification. But chance to obtain collisions are clearly related to number of rows. If your goal is to make hard to an hacker to build proper hash, you have to use a secret phrase. Mostly if you're awaiting for many row in your database!

More youre database is big more i'ts easy to crack them by brute force! So care about hash method!

Other ways

Using server feature, like mysql binlogs to report each operation in a secured backup server (could be a NAS in write only).

A simplier way could be to make secured differentials backups and watch about diffs transactions packets (backup procedure could be trigged very closely if whole database may stay in RAM.).

Or finally, you could add triggers to database engine to be alerted and watch for alterations on database files, by using system tools like FAM ou Inotify.

  • Are you saying salt == secret phrase? Salt is reasonable if the value field is somewhat unconstrained and a bad hash function is used. E.g. collision between the first row data and one where the value field is a much higher number. – Henning Klevjer Jan 17 '13 at 7:58
  • @HenningKlevjer In my mind, a salt is a little add to make more flavour. Normaly, the salt is stored in same database than the hashed value himself. A secret phrase have to not be stored on same machine. – F. Hauri Jan 17 '13 at 8:02
  • Sure, you can have digital signatures on the fields if you like, but for this application I think that's overkill protection. – Henning Klevjer Jan 17 '13 at 8:06
  • I don't know final goal of request, but salt (few characters stored in same field) seem useless. – F. Hauri Jan 17 '13 at 8:09
  • The goal is to be alerted if any data has been altered from the original. Also to make it (virtually) impossible to create a hash with malicious data – maxum Jan 17 '13 at 8:14

Besides using HMAC to verify integrity of rows, use the DB permission system to prevent UPDATE and DELETE of rows in this table/db. Allow only INSERT and SELECT.


Storing the hashes in the same table as the data just lets a hacker see that you have an anti-tampering mechanism in place. If an attacker gains access to the table information they would likely figure out you've got something going on and act accordingly. Using hashes is not a bad idea, however you should store them in a separate database on a separate system as there's no point in giving information away. As for the salt (more of a key really), I'm not sure what you had in mind, but I think it's a good idea as if you have the hashes on a separate DB the salt is another layer of tamper protection: if the attacker does detect you have a DB of hashes they will still have to figure out what the salt (IV, key, whatever) is.


You haven't mentioned who you are protecting your database from and what capabilities they have. Whether your hashing plan is adequate depends on the attacker's access level.

  1. The attacker has "normal" account on database. This could be through an SQL injection. @Matrix's suggestion of only allowing INSERT and SELECT privileges works fine for this case, although it does mean that your app can't DELETE or UPDATE or REPLACE or TRUNCATE or DROP or ALTER or loads of other commands.
  2. The attacker has a superuser account on the database. Since the attacker now has UPDATE privileges, the secrecy of your algorithm/key/salt is the only thing stopping him from recalculating the hash when he changes the other values. Obviously, this means that the key(s) cannot be stored in the database. They can be stored in a different database or on the application server.
  3. The attacker has a shell account on your application server. This could come about through a code injection vulnerability in your application. In this case, the secret key or salt or algorithm is no longer secret. He has access to your application code and wherever the secret keys may be stored, the application needs to be able to access them, so the attacker will be able to as well.

The way I would achieve your goal is to immediately ship a log of all changes off the database and on to a dedicated logging server. If we're talking about MySQL, setting up a replication server will do the job. The SQL thread doesn't need to be running on the slave because the relay log files are your log of all changes. MySQL binary logs are a log of all write queries to a database. You can view the contents of a MySQL binary log (or relay log, which is what it is called once a slave has transferred it from the master) with the mysqlbinlog command.

Your logging server needs to be protected well. Ideally, you should have the minimum number of user accounts possible and any user accounts on it should have a different password or SSH key to the rest of your servers.

This scheme has the advantage that not only can you detect that a change has been made but you can also look further back into the logs to find out what the values were before the change was made. It can be overcome by an attacker that manages to acquire a root shell account on the main database server.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.