Mistyped tag leads to exposure of Tumblr DB passwords and API keys





  • LOL, that is brutal. The mistake is brutal. The fact that it got pushed to production is brutal. Worst of all, their configuration file is brutal.



  • @Soviut said:

    LOL, that is brutal. The mistake is brutal. The fact that it got pushed to production is brutal. Worst of all, their configuration file is brutal.

    I've tried using Tumblr twice, both times it simply didn't fucking work. I don't understand why anybody uses a site that, from my perspective, has 0% uptime.

    Anyway, Tumblr is obviously incompetent, but what's with the morons in the thread saying to use INI? Srsly? What is this, 1992?



  • Let's go through the partial checklist:

    1. hard-coded DB connections (including plaintext passwords) in .php file: check
    2. hard-coded RFC1918 host addresses spewed all around the file (leaking information about internal topology): check.
    3. Monolitic monster script to handle everything: check.
    4. Home-brewed "where am i" test to see if we're running production or development: check.
    5. Ugly hand-hacked HTML to try and "pretty up" the resulting page: check.
    Yep. Looks just like most of the PHP I've hacked together over the last few years. Of course, my scripts happened to be used internally (by people who either knew the DB passwords, or at least had access to the physical machine), and came with dire warnings about what would happen if they were ever installed on a machine with direct Internet access.



  • @RichP said:

    Let's go through the partial checklist:

    1. hard-coded DB connections (including plaintext passwords) in .php file: check
    2. hard-coded RFC1918 host addresses spewed all around the file (leaking information about internal topology): check.
    3. Monolitic monster script to handle everything: check.
    4. Home-brewed "where am i" test to see if we're running production or development: check.
    5. Ugly hand-hacked HTML to try and "pretty up" the resulting page: check.

    Yep. Looks just like most of the PHP I've hacked together over the last few years. Of course, my scripts happened to be used internally (by people who either knew the DB passwords, or at least had access to the physical machine), and came with dire warnings about what would happen if they were ever installed on a machine with direct Internet access.

     

    • Lack of any use of a text editor that would vomit at "i<php": check
    • Lack of any sort of QA process: check
    • Changes go live to production straight away: check


  •  @dr spock said:

    @RichP said:

    Let's go through the partial checklist:

    1. hard-coded DB connections (including plaintext passwords) in .php file: check
    2. hard-coded RFC1918 host addresses spewed all around the file (leaking information about internal topology): check.
    3. Monolitic monster script to handle everything: check.
    4. Home-brewed "where am i" test to see if we're running production or development: check.
    5. Ugly hand-hacked HTML to try and "pretty up" the resulting page: check.

    Yep. Looks just like most of the PHP I've hacked together over the last few years. Of course, my scripts happened to be used internally (by people who either knew the DB passwords, or at least had access to the physical machine), and came with dire warnings about what would happen if they were ever installed on a machine with direct Internet access.

     

    • Lack of any use of a text editor that would vomit at "i<php": check
    • Lack of any sort of QA process: check
    • Changes go live to production straight away: check


    Actually, it's i?php, but still it should have been blatently obvious in anything but pure text (notepad, anyone?) editors.

    I do mostly PHP coding at work, and I have a general set of rules when pushing out updates:

    • Make sure production config file is read-only, so no accidental changes can be pushed to it.
    • Always test any changes from every possible angle before pushing to production
    • If your configuration requires more than a few lines (generally a single database connection info, always only accessable internally), pull the rest of your config from the database itself.
    • Before pushing out any changes to the config file or a file that could expose it, do a full readthrough of all the changes in code and check each file individually to make sure it's syntactically correct.

    Though it's just me for the most part right now, my boss does a few updates occasionally. we'll be bringing on people as we grow, however, and I'll make sure these rules are followed explicitly... along with my general rules about database layout and structure (no plaintext passwords, use individual salt for each password, stuff like that).


  • @blakeyrat said:

    I don't understand why anybody uses a site that, from my perspective, has 0% uptime.

    Because from their perspective, it has more. Duh.



  • Wow, seriously? Rule #1 of a public-facing PHP script:

    require_once "/path/outside/of/htdocs/config.php";

    You should never have a script with any config info under the docroot. The double WTF is not only did it dump the contents of the source, but it looks like it dumped a bunch of developer debugging info too. A public-facing server should never dump that kind of stuff.



  • @error_NoError said:

    Wow, seriously? Rule #1 of a public-facing PHP script:

    require_once "/path/outside/of/htdocs/config.php";

    You should never have a script with any config info under the docroot. The double WTF is not only did it dump the contents of the source, but it looks like it dumped a bunch of developer debugging info too. A public-facing server should never dump that kind of stuff.

    Actually, if that exact error was in the config file itself, you'd still be screwed.

    The issue is that require_once wouldn't recognize the included config file as a php file, so it dumps it out as plain text. The PHP parser is basically saying "This isn't php, so echo it." It doesn't matter if the file it outside of htdocs if the page accessing the file just dumps it as plain text anyway.

    The only way around it is to have php actually parse the config file instead of having it be php. That way if there's a typo or the file isn't recognized as the proper type, you get an error, which can be disabled, instead of a data dump.


  • Well doh you're right, it looks like TRWTF is me.



  • Wow, look at this:

    clickatell user name: 'davidkarp'

    clickatell password: 'JLVchl23'

    Who wants to bet that David Karp (the founder of Tumblr) uses that password for at least one other account?

    (Edit to add: I am not actually challenging anybody to hack David Karp, nor do I want to, myself. thought I should clarify that just in case he gets hacked and they find this post)



  • This is the kind of shit that I would expect from university graduates who know all about callbacks and lambdas but have no fucking clue about how to practically use them:

     

        // Shard configuration
        ShardManager::add(array(
          'db' => 'db-primary01',
          'callback' => function($key) { return ($key['tumblelog_id'] < 3000000); },
        ));
        ShardManager::add(array(
          'db' => 'db-primary02',
          'callback' => function($key) { return ($key['tumblelog_id'] >= 3000000 && $key['tumblelog_id'] < 6000000); },
        ));
        ShardManager::add(array(
          'db' => 'db-primary03',
          'callback' => function($key) { return ($key['tumblelog_id'] >= 6000000 && $key['tumblelog_id'] < 9000000); },
        ));
        ShardManager::add(array(
          'db' => 'db-primary04',
          'callback' => function($key) { return ($key['tumblelog_id'] >= 9000000 && $key['tumblelog_id'] < 12695000); },
        ));
        ShardManager::add(array(
          'db' => 'db-primary05',
          'callback' => function($key) { return ($key['tumblelog_id'] >= 12695000); },
        ));
    

     

    At least it isn't as bad as the leaked Facebook code - Tumblr at least uses classes.

     

    require_once('lib/GiantOctopus.php');

     

    WAIT WHAT

    @blakeyrat said:

    Anyway, Tumblr is obviously incompetent, but what's with the morons in the thread saying to use INI? Srsly? What is this, 1992?

    Since all PHP's vital config settings are stored in an INI file, most PHP programmers are at least familiar with that form of data storage. (If they weren't, God knows how they'd store settings. Maybe with smoke signals.) I'm waiting for the shitstorm that ensues when the PHP group decides to move to XML config...



  • @The_Assimilator said:

    ShardManager::add(array( 'db' => 'db-primary01', 'callback' => function($key) { return ($key['tumblelog_id'] 'db-primary02', 'callback' => function($key) { return ($key['tumblelog_id'] >= 3000000 && $key['tumblelog_id'] 'db-primary03', 'callback' => function($key) { return ($key['tumblelog_id'] >= 6000000 && $key['tumblelog_id'] 'db-primary04', 'callback' => function($key) { return ($key['tumblelog_id'] >= 9000000 && $key['tumblelog_id'] 'db-primary05', 'callback' => function($key) { return ($key['tumblelog_id'] >= 12695000); }, ));
     

    ?

    You copypasted some of the cde and then modifed so taht it doesn't make any sense.


  • @dhromed said:

    @The_Assimilator said:

    ShardManager::add(array(
    'db' => 'db-primary01',
    'callback' => function($key) { return ($key['tumblelog_id'] 'db-primary02',
    'callback' => function($key) { return ($key['tumblelog_id'] >= 3000000 && $key['tumblelog_id'] 'db-primary03',
    'callback' => function($key) { return ($key['tumblelog_id'] >= 6000000 && $key['tumblelog_id'] 'db-primary04',
    'callback' => function($key) { return ($key['tumblelog_id'] >= 9000000 && $key['tumblelog_id'] 'db-primary05',
    'callback' => function($key) { return ($key['tumblelog_id'] >= 12695000); },
    ));
     

    ?

    You copypasted some of the cde and then modifed so taht it doesn't make any sense.

    When I edit that post it has the correct code, when viewed it doesn't. Yay for CS's insane sanitising of input.



  •  True, true.

    I fixed it now, by re-typing all the < characters, so that CS/TinyMCE can entitize them.


Log in to reply