Maverick StClare’s company recently adopted a new, SaaS solution for resource planning. Like most such solutions, it was pushed from above without regard to how people actually worked, and thus required the users to enter highly structured data into free-form, validation-free, text fields. That was dumb, so someone asked Maverick: “Hey, could you maybe write a program to enter the data for us?”

Well, you’ll be shocked to learn that there was no API, but the web pages themselves all looked pretty simple and the design implied they hadn’t changed since IE4, so Maverick decided to take a crack at writing a scraper. Step one: log in. Easy, right? Maverick fired up a trace on the HTTPS traffic and sniffed the requests. He was happy to see that his password wasn’t sent in plain text. He was less happy to see that it wasn’t sent using any of the standard HTTP authentication mechanisms, and it certainly wasn’t hashed using any algorithm he recognized. He dug into the code, and found this:

function Foggy(svInput)
{
  // Any changes must be duplicated in the server-side version of this function.
  var svOutput = "";
  var ivRnd;
  var i;
  var ivLength = svInput.length;

  if (ivLength == 0 || ivLength > 158)
  {
        svInput = svInput.replace(/"/g,"&qt;");
        return svInput;
  }

  for (i = 0; i < ivLength; i++)
  {
        ivRnd = Math.floor(Math.random() * 3);
        if (svInput.charCodeAt(i) == 32 || svInput.charCodeAt(i) == 34 || svInput.charCodeAt(i) == 62)
        {
          ivRnd = 1;
        }
        if (svInput.charCodeAt(i) == 33 || svInput.charCodeAt(i) == 58 || svInput.charCodeAt(i) == 59 || svInput.charCodeAt(i) + ivRnd > 255)
        {
          ivRnd = 0;
        }
        svOutput += String.fromCharCode(ivRnd+97);
        svOutput += String.fromCharCode(svInput.charCodeAt(i)+ivRnd);
  }

  for (i = 0; i < Math.floor(Math.random() * 8) + 8; i++)
  {
        ivRnd = Math.floor(Math.random() * 26);
        svOutput += String.fromCharCode(ivRnd+97);
  }

  svOutput += String.fromCharCode(svInput.length + 96);
  return svOutput;
}

I… have so many questions. Why do they only replace quotes if the string is empty or greater than 158 characters? Why are there random numbers involved in their “hashing” algorithm? I’m foggy about this whole thing, indeed. And ah, protip: security through obscurity works better when nobody can see how you obfuscated things. All I can say is: “aWcjaacvc0b!cVahcgc0b!cHaubdcmb/gmzyrcoqhp”.

[Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today!