2

I understand the basic process of SQL injection attack. My question is related to SQL injection prevention. I was told that one way to prevent such an attack is by frequently changing the table name! Is that possible?

If so, can someone provide me a link to read about it more because I couldn't find an explanation about it on the web.

2
  • Changing the table name to prevent SQL injection sounds a bit like continually changing the color of your Ferrari so it won't get stolen. An app which is robust to SQL injection will be able to block all rogue queries trying to pry into secure data, just as a good car alarm will protect a Ferrari. Commented Oct 12, 2016 at 21:59
  • @TimBiegeleisen: Are bind placeholders in a prepared statement like cupholders in a Ferrari? And I'm wondering... what color is your Ferrari? Commented Oct 13, 2016 at 13:49

3 Answers 3

3

No. That makes no sense. You'd either have to change every line of code that references the table or you'd have to leave in place something like a view with the old table name that acts exactly like the old table. No reasonable person would do that. Plus, it's not like there are a ton of reasonable names for tables so you'd be doing crazy things like saying table A stores customer data and AA stores employer data and AAA was the intersection between customers and employers.

SQL injection is almost comically simple to prevent. Use prepared statements with bind variables. Don't dynamically build SQL statements. Done. Of course, in reality, making sure that the new developer doesn't violate this dictum either because they don't know any better or because they can hack something out in a bit less time if they just do a bit of string concatenation makes it a bit more complex. But the basic approach is very simple.

Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately, the real life is not that comical. You cannot avoid dynamically built SQL statements, so denying this possibility is rather a disservice, leaving the poor folks on their own and thus making them vulnerable for sure.
@YourCommonSense - Most applications have no need for dynamic SQL at all. When an application needs dynamic SQL, you can still generally use prepared statements and bind variables for any user input. If an application needs dynamic SQL and the user's input needs to be part of that, most of the time you can white list the set of allowed user inputs. If you need dynamic SQL and you can't make the user input a bind variable and you can't white list the valid inputs then you're in the rather dangerous business of trying to properly escape the input.
This latter statement of yours is much more helpful than initial answer.
2

Pffft. What? Frequently changing a table name?

That's bogus advice, as far as "preventing SQL Injection".

The only prevention for SQL Injection vulnerabilities is to write code that isn't vulnerable. And in the vast majority of cases, that is very easy to do.

Changing table names doesn't do anything to close a SQL Injection vulnerability. It might make a successful attack vector less repeatable, requiring an attacker to make some adjustments. But it does nothing prevent SQL Injection.


As a starting point for research on SQL Injection, I recommend OWASP (Open Web Application Security Project)

Start here: https://www.owasp.org/index.php/SQL_Injection

If you run across "changing a table name" as a mitigation, let me know. I've never run across that as a prevention or mitigation for SQL Injection vulnerability.

4 Comments

I was told by a professor such a thing exists and I have to search about it !!! I still don't see that too but I thought to ask you guys
@Tiff: You should get a rebate on your tuition. Unless this is some kind of "test" that your professor is giving you. SQL Injection is a vulnerability in code. An attacker can exploit a SQL Injection vulnerability without knowing any table names. Having a valid table name can make it marginally easier for an attacker to craft more nefarious exploits. Otherwise, your professor is spouting nonsense.
@tiff You need a new professor because this one is broken.
As a starting point for research, I'd recommend the OWASP (Open Web Application Security Project). The SQL Injection Cheat Sheet gives a very good high level overview. owasp.org/index.php/SQL_Injection (and AFAIK) nowhere is "frequently changing table names" recommended as a mitigation.
1

Here's things you can do to prevent SQL injection:

Use an ORM that encapsulates your SQL calls and provides a friendly layer to your database records. Most of these are very good at writing high quality queries and protecting you from injection bugs simply because of how you use them.

Use prepared statements with placeholder values whenever possible. Write queries like this:

INSERT INTO table_name (name, age) VALUES (:name, :age)

Be very careful to properly escape any and all values that are inserted into SQL though any other method. This is always a risky thing to do, so any code you do write like this should have any escaping you do made blindingly obvious so that a quick code review can verify it's working properly. Never hide escaping behind abstractions or methods with cute names like scrub or clean. Those methods might be subtly broken and you'd never notice.

Be absolutely certain any table name parameters, if dynamic, are tested versus a white list of known-good values. For example, if you can create records of more than one type, or put data into more than one table ensure that the parameter supplied is valid.

Trust nothing supplied by the user. Presume every single bit of data is tainted and hostile unless you've taken the trouble to clean it up. This goes doubly for anything that's in your database if you got your database from some other source, like inheriting a historical project. Paranoia is not unfounded, it's expected.

Write your code such that deleting a line does not introduce a security problem. That means never doing this:

$value = $db->escaped(value);
$db->query("INSERT INTO table (value) VALUES ('$value')");

You're one line away from failure here. If you must do this, write it like so:

$value_escaped = $db->escaped(value);
$db->query("INSERT INTO table (value) VALUES ('$value_escaped')");

That way deleting the line that does the escaping does not immediately cause an injection bug. The default here is to fail safely.

Make every effort to block direct access to your database server by aggressively firewalling it and restricting access to those that actually need access. In practice this means blocking port 3306 and using SSH for any external connections. If you can, eliminate SSH and use a secured VPN to connect to it.

Never generate errors which spew out stack traces that often contain information highly useful to attackers. For example, an error that includes a table name, a script path, or a server identifier is providing way too much information. Have these for development, and ensure these messages are suppressed on production servers.

Randomly changing table names is utterly pointless and will make your code a total nightmare. It will be very hard to keep all your code in sync with whatever random name the table is assuming at any particular moment. It will also make backing up and restoring your data almost impossible without some kind of decoder utility.

Anyone who recommends doing this is proposing a pointless and naïve solution to a an already solved problem.

Suggesting that randomly changing the table names fixes anything demonstrates a profound lack of understanding of the form SQL injection bugs take. Knowing the table name is a nice thing to have, it makes your life easier as an attacker, but many attacks need no knowledge of this. A common attack is to force a login as an administrator by injecting additional clauses in the WHERE condition, the table name is irrelevant.

3 Comments

Excellent overview/summary. +10 (I'd +150 if I could). If I have to include a potentially unsafe value in SQL text, I do the escaping, right where value is included... e.g. $sql = "INSERT INTO t (c) VALUES ('" . $dbh->real_escape_string($var) . "')";, and then pass just $sql to be executed. That pattern works for me, because I have a complete $sql that I can output to the debug log, right before it gets executed. This may be an ugly pattern, but it make its blindingly obvious that escaping is done exactly once, right when and where the value gets included in SQL text.
@spencer7593 That's a good example. In a quick review you can see that the value is escaped, there's no need to look at other code to double-check. It's ugly, but you're doing something ugly.
That's it exactly. I don't mind that the code is ugly. Attempting to make the code look pretty is like putting lipstick on a pig. With that pattern, you can see right there, on that line, that the value being included in the SQL text is being escaped. I don't need the escaped value stored in a variable, cluttering up the code with another variable. Because it doesn't need to referenced anywhere else. The only place that value needs to be escaped "for inclusion in SQL text" is right where it's being included in the SQL text.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.