I was reading about SQL injection and saw this, which got me thinking:


  input fields as small as possible to reduce the likelihood of a hacker being able to squeeze SQL code into the field without it being truncated (which usually leads to a T-SQL syntax error).


Source: Microsoft SQL Server 2008 R2 Unleashed

What is the is the shortest field size where SQL injection can cause harm?

With harm being database modification or returning results not intended by design. Including an end comment marker (--) in a two character field would not cause harm, it would just cause a failed query. The potential hacker, might learn the field is susceptible to injection, but they are unable to leverage it.

No, there is no length that is too short to be exploitable (at least in some situations).

A length-filter is not a valid protection against SQL injection, and prepared statements really are the only proper defense.

A length filter is however a good measure as defense in depth (as are integer filters, alphanum filters, etc). There are many situations where e.g. valid input could never be above say 30 characters, but where meaningful exploitation requires more. It should (but probably doesn't) go without saying that any filtering as defense in depth must be taking place server-side as anything client-side can simply be bypassed.

Restriction Bypass

Restriction clauses (e.g. AND/OR) can be bypassed by two characters, which can cause real harm, not just a failed query. The most simple example is a login (other examples would be the unauthorized deletion of additional data):

SELECT * FROM users WHERE userid = [id] AND password = [password]


Injection:  

id = 1#
password = wrong_password


Payload: 2 chars

DoS

DoS attacks require very few characters. In a MySQL example, it takes 7 for the actual call + x for the given seconds + whatever is needed to be able to call the function and fix the query.

Example:

SELECT * FROM users WHERE userid = [id]


Injection (this is a valid injection, a longer form would be 1 AND sleep(99)):

sleep(99)


Payload: 9 chars

Reading Data

If the data is displayed, the length depends mainly on the table and column name. I'll assume equal column count for all tables (it may happen, and it saves characters). 

Example:

SELECT * FROM comments WHERE commentid = [id]


Injection:

1 union select * from users


Payload: 27 chars.

Editing Data

Unauthorized database modifications can also be achieved with few characters.

Example:

UPDATE users SET password = '[password]' WHERE id = [id]


Injection (into password):

',isadmin='1


Payload: 12 chars

A restriction bypass would also work (the result is that all passwords are now empty*):

'#


Payload: 2 chars

* The password example is used for simplicity; passwords should be hashed making the example impossible. The example still applies in all similar situations (updating a username, updating permissions, and so on)
