Malicious Injection — It's Not Just For SQL Anymore 119
nywanna writes "When most people think of malicious injection, they think of SQL injection. The fact is, if you are using XML documents or an LDAP directory, you are just as vulnerable to a malicious injection as you would be using SQL. Bryan Sullivan looks at the different types of malicious code injections and examines the very basics of preventing these injections."
XML Logic Is Flawed (Score:5, Informative)
Bob
If you only knew the POWER of languages (Score:4, Informative)
Heh, remember when we had binary file formats and protocols, fixed-length fields (didn't need delimiters), and there was no parsing or worrying about "escaping" data? We didn't have these problems.
Anyway, I like this article because it admits that whitelists are better than blacklists. You have to validate data: make sure it is known to be non-harmful, rather than looking for whatever problems that you have imagined so far. You'll never guess all the things that can go wrong; you just know what is right.
Re:More old news (Score:4, Informative)
If your parameter is a VALUE, it must remain a VALUE when you compose a command and proper escaping is the correct, reliable way.
Validating input may be helpful as another layer of security, but it's not the "only right way", it's not even the *right* way (in most cases).
Re:Validate this (Score:5, Informative)
> I can't help but feel that most developers have at least a little common sense and do something along those lines anyway.
I hope that most developers have the common sense to take the correct approach: avoid injection problems by proper quoting! There is no need to validate the data, you just have to make sure that it stays data when you parse it on. Just use the proper library functions, and you will be fine (especially if you use hex encoding
White lists are a good idea if you don't trust you quoting, or if you need to verify the input for another reason. Black lists are most certainly not a good idea. Just imagine that the web shop tries to sell a product called "Selecta[tm]", but you block all attempts to buy it because it matches your black word "SELECT"
P.S.: Anybody with an apostrophe in their name naturally develops an unsatisfiable urge to kill web programmers.
Re:More old news (Score:1, Informative)
Re:More old news (Score:1, Informative)
Here's my tips for preventing SQL injection.
1) Use stored procedures!!!!!!!
2) escape your escape characters. i.e. in most statments a "'" is stored as "\'" so escape the \ so its stored as "\\'", it will invalidate the SQL statment because SQL will read it as "\'" instead of just "'"
2.5) an alternate to escaping characters is to just strip characters unnecessary to be passed with your stored procedure. i.e. strip all quotes, strip all double quotes, strip all equals signs, bash signs, etc.
3) Do not send SQL parameters to your page in GET statements!!!!!! Either use session variables or POST statements, session variables are best.
4) You should be secure, but if your not comfortable doing that, then provide additional validation.
Re:XML Logic Is Flawed (Score:1, Informative)
Re:More old news (Score:3, Informative)
Using POST instead of GET doesn't make *any* difference. You can fake a POST request just as easily as a GET request. Please stop telling people that a POST is more secure...
Re:More old news (Score:4, Informative)
Here are mine that aren't garbage:
> 1) Use stored procedures!!!!!!!
"EXEC dbo.stored_procedure 'Oops'; DROP DATABASE foo; --'"
> 2) escape your escape characters. i.e. in most statments a "'" is stored as "\'" so escape the \ so its stored as "\\'", it will invalidate the SQL statment because SQL will read it as "\'" instead of just "'"
Not sure what you're talking about, but a literal apostrophe is quoted by doubling it in SQL. ' -> ''. However, don't quote -- you'll get it wrong. Use a proper mechanism instead, like prepared statements.
> 2.5) an alternate to escaping characters is to just strip characters unnecessary to be passed with your stored procedure. i.e. strip all quotes, strip all double quotes, strip all equals signs, bash signs, etc.
That's a great idea, until you need to store unicode or have a customer named "O'Reilly".
> 3) Do not send SQL parameters to your page in GET statements!!!!!! Either use session variables or POST statements, session variables are best.
Right, there's no way anyone can see hidden form fields! They're magical! (Also, session variables aren't "best". If you find the need to store SQL in a variable, your program is terribly designed and you need to rethink it. In this day and age of stored procedures and ORMs, you probably shouldn't have ANY SQL in your code.)
4) You should be secure, but if your not comfortable doing that, then provide additional validation.
Always validate -- it saves work later. If a user types 2-1234 as his phone number, and you store that, you won't be able to call him later, completely defeating the purpose of asking him for the data.
If you're not sure that you can remember to validate everything, use a language that taints incoming data and kills the program when you use it. In perl, turning on taint mode will prevent the common pattern of:
my $value = CGI->param('foo');
$dbh->do("SELECT * FROM foo WHERE bar = $value");
and even:
$sth = $dbh->prepare('SELECT * FROM foo WHERE bar = ?');
$sth->execute($value);
Since you didn't validate $value, you can't use it (correctly or incorrectly).
Hope this helps.
Comment removed (Score:4, Informative)
Re:More old news (Score:3, Informative)
Escaping values only brings up new vulnerabilities. In database servers these are known as SQL truncation, and are the byproduct of buffer overruns in system functions (such as QUOTENAME and PATINDEX in T-SQL). These truncation attacks affect even parameterized queries, and the ubiquitous sp_executesql system stored procedure. I won't go into the details. All the info you need is is BOL, so look it up for yourself.
The real problem (again, in database servers) is dynamic SQL. That, and incorrect security permissions (some dbas need to be beaten with a stick), but I'm not here to teach a SQL Administration class. Many, many dynamic SQL statements, because they are only filtering the data set, can be re-written as a non-dynamic SQL stored procedure, but still afforded their dynamic nature. For example, this vulnerable stored procedure:
create proc sp_get_product
@prod varchar(255) = null
as
declare @sql varchar(1000)
set @sql = 'SELECT PRODUCTID, PRODUCTNAME, CATEGORY, PRICE FROM PRODUCTION'
if @prod is not null set @sql = @sql + ' PRODUCTNAME LIKE ''' + @PRODNAME + '''
exec(@sql)
can be re-written to:
create proc sp_get_product
@prod varchar(255) = null
as
select productid, productname, category, price
from product
where productname like coalesce(@prod, productname)
Coalesce returns the first non-null argument in it's argument list. If @prod has a value, the resulting dataset is filtered on it. If @prod is null, then the entire dataset will be returned because productname will filter on it's own value. Only near-infinite where clauses can't be done this way.
Also, production database server accounts should have no access to any database objects. They should only be able to run stored procedures, and that's it.
You're advice about "escaping" values is just as bad as those computer science professors in college that say "re-writing your conditional statements to automatically exclude bad data will eliminate the need to validate the data that makes it through."
Goddammit. Comments (and articles) like this make me so fucking mad.
I think the point is that... (Score:3, Informative)
Hope this helps.
Check All User Input w/Regular Expressions (Score:3, Informative)
Re:More old news (Score:2, Informative)
Yeah...PHP.
Don't worry about injection vulnerabilities in LAMP -- just don't forget to use mysql_real_escape_string() and not mysql_escape_string()!
The next rev will no doubt include mysql_really_real_escape_string().
How I'd do stuff (Score:4, Informative)
Anyway, my suggestion has always been to do something like the following:
Inputs to your program
|||
Corresponding Input filters
|||
Your program
|||
Corresponding Output filters
|||
Outputs from your program
|||
Stuff receiving the outputs
You have a different "input filter" for each class of input so that your program can handle those inputs correctly.
Then you have a different output filter (e.g. SQL bind vars, HTML, XML) so that the stuff receiving your outputs (browser, database, viewer, etc) will handle them correctly.
NEVER do stuff like magic quotes (PHP is one of the worst and most braindead language in popular use) - mixing input and output filtering is so wrong it isn't funny (there are so many other things PHP does wrong that it's almost criminal).
Depending on the circumstances your program could output a single quote ' differently e.g. %27 for a cgi parameter, '' for Oracle data and \' for MySQL data (BTW MySQL is the PHP of databases). So it should be obvious that "one size fits all" doesn't work.
By filtering I mean quoting/encoding sanity checking etc - whatever it takes to get the data in a suitable form (with hopefully minimal data loss/corruption).