Slashdot Mirror


Malicious Injection — It's Not Just For SQL Anymore

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."

37 of 119 comments (clear)

  1. pr0n by macadamia_harold · · Score: 4, Funny

    When most people think of malicious injection, they think of SQL injection.

    Come on now, considering your audience, you might want to re-think that statement.

    1. Re:pr0n by spellraiser · · Score: 5, Funny

      Yeah. Malicious Injection was a pretty good flick. I can't wait for Malicious Injection: The SQL.

      --
      I hear there's rumors on the Slashdots
    2. Re:pr0n by Dunbal · · Score: 2, Funny

      I can't wait for Malicious Injection: The SQL.

            Available soon on VHS, DVD and ODBC...

      --
      Seven puppies were harmed during the making of this post.
  2. Old news by kill-1 · · Score: 3, Insightful

    Shell scripts have been vulnerable to similar "injection" exploits since the invention of CGI.

  3. More old news by spellraiser · · Score: 3, Insightful

    From TFA:

    The only real way to defend against all malicious code injection attacks is to validate every input from every user.

    Seems simple enough, but it's amazing how often this is ignored or implemented badly.

    --
    I hear there's rumors on the Slashdots
    1. Re:More old news by Vihai · · Score: 3, Informative
      The only real way to defend against all malicious code injection attacks is to validate every input from every user.
      Seems simple enough, but it's amazing how often this is ignored or implemented badly.

      ...but unfortunately it's mostly WRONG. In many cases, the real way to defend against injections is to ESCAPE values before composing strings, this is mostly the case with SQL (where prepared queries and the help of a good prepare/execute API is very much helpful) but it's not limited to it.

      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).

    2. Re:More old news by J0nne · · Score: 3, Informative
      3) Do not send SQL parameters to your page in GET statements!!!!!! Either use session variables or POST statements, session variables are best.

      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...
    3. Re:More old news by jrockway · · Score: 3, Informative

      > Here's my tips for preventing SQL injection.

      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.

      --
      My other car is first.
    4. Re:More old news by Anonymous Coward · · Score: 2, Interesting

      WRONG! The solution is to NOT paste together "programs" (literal or figurative [i.e. SQL]) by combining your stuff and user's stuff!

      Forget making quotes illegal (the irish will thank you) and forget trying to second-guess every possible problem by escaping the all the stuff YOU are smart enough to forsee problems with (leaving holes for people smarter than you).

      Just ensure that your programs and user inputs never get mixed together. For example, use parameterized SQL. Or put user input into a file and read it, instead of the ever-lame eval("var='"+userinput+"';") type of approach.

    5. Re:More old news by TheRealBurKaZoiD · · Score: 3, Informative

      Wrong. For God's sake, you dweeby little junior programmers need to do some research before you open your damn mouths.

      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.

    6. Re:More old news by runcible · · 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().

      --
      remember the wisdom of Mahatma Gandhi: If enough peasants die horribly, someone will probably notice
  4. My rock-solid solution to the injection problem... by Anonymous Coward · · Score: 5, Funny

    ...is to replace database storage, xml, and ldap with comma-delimited text files on anonymous ftp. In fact, my last job fired me for gross incompetence because the other programmers were jealous of the simplicity of my solution.

  5. know your system by jeepee · · Score: 2, Insightful

    "including LDAP injection and XPath injection. While these may not be as well-known to developers, they are already in the hands of hackers, and they should be of concern."

    How come they are not well known to developers. Last time I checked if I dont use ldap somewhere along my lines
    of codes I'm not in trouble of a ldap injection. Know your systems and check yours inputs! god damn!

    1. Re:know your system by msobkow · · Score: 2, Insightful

      Personally I have never understood why people try to hack utilities like XPath into database equivalents. But I guess if you learn how to use a hammer and screwdriver, you might well refuse to learn how to handle a wrench because you can "make" things work with the wrong tools.

      Or perhaps it's a negative side-effect of object reuse fanatics who don't consider that reusability does not necessarily mean eliminating alternate implementations, but enforcing an appropriately designed and narrowed interface instead of specific implementations.

      Imagine a rich reuse library that included not just default implementations, but specialized implementations that took advantage of particular tools and technologies to tweak performance, scalability, security, and reliability. ie. Instead of a generic JDBC connection with DbIO objects and methods, you could have the generic interface with specific implementations for Sybase ASE, DB/2 UDB, Oracle, PostgreSQL, SQLServer, etc. Some might not even use JDBC behind the interface. Some might rely on stored procs, others might rely on product-specific features like PostgreSQL table inheritance.

      In any case, I'm reasonably certain such generic interface implementations would be much less vulnerable to injections, because even if the code were sloppy, the attacker would have to know which implementation they're attacking, not just which technology.

      Personally I ALWAYS validate and quote data appropriately. A couple decades of database, systems, applications, and distributed software development teaches painful lessons through late night and weekend debugs.

      --
      I do not fail; I succeed at finding out what does not work.
  6. XML Logic Is Flawed by CowboyBob500 · · Score: 5, Informative

    In his XML example with XPath injection he states that running a certain query can return the entire order history of all customers. That may be true, but if the application is returning an XML document containing the entire order history of all customers for each customer request before running an XPath query, then I think the application has more problems than being vulnerable to XPath injection.

    Bob

    1. Re:XML Logic Is Flawed by Ant+P. · · Score: 3, Insightful

      Yeah, but XPath can be done server-side just like SQL.

    2. Re:XML Logic Is Flawed by CowboyBob500 · · Score: 3, Insightful

      But not over an XML representation of the entire damn customer orders table. That's insane.

      Bob

  7. Validate this by gigne · · Score: 4, Insightful
    FTA
    RE: validating input fields...
    To be completely thorough, a developer should set up both white- and blacklists in order to cover all bases.

    I can't help but feel that most developers have at least a little common sense and do something along those lines anyway.
    I often write little validate_input(char *string, char *format) that checks all input string from a user are simple, but more often than not very effective. How is this any different from using white and black lists. Any coder worth their salt would do something to stop malicious input, but no one in completely infallible.

    Security of anything in this world is near on impossible. Hackers will get around anything given time.
    --
    Signature v3.0, now with 42% less memory usage.
    1. Re:Validate this by thsths · · Score: 4, Informative

      >> To be completely thorough, a developer should set up both white- and blacklists in order to cover all bases.
      > 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.

  8. It may sound trite, but... by PHAEDRU5 · · Score: 3, Interesting

    I blame Microsoft for a lot of these vulnerabilities.

    I recently attended a Microsoft-sponsored seminar on web site security at the DeVry Institute in Decatur, GA.

    One of the speakers was a man from SPI Dynamics (sorry, forgot his name). He demonstrated how Microsoft's tools make it very easy to expose a database to the web, but how the same tools make exploiting the database very easy. He demonstrated an application that used SQL injection to first reverse-engineer the schema of an exposed database, and then the data in the database. It was quite a revelation.

    --
    668: Neighbour of the Beast
    1. Re:It may sound trite, but... by bdigit · · Score: 4, Insightful

      Um you can just as easily reverse engineer a mysql or postgresql database through sql injection attacks also. What's your point?

    2. Re:It may sound trite, but... by ehrichweiss · · Score: 2, Insightful

      Don't blame them on M$(though I would love to do so myself) they're actually not even the fault of XML or even SQL. Instead they're due to the programming language interface whether that is PHP, REXX, Perl, etc. Look carefully and you'll realize that the languages make it incredibly difficult to delimit certain variables that happen to be assigned things like quotation marks, etc. even with the usage of single and double quotes. For example variable1="this is the first line's message".variable2."and it's going to be hard for the language to figure out what to do about those single quotes if it thinks that single quotes are also delimiters". You can escape the chars but it doesn't make it any better usually. I'm not citing the best of examples but if I dig through some of the code I've had to debug that was written by others, I could show you a nightmare for the coder, much less the security conscious.

      --
      0x09F911029D74E35BD84156C5635688C0
    3. Re:It may sound trite, but... by ArsenneLupin · · Score: 2, Interesting
      Um you can just as easily reverse engineer a mysql or postgresql database through sql injection attacks also. What's your point?

      Actually, you can't. There are several things about SQL-Server databases that makes buttfucking them particularly easy:

      • Very helpful error messages when attempting to cast strings to integers. This makes it quite easy to read all kinds of errors from the database by doing stuff such as select top 1 convert(int, name) from sysobjects ==> this will give you the name of first table in a nice error message. Other databases, such as mysql will just display "data conversion error", or something similar, without giving you the value.
      • Presence of sysobjects and syscolumns tables. Mysql doesn't have these, so there is no easy way to find out the schema.
      • Very helpful error messages displayed for group by ... having ... queries, which make it even easier to reverse engineer the schema. So you just sneak in ' having 1=1-- into your query, and out pops the name of the first table and column selected by that statement. Continue with ' group by tbl1.col1 having 1=1-- and out pops another column. Continue adding columns to the group by clause ' group by tbl1.col1,tbl2.col2 having 1=1--- until you've got the whole select part, and when you've got that, it's usually pretty easy to see what needs to be typed to insert a nice piece of ass into the site.
      • Possibility to concatenate statements in one query: select id from customer where login='myname' ; update customer set access_level=operator where login='myname' -- and password = 'x'. Mysql and postgresql would barf when fed such a composite statement, whereas SQL server would happily execute it. Such composite statements are essential for most defacements.
      Interestingly enough, these vulnerabilities are specific to SQL server. Other Microsoft offerings such as Access (Jet database engine) don't share those:
      • No verbose error messages for failed type casts.
      • msysobjects table protected in default setup
      • Generic error message for bad group by's
      • No support for composite statements
      So, if you have to use a Microsoft product for your web site, at least use access. Not only is it cheaper, it's also more secure (even if only by chance...)
  9. If you only knew the POWER of languages by Sloppy · · Score: 3, 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.

    --
    As copyright owner of this comment, I authorize everyone to defeat any technological measure which limits access to it.
  10. Re:Seriously by Dunbal · · Score: 2, Insightful

    Any user input should be scrubbed sanitized and checked before using it

          This has been true since the dawn of programming. NEVER trust the user. Oh before it was just entering text when the program expected an integer, or a negative value when it expected a positive etc. Now we don't get "? Redo from start" errors that crash the BASIC programs. But it's essentially the same thing. Never expect the user will cooperate with the program. Especially a program that is available to potentially malicious people out on the internet.

    --
    Seven puppies were harmed during the making of this post.
  11. Phishers like frame injections by miller60 · · Score: 4, Interesting

    Phishers have been known to use frame injections to insert their content into framesets, allowing them to grab login info from within the bank's own web site. It's not nearly as fancy as an SQL injection, but it's sure malicious and quite difficult for victims to recognize.

  12. Defensive Programming by davidwr · · Score: 3, Funny

    "It's not just for breakfast anymore."

    --
    Knowledge is how to play a game, intelligence is how to win, wisdom is knowing what game to play.
  13. Email header injection attack by DeadSea · · Score: 5, Interesting
    Another example of an injection attack allow an attacker to send spam through a contact form that doesn't normally allow the recipient to be specified by the user.

    A webmaster hosts a contact form on his website that allows users to fill out a form to contact him. He allows the user to specify a subject and a message but the recipient is hard coded to webmaster@example.com.

    The message ends up looking like this:

    To: webmaster@example.com
    From: thewebserver@example.com
    Subject: $subject

    $message
    Where $subject and $message are captured from the user on the website.

    If the $subject is not properly sanitized, a bot could submit it with a new line in it and be able to start a new line in the headers of the email. That new line could be, for example, a large CC list of people to spam with his message:

    Buy my weight loss pills!
    CC: spammee1@example.com, spammee2@example.com

    Which is why I would suggest using a contact form such as the one that I have written that has already thought about this sort of thing.

  14. Wash it before you eat it by Jhan · · Score: 3, Interesting

    It's a simple matter of hygiene:

    Wash it before you eat it.

    All data read from external sources must be validated before being used. In some languages/frameworks this is as hard as nails (ie. I programmed a pretty large web application with only straight CGI programs written in pure Unix/C), in some you have help (Perl with taint), in some it's kinda-sorta-almost not an issue (PHP with Agavi and Creole).

    If I had to choose, I would have to say that the middle way, the Perl way, is the best. It does not pretend to solve all your problems for you, even when it can't really. Rather it brings the problems at hand to your attention. Problems surface, fix problems, code gets better.

    --

    I choose to remain celibate, like my father and his father before him.

  15. Re:Ignorance by moco · · Score: 2, Interesting

    Then your program needs to be aware of LDAP, SQL, XML and XPATH syntax. Validating user input, as in using regular expressions, will protect you from "FutureML" injection attacks without the need of knowing how "FutureML" will work. In my opinion validating user input IS the correct way of doing it.

    --
    moi
  16. Re:Ignorance by bluebox_rob · · Score: 4, Insightful

    I think you're right - as long as you are sure that you know what's going to be done with the data after its been written away to your database. You might have your escaping/quoting routine solidly implemented for all inputs to your system, but the trainee down the hall who writes the reporting application that parses the table once a month might not be so savvy - the cunningly crafted SQL injection attack that your quoting has preserved and saved away into the db could wreak havoc when it gets read out again at the other end. The same goes for any HTML/XML that has been saved away, and then gets blindly written out by a web developer on the Order Summary page, or merged into some larger XML document without proper checks.

    I suppose an apt analogy would be saying that it's ok to allow infectious material into a building as long as it is first correctly sealed in a bio-safe container - well that's true as long as you're sure the janitor isn't going to open it up later that evening and use it for a cookie jar.

  17. He thought of that... by martinmarv · · Score: 2, Funny

    Each value was put in "quotes"...

  18. Comment removed by account_deleted · · Score: 3, Informative

    Comment removed based on user account deletion

  19. I think the point is that... by PHAEDRU5 · · Score: 2, Informative

    If you develop software that follows the usual layered model (web, business, persistence), you have code in place to isolate the web bit from the database bit. MS tools sort of shortcut the web/database bit, making it easier to exploit what's in the database.

    Hope this helps.

    --
    668: Neighbour of the Beast
  20. Check All User Input w/Regular Expressions by CodeBuster · · Score: 2, Informative

    It is well known amongst the more experienced software developers out there that all user input to ANY software system should be considered suspect and therefore must be checked for invalid inputs, boundary, and special cases. The solution has been around for decades, but it is really surprising how many developers out there have NOT heard of regular expressions or do not know how to properly use them. There are some cases, usually when widely variant free-form input is required, that are difficult to use with regular expresssions, but for the most part they have proven to be remarkably effective in my own experience and I use them regularly (pun intended) in my website and application development. If you have not gotten in on the regular expression game then consider picking up the O'Reilly Mastering Regular Expressions book or visiting Regular-Expressions.info before building your next project. The project you save might be your own!

  21. Validation Is Not the Solution by RAMMS+EIN · · Score: 2, Insightful

    There is a solution to injection vulnerabilities, but it's not validation. Sure, if you validate everything properly, you won't suffer from injection vulnerabilities. However, writing the code for that is cumbersome and error-prone, and thus, in practice, we see that values are not or not properly validated.

    The solution I've been championing is structured composition. Instead of verifying that the input won't alter the structure of whatever you're composing, you use APIs that ensure that this won't happen. Some examples of this, as well as other bug-eliminating language/library features, can be found in my essay Better Languages for Better Software.

    --
    Please correct me if I got my facts wrong.
  22. How I'd do stuff by TheLink · · Score: 3, Informative

    So far everyone seems to be focusing on "input" and forgetting about "output", or even mixing the two.

    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).

    --