Twitter-pwn’ed: the confessions of a lazy developer

This is a hard post to write since it is absolutely embarrassing to me and may cause me to lose serious geek-cred. However, I hope this is a useful mea culpa for others’ benefit. This morning I spent a while revising a script that accepted external input which I borrowed (and modified) from someone else. The original script used the external input safely – my modifications made it a true security nightmare. Basically, the script took content from the Twitter API and rerouted it through Jabber (XMPP) protocol. My change also sent the content through email.

If I had used the built-in SMTP features of ruby this post would have been unnecessary. However, as I was in a hurry (the excuse of a scoundrel) I simply piped the output through BASH to the mail command via ruby’s system() function. Also, I took no precautions to escape the external input from being executed by BASH itself. System admins and top-notch developers are now crying with laughter.

Why did I do this? Besides being an idiot, I did this because this script was a “one-off” and not something I was paid to develop. I needed a feature and, in the spirit of a developer (not a system administrator or security professional), I looked for the path of least resistance. With the system() call I could use my knowledge of the Linux command-line to accomplish my task. Since the original script was written in ruby, a language I have not used much at all, previously, I was able to add my needed feature in minutes. A couple more minutes would be all that was necessary to find out how to use ruby itself to accomplish this result. Laziness won over thoroughness and correctness. Result: a *huge* security hole.

Here’s what prompted me to invest in learning to add this feature in the Right Way™: a friend of mine who is an überGeek realized that, based on a clue I gave out about my script’s performance, he could have his way with my server via Twitter. I was Twitter-pwn’ed. Here’s what he sent me (knowing I watch my tweets via this script):

@rjamestaylor $(touch /tmp/test)

@rjamestaylor $(ls -la /tmp/test)

After he sent these two tweets my script sent me an email with this:

-rw-r--r-- 1 root root 0 Dec 27 03:39 /tmp/test

Yes. BASH executed his tweet (!) and as ROOT! So, if someone had tweeted “@rjamestaylor $(rm -rf /)” my server would be a barren husk of hardware. Worse, someone could have used my script — via Twitter! — to setup privileged user accounts, send spam (though small), attack other systems, etc. Why root (or as my geek friends would ask, WHY IN GOD’S NAME “root”?)? Simple: I was in a hurry. Stupid.

Lesson: spending the little bit of extra time necessary to add features without violating security protocols is always worth it. Sure, I could have just bought some CodeOffsets to assuage my guilt, but it was actually better to (1) shut down my script until (2) I fixed the security issues.

Turns out adding net::smtp to a script in ruby is painless. Now I have my feature and no exciting side-effects from rushed, careless development. In fact, most security holes I encounter in others’ code is due to the same thing: rush to add features without a review of implications. Anytime one takes external input from a user or the Internet (or Twitter) one must sanitize the input from unintended effects. This goes for SQL injection (parameters, people!) as well as simple command expansion attacks, among many other possible vectors.

So, go ahead and tweet BASH-expandable tweets to me, my code is not just offset, it’s fixed.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Ping.fm
  • StumbleUpon
  • Technorati
  • Tumblr
  • TwitThis
  • Fark
  • FriendFeed
  • HackerNews
  • Posterous
  • Slashdot

About rjamestaylor

Comments

  1. Roger Wyatt says:

    ouch…simply ouch. Good thing your friend was kind and ended up saving your butt.

    Thanks for the story.

  2. Daniel Story says:

    The funny thing is that this thought briefly occurred to me when I read your first tweet about the script… but I was in between rounds of Call of Duty and had completely forgotten to do anything mali^H^H^H^H helpful with it by the time I stopped playing. Xboxfail.

  3. rjamestaylor says:

    Daniel: this is why I put off fixing my quick addition for so long – hey, it’s Twitter…who would be able to overcome ADD to attack me? :)

  4. This post makes me feel like I’m at Software Developers’ Anonymous Meeting. “My name is Shannon, and I’ve been pwn’ed.” Yes, I’ve done similar things, and yes, you were very lucky to have a friend to point out the issue. I’m glad you shared the experience. More of us should share, since we really need constant reminders.

    I realize it’s our responsibility to code defensively, but I’m also angered at the time we have to devote to the practice. I am digusted and amazed by the people who will spend their time trying to break my code instead of doing something creative themselves. The worst thing about it is that they usually don’t gain a thing. They try to cleverly insert Ciallis links via SQL injection. If they succeed, they probably just bring down the app anyway. No one wins, and I’m stuck with a huge cleanup effort. What a waste.

  5. @meanrachel says:

    I have no idea what 98% of this post means, although that didn’t stop me from trying to understand it (unsuccessful). But I wanted to say: you’re not an idiot, just a smart person in a hurry!

    • rjamestaylor says:

      Very kind words, @MeanRachel :) — Takeaway: being careful isn’t just for big, well-funded projects. Even “quick one-offs” can have serious implications. Best practices are best practiced!

Bad Behavior has blocked 247 access attempts in the last 7 days.