Slashdot Mirror


New Attack Exploits "Safe" Oracle Inputs

Trailrunner7 writes "Database security super-genius David Litchfield has found a way to manipulate common Oracle data types, which were not thought to be exploitable, and inject arbitrary SQL commands. The new method shows that you can no longer assume any data types are safe from attacker input, regardless of their location or function. 'In conclusion, even those functions and procedures that don't take user input can be exploited if SYSDATE is used. The lesson here is always, always validate and prevent this type of vulnerability getting into your code. The second lesson is that no longer should DATE or NUMBER data types be considered as safe and not useful as injection vectors: as this paper (PDF) has proved, they are,' Litchfield writes."

11 of 118 comments (clear)

  1. Use ORMs by chrysalis · · Score: 2, Informative

    Interesting flaw.

    However, don't ORMs (and database-independant abstraction layers like AdoDB) protect against this?

    --
    {{.sig}}
    1. Re:Use ORMs by Shados · · Score: 3, Informative

      Yup. Basically, the only real way this could be exploited would be something like a stored procedure which takes one of the "vulnerable" types as parameters, exposed directly to the clients, and concatenate the types with little to no casting.

      Something like (pseudocode, the following wouldn't even pass syntax check, obviously, but its stupid hard to find a working case)

      DECLARE @blah SOMEVULNERABLETYPE

      Exec "select * from stuff where stuff.Blah =" + @blah;

      If @blah was a string, everyone would realise its vulnerable...but in this case, numbers, dates, etc, would be assumed safe (how do you put code in a number??), when it supposingly was discovered its not safe.

      However, if you went through a database driver (not even an ORM!), and made a prepared statement, passed a Java (for example) variable as parameter to a query, well, no invalid input will be able to get through. If you add an ORM layer on top of that which does extra validation, then even if all of the types (both java and database) were vulnerable, it wouldn't go through either...

      This is really more of a theoritical vulnerabilty than a real one... it can't realistically be exploited in the wild, and its hard to even -imagine- a scenario in a well coded app.

  2. Re:heh by morgan_greywolf · · Score: 2, Informative

    Agreed. Handing out ALTER SESSION privs to anyone using a form is just plain dumb, dumb, dumb. You may as well put PLEASE HACK ME in flashing red letters at the top of the form.

  3. Re:To all you type safe ninnies by AKAImBatman · · Score: 4, Informative

    Type safety and "safe" data types are two different things. One is a language construct intended to prevent errors in code through compile-time checking (though you pay in flexibility), the other is types of data that theoretically can be used in a database without doing validation checks.

    I'll leave it as an exercise for you to figure out which one is which.

  4. Re:security super-genius by BigBlueOx · · Score: 2, Informative

    The term "super-genius" was coined in modern English in 1952 in "Operation: Rabbit". The fact that the supposedly encyclopedic Wikipedia refuses to index on this term, despite my frequent repeated submissions of well thought out and quite lengthy protest emails, just goes to show their blighted pig-ignorance.

    http://en.wikipedia.org/wiki/Operation:_Rabbit

  5. Re:heh by DazzaL · · Score: 3, Informative
    It is not true to say that you need ALTER SESSION privilege granted to actually issue ALTER SESSION commands. Yes, that sounds counter-intuitive but it is true that you can issue SOME alter session commands if you can connect to a database regardless of what privs you have.

    In this case setting NLS_DATE_FORMAT can be done by ANYONE regardless of whether they have ALTER SESSION granted.

    some observations:

    1. in most web apps you wont have access to the database, just the webserver...the database should be firewalled off.

    2. it is RARE for PL/SQL developers to use resort to using dynamic SQL (execute immediate/DBMS_SQL) to run SQL, so this flaw, whilst interesting, is HIGHLY unlikely to be a problem...its certainly no where near as dangerous as developers not validating inputs where a application tier (java/php etc) does sql commands (esp if its not using bind variables) against a database [which by definition are dynamic sql calls].

    Not to mention that using execute immediate without the USING clause and bind variables is again really rare by any half competent pl/sql developer.

    3. the code also relies on another major error in the coding..type conversion. the date is implicitly converted to a string due to concatenation(||) i.e oracle rewrote that internally as to_char(v_date) and, as there was no supplied format it uses NLS_DATE_FORMAT.

    i.e. in the example in the paper: stmt:='select object_name from all_objects where created = ''' || v_date || ''''; dbms_output.put_line(stmt); execute immediate stmt;

    would undoutably be written PROPERLY as (in the dynamic case) execute immediate 'select object_name from all_objects where created = :b1' using v_date;

    which is not susceptible to injection (NLS_DATE_FORMAT cant even come into play here).

  6. Re:heh by martinmarv · · Score: 2, Informative
    In the environments I've worked in (enterprise applications and large CMS-based websites), using stored procedures for everything can be a pain. For me, the best approach is a happy medium:-
    • Don't restrict yourself to stored procedures, but do use them for updates, or database-side processing
    • Do use a dedicated account for database access and make sure only appropriate permissions are granted
    • Use parameterised queries (seems like most common frameworks support this)
    Also
    • Always validate user input
    • Always escape user input that will end up in the database
  7. Re:heh by Kozz · · Score: 2, Informative

    Reminds me of a webapp I worked on once. The programmer, in his infinite wisdom, would "SELECT * FROM TABLENAME", then stuff all 2500 records into a PHP array. Then he would promptly iterate over this array, selecting only two columns (of about thirty) he wanted from the desired rows matching his criteria.

    I held my gag reflex long enough to perform only the requested change and make it functional. Then I declined all work after that.

    --
    I only post comments when someone on the internet is wrong.
  8. Re:heh by Anonymous Coward · · Score: 1, Informative

    Neither ALTER SESSION nor creating PL/SQL stored procedures is a highly privileged operation in Oracle. Users use ALTER SESSION to set a preference for date formatting and you don't need any system privileges for this. Each database user has their own schema in which they can create stored procedures if they have the CREATE PROCEDURE system privilege. And you can create a stored procedure that is invoked using the rights of the caller or the rights of the owner. Most procedures execute using the rights of the owner. Your provided stored procedure would be set to run with invoker rights and so when it's called by the hijacked stored procedure it runs with the rights of the owner of that procedure.

    This is essentially an privilege escalation attack, potentially allowing an ordinary Oracle user to run arbitrary code using the rights of another, more privileged user.

    The real limitation here is that you need to find a procedure that you have rights to execute, that is owned by a privileged user and which converts a date to a string without using the TO_STRING function, and then pastes it into a SQL query and runs it. Usually the stored procedure would just bind the date variable directly in the query and avoid the string conversion. You simply shouldn't be pasting parameter values into queries in any tier.

  9. Re:DB Programming 101? by VGPowerlord · · Score: 2, Informative
    Since Shados didn't say what the difference is, I will.

    Inner and outer joins always have a join condition.
    An INNER JOIN only returns the records that satisfy the join condition.
    An OUTER JOIN always returns all the results of one (LEFT or RIGHT) or both (FULL) tables, returning nulls for all the requested data in the other table when the join condition is not met.

    Maybe that's not clear enough. I'll make a pair of contrived tables to demonstrate.

    people
    id | name
    01 | Bill
    02 | Tina
     
    items
    id | item
    01 | candy
    01 | ice cream
    03 | milk
    Seems simple, right? Here's the various queries and what they'd return:

    SELECT name, item FROM people INNER JOIN items USING (id)
    name | item
    Bill | candy
    Bill | ice cream

    SELECT name, item FROM people LEFT OUTER JOIN items USING (id)
    name | item
    Bill | candy
    Bill | ice cream
    Tina | NULL

    SELECT name, item FROM people RIGHT OUTER JOIN items USING (id)
    name | item
    Bill | candy
    Bill | ice cream
    NULL | milk

    SELECT name, item FROM people FULL OUTER JOIN items USING (id)
    name | item
    Bill | candy
    Bill | ice cream
    Tina | NULL
    NULL | milk
    Note that if you ever used real tables like this, your work would probably end up on The Daily WTF.
    --
    GLaDOS for President 2016! "Well here we are again. It's always such a pleasure." -- GLaDOS, 2011
  10. Re:heh by blirp · · Score: 2, Informative
    In order to pull this off you need to have alter session priveleges.

    No, you don't. What you need is to somehow be able to modify NLS_NUMERIC_CHARACTERS or NLS_DATE_FORMAT. This is easily demonstrated with ALTER SESSION. But there might be a bug/exploit somewhere down the road that allows this in some other manner. Each of the two exploits are unusable, but combined ...

    M.