inazar's avatar

inazar

Codemonkey
273 Watchers64 Deviations
123.4K
Pageviews

The following information has been declassified from the DeviantArt Code Archive, after the decommissioning of the Holiday Puzzle.

Screenshot 2021-05-31 at 22.38.21

Back in the mists of time (or "2011") DA's annual Holiday Extravaganza sale needed a little sprucing up, so we came up with the idea of a simple Threes-alike puzzle game: click on groups of three or more Christmas-themed items, and they'd clear from the screen. Clear as much as you could, and the screen would refill as you moved up a level; cross a threshold with your final score, and get a discount code to use in the shop against prints and DevWear (yes, we once had merch too).


As it turned out, the promise of a discount brought out some of the more devious deviants, and they started finding ways to get at the codes without going to the trouble of playing the game...


Countermeasure I: Server-side Vouchers

Very quickly we found out that an enterprising person, learning that this game provided discount codes, could simply read through the source code of the game running in their browser, to see what came up at the end. The end-screen block of code would have any discount codes right there to be plucked out, without playing the game at all.


So that wouldn't do. To hide the voucher codes from public view would mean keeping them on the server, and sending the score over at the end of the game to check if it was high enough to trigger a voucher discount.


And you can already see where this would go wrong.

Countermeasure II: Game Run Timings

The hurdle of sending the score to the server isn't much of a thing to overcome in the grand scheme: our young hacker can simply send requests using software that isn't a browser. To try to combat this, we began to store two things in the state of the game: a time when the player would start the game, and a time for the end of the game. All of that would get sent to the server which would look at the score and try to work out if there had been a reasonable about of game time involved: if you submitted a game with one second between start and end, and a 10,000 score, that would be suspicious.


That said, the onus was on the browser to send the times and the score. Which means we didn't actually fix anything: once our enterprising hacker had some data regarding what we thought was "not very suspicious" in terms of how long a game should take, it was a short matter of crafting the request so the score and times would match.

Countermeasure III: Server-Side Game Run Timings

More hurdles were needed, and they came in the form of storing that time information at the server: making a request when the game starts, and another when the game ends, and using the times of the requests to make that comparison against the score. That bought us a couple of days...


You may already see the flaw in this plan: if the young hacker can send one request programmatically, they can send two separated by a timespan, it's literally two lines of code instead of one.

Countermeasure IV: Checksumming

We needed to send something to the server to authenticate the score, so we'd know it was coming genuinely from the game. So the idea was to use something like the Luhn checksum (which is used on credit card numbers) to add together the digits of the score and stick another digit on the end, which we could then pull out and check at the server.


It was a cunning plan, with a fatal flaw: any checksum we used would need to be calculated at the client, using code that anyone could see and replicate. And so it proved: after a longer-than-usual period of genuine scores in the database, we started to see insane scores being posted again as some endeavouring person reverse-engineered the checksum and started using it in their own code.


We needed something... special.

Countermeasure The Final: Virtual Checksumming Machine

Screenshot 2021-06-07 at 08.33.17

Checksumming the score was a good idea, it was just the fact that the checksum algorithm was available in the code to be reverse-engineered that let it down. So we decided to use a checksum written in a different language, for a different computer architecture altogether, and cram that in sideways using an interpretative emulator (not a virtual machine in the traditional sense, perhaps, but in the same spirit).


The more astute reader may notice two things about the code involved: it's Z80 assembly, and it's an implementation of CRC-16. Compare the relatively clean code there, to the obfuscated emulation monstrosity that ended up in the Holiday Puzzle final code:

Screenshot 2021-06-06 at 21.11.28

And you can see why our enterprising young hackers gave up on trying to work out the checksum algorithm. From the introduction of the obfuscated checksum countermeasure, to the last score submitted in 2019, we didn't see any more insane or suspicious scores submitted. So I guess it worked.


The takeaway is that security is an ongoing battle, even for something as small and silly as the Holiday Extravaganza's puzzle game from 2011; what works for a short while may be circumvented again, and what ends up working for long periods might not be what you expected.


For bonus points (no points will actually be awarded), see if you can work out all the obfuscation measures in the emulation; there are at least three that I can spot off the top of my head.

Join the community to add your comment. Already a deviant? Log In


Fifteen. Jeepers. There are brick and mortar businesses that fail within 15 years, so it's awesome that DA's had sticking power for all this time. On the up and up...

  • How long have you been on DeviantArt?
    Let's see. TripleFault was my first DA account, and he appears to have signed up somewhere over nine years ago. Not active at all, though, until I joined staff in '11.
  • What does your username mean?
    Well, my name is Imran Nazar. You get the idea. If you want the story about "TripleFault", that's a whole 'nother thing and a lot more nerdy.
  • Describe yourself in three words.
    Don't Want To.
  • Are you left or right handed?
    Right. I'm atrocious with my left hand, at really anything.
  • What was your first deviation?

    But I was taking photos before then. That particular one is from the beach in Antalya, and there's a whole series of photos from the solar eclipse that passed through there, that I should dig out and upload sometime.
  • What is your favourite type of art to create?
    I like to think of myself as a fair-to-middling writer, so literature: science fiction in particular. I always tend to run out of words after 600 or so, though. Need to work on my character development, I'm told.
  • If you could instantly master a different art style, what would it be?
    Oh, gee. Probably manga or something similarly styled. Things like the venerable Jet Set Radio, that kind of cel-shaded look.
  • What was your first favourite?
    <da:thumb id="273508167"/>

    I instantly thought this was just fantastic. I don't favourite much (and I probably should more), but that just struck me.
  • What type of art do you tend to favourite the most?
    Landscapes feature a lot. I gravitate towards photos where people are either conspicuously missing, or irrelevant.
  • Who is your all-time favourite deviant artist?
    Burtn lives in a beautiful part of the world, and has some astonishing landscapes taking full advantage of the scenery.
  • If you could meet anyone on DeviantArt in person, who would it be?
    Probably copperrein or Erzsabet; we run into each other occasionally on dAmn, and it seems that meeting them would be a fun time.
  • How has a fellow deviant impacted your life?
    I'll take a leaf out of helloandre's book here, and briefly mention the many late-night conversations and adventures with pachunka and allixsenos.
  • What are your preferred tools to create art?
    Keyboard. It's a little facetious to treat the code that one writes as art, but very occasionally it can be raised to a higher form, something elegant and creative. Doesn't happen very often for me, of course.
  • What is the most inspirational place for you to create art?
    When I'm writing (be it code or something fiction-y), it's almost exclusively from the couch. As long as I'm comfortable, my mind can roam.
  • What is your favourite DeviantArt memory?
    Traipsing (well, being towed by pachunka) around the Montparnasse district of Paris, in the wee hours of a summer morning.
    Blast Radius by inazar
    Montparnasse Tower is, in our considered opinion, a vertical assembly building for the French space programme. Don't tell anyone.


Skin by SimplySilent
Join the community to add your comment. Already a deviant? Log In
This RFC, "Hypertext Coffeepot Control Protocol for Tea Efflux Appliances", was published by the RFC Editor on Apr 1, 2014.

Independent Submission
Request for Comments: 7168
Updates: 2324
Category: Informational
ISSN: 2070-1721

Abstract

The Hyper Text Coffee Pot Control Protocol (HTCPCP) specification does not allow for the brewing of tea, in all its variety and complexity.  This paper outlines an extension to HTCPCP to allow for pots to provide networked tea-brewing facilities.

Status of This Memo

This document is not an Internet Standards Track specification; it is published for informational purposes.

This is a contribution to the RFC Series, independently of any other RFC stream.  The RFC Editor has chosen to publish this document at its discretion and makes no statement about its value for implementation or deployment.  Documents approved for publication by the RFC Editor are not a candidate for any level of Internet Standard; see Section 2 of RFC 5741.

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at www.rfc-editor.org/info/rfc716….

Copyright Notice

Copyright (c) 2014 IETF Trust and the persons identified as the document authors.  All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (trustee.ietf.org/license-info) in effect on the date of publication of this document.  Please review these documents carefully, as they describe your rights and restrictions with respect to this document.  Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

1.  Introduction

As noted in the Hyper Text Coffee Pot Control Protocol, coffee is renowned worldwide as an artfully brewed caffeinated beverage, but coffee shares this quality with many other varied preparations based on the filtration of plant material.  Foremost, among these are the category of brews based on the straining of water through prepared leaves from a tea tree: the lineage and history of the tea genus will not be recounted as part of this paper, but evidence shows that the production of tea existed many thousands of years ago.

The deficiency of HTCPCP in addressing the networked production of such a venerable beverage as tea is noteworthy: indeed, the only provision given for networked teapots is that they not respond to requests for the production of coffee, which, while eminently reasonable, does not allow for communication with the teapot for its intended purpose.

This paper specifies an extension to HTCPCP to allow communication with networked tea production devices and teapots.  The additions to the protocol specified herein permit the requests and responses necessary to control all devices capable of making, arguably, the most popular caffeinated hot beverage.

1.1.  Terminology

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119.

2.  HTCPCP-TEA Protocol Additions

The TEA extension to HTCPCP adapts the operation of certain HTCPCP methods.

2.1.  BREW and POST Methods

Control of a TEA-capable pot is performed, as described in the base HTCPCP specification, through the sending of BREW requests.  POST requests are treated equivalently, but they remain deprecated.  Tea production differs from coffee, however, in that a choice of teas is often provided for client selection before the tea is brewed.  To this end, a TEA-capable pot that receives a BREW message of content type message/teapot MUST respond in accordance with the URI requested, as below.

2.1.1.  The / URI

For the URI /, brewing will not commence.  Instead, an Alternates header as defined in RFC 2295 MUST be sent, with the available tea bags and/or leaf varieties as entries.  An example of such a response is as follows:

   Alternates: {"/darjeeling" {type message/teapot}},                {"/earl-grey" {type message/teapot}},                {"/peppermint" {type message/teapot}}

The following example demonstrates the possibility of interoperability of a TEA-capable pot that also complies with the base HTCPCP specification:

   Alternates: {"/" {type message/coffeepot}},                {"/pot-0/darjeeling" {type message/teapot}},                {"/pot-0/earl-grey" {type message/teapot}},                {"/pot-1/peppermint" {type message/teapot}}

TEA-capable HTCPCP clients MUST check the contents of the Alternates header returned by a BREW request, and provide a specific URI for subsequent requests of the message/teapot type.

A request to the / URI with a Content-Type header of message/coffeepot SHOULD also be responded to with an Alternates header in the above format, to allow TEA-capable clients the opportunity to present the selection of teas to the user if inferior caffeinated beverages have initially been requested.

2.1.2.  Variety-Specific URIs

TEA-capable pots follow the base HTCPCP specification when presented with a BREW request for a specific variety of tea.  Pots SHOULD follow the recommendations for brewing strength given by each variety, and stop brewing when this strength is reached; it is suggested that the strength be measured by detection of the opacity of the beverage currently under brew by the pot.

TEA-capable clients SHOULD indicate the end of brewing by sending a BREW request with an entity body containing stop; the pot MAY continue brewing beyond the recommended strength until this is received.  If the stop request is not sent by the client, this may result in a state inversion in the proportion of tea to water in the brewing pot, which may be reported by some pots as a negative strength.

If a BREW command with an entity body containing stop is received before the recommended strength is achieved, the pot MUST abort brewing and serve the resultant beverage at lesser strength.  Finding the preferred strength of beverage when using this override is a function of the time between the TEA-capable pot receiving a start request and the subsequent stop.  Clients SHOULD be prepared to make multiple attempts to reach the preferred strength.

2.2.  Modified Header Fields

HTCPCP-TEA modifies the definition of one header field from the base HTCPCP specification.

2.2.1.  The Accept-Additions Header Field

It has been observed that some users of blended teas have an occasional preference for teas brewed as an emulsion of cane sugar with hints of water.  To allow for this circumstance, the Accept-Additions header field defined in the base HTCPCP specification is updated to allow the following options:

   addition-type   = ( "*"                      | milk-type                      | syrup-type                      | sweetener-type                      | spice-type                      | alcohol-type                      | sugar-type                      ) *( ";" parameter )    sugar-type      = ( "Sugar" | "Xylitol" | "Stevia" )

Implementers should be aware that excessive use of the Sugar addition may cause the BREW request to exceed the segment size allowed by the transport layer, causing fragmentation and a delay in brewing.

2.3.  Response Codes

HTCPCP-TEA makes use of normal HTTP error codes and those defined in the base HTCPCP specification.

2.3.1.  300 Multiple Options

A BREW request to the / URI, as defined in Section 2.1.1, will return an Alternates header indicating the URIs of the available varieties of tea to brew.  It is RECOMMENDED that this response be served with a status code of 300, to indicate that brewing has not commenced and further options must be chosen by the client.

2.3.2.  403 Forbidden

Services that implement the Accept-Additions header field MAY return a 403 status code for a BREW request of a given variety of tea, if the service deems the combination of additions requested to be contrary to the sensibilities of a consensus of drinkers regarding the variety in question.

A method of garnering and collating consensus indicators of the most viable combinations of additions for each variety to be served is outside the scope of this document.

2.3.3.  418 I'm a Teapot

TEA-capable pots that are not provisioned to brew coffee may return either a status code of 503, indicating temporary unavailability of coffee, or a code of 418 as defined in the base HTCPCP specification to denote a more permanent indication that the pot is a teapot.

3.  The message/teapot Media Type

To distinguish messages destined for TEA-capable HTCPCP services from pots compliant with the base HTCPCP specification, a new MIME media type is defined by this document.  The Content-Type header of a POST or BREW request sent to a TEA-capable pot MUST be message/teapot if tea is to be requested.

4.  Environmental Considerations

As noted in Section 2.1, a BREW request with a Content-Type header field of message/teapot to a TEA-capable pot will result in an Alternates header being sent with the response, and a pot will not be brewed.  However, if the BREW request has a Content-Type of message/coffeepot, and the pot is capable of brewing coffee, the service's behavior will fall back to the base HTCPCP specification and a pot will be brewed.

If the entity returned by the server when brewing commences contains a TEA-compliant Alternates header indicating message/coffeepot and the client does not want coffee, the client SHOULD then send a BREW request with an entity body containing stop.  This will result in wasted coffee; whether this is regarded as a bad thing is user-defined.

Such waste can be prevented by TEA-capable clients, by first requesting a BREW of type message/teapot and then allowing selection of an available beverage.

5.  Security Considerations

As with the base HTCPCP specification, most TEA-capable pots are expected to heat water through the use of electric elements, and as such will not be in proximity to fire.  Therefore, no firewalls are necessary for communication with these pots to proceed.

This extension does support communication with fired pots, however, which may require heat retention and control policies.  Care should be taken so that coal-fired pots and electrically heated kettles are not connected to the same network, to prevent pots from referring to any kettles on the network as darkened or otherwise smoke driven.

6.  Acknowledgements

This extension to the HTCPCP specification would not be possible without the base specification, and research on networked beverage production leading up thereto.  In that vein, the author wishes to acknowledge the sterling work of Larry Masinter in the development of the leading protocol for coffee pot communication.

Many thanks also to Kevin Waterson and Pete Davis, for providing guidance and suggestions during the drafting of this document.

Join the community to add your comment. Already a deviant? Log In

The Lowest Hash

1 min read
So here's another interesting little exercise, inspired by the block confirmation technique of a certain Internet cryptocurrency. Take a hashing algorithm, say MD5, and see how numerically low a hash you can find. That's it, that's all.

Of course, the nuances come in how you build strings to test. At random, sequential, counting up from a random start point? Do you use an interpreted script language, for ease of hacking up the script, or do you build for speed? Use OpenSSL's hash library or write your own MD5 implementation using the crazy new Intel AVX?

Either way, I've had a program running for a couple of hours now, and so far I've gotten as low as:

>,&Wj has an MD5 hash of 000000000756153c5a6776a1d40bb2c3

Can you do any better?
Join the community to add your comment. Already a deviant? Log In
So I thought I'd write a little about FizzBuzz, and about Brainfuck, and what happens when the two collide.

FizzBuzz is one of the classic "simple computer programs": first introduced as an interview question, it makes for a good tutorial on the basic concepts of iteration (using sequential values) and branching (making decisions based on certain conditions).

The way it goes is: Print out the numbers 1 to 100, but print "Fizz" instead of the number if it's a multiple of 3, and "Buzz" if it's a multiple of 5. So your output might look like this:
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16...
So what happens when you try to write this in various programming languages? Let's have a look at some simple JavaScript:
alert((function() {
    var out = [], i, temp;
    for (i = 1; i <= 100; i++) {
        temp = "";
        if (i % 3 == 0) temp += "Fizz";
        if (i % 5 == 0) temp += "Buzz";
        out.push(temp ? temp : i);
    }
    return out.join(" ");
})());
Relatively simple to follow in a high-level language, but what happens when you go lower? One of the lowest-level languages is Brainfuck, which provides just eight instructions and a very limited memory space and environment. So the above segment of JavaScript translates into the following Brainfuck:
Master counter = 100
>++++++++++[<++++++++++>-]

Set up alphabetical outputs
>>>>>>>>>>>>>>>>
++++[>++++<-]>
[<<<<<<<++>+++>++++>++++++>+++++++>+++++++>++++>-]
<++<+++++<++++++++++<+++++++++<++++++
<<<<<<<<<<<<<

[
    Increment by3 and by5 remainder counters
    and clear the "was divisible" flag
    >+>+>[-]

    If the by3 counter is 0 print Fizz
    and increment the "was divisible" flag
    >>>>[-]>[-]<<<<<<<
    [>>>>>>+>+<<<<<<<-]
    >>>>>>[<<<<<<+>>>>>>-]+
    >---[<->[-]]
    <[
        >>>>>>.>.>..<<<<<<<<
        <<<<+<<[-]>>>>>>-
    ]

    If the by5 counter is 0 print Buzz
    and increment the "was divisible" flag
    <<<<<[>>>>>+>+<<<<<<-]
    >>>>>[<<<<<+>>>>>-]+
    >-----[<->[-]]
    <[
        >>>>>>>>>>.<.<..<<<<<<<<
        <<<<+<[-]>>>>>-
    ]

    Increment the low byte of the three byte representation
    <+

    If the low byte is 10 increment the second byte and zero the low
    >[-]>[-]>[-]<<<
    [>+>+>+<<<-]
    >[<+>-]+
    >----------[<->[-]]
    <[
        <<+>[-]>-
    ]

    If the second byte is 10 increment the high byte and zero the second
    >[-]>[-]<<<<
    [>>+>+>+<<<<-]>>[<<+>>-]+
    >----------[<->[-]]
    <[
        <<<+>[-]>>-
    ]

    If the "was divisible" flag is 0 print the number
    [-]>[-]
    <<<<<[>>>>+>+<<<<<-]>>>>[<<<<+>>>>-]+
    >[<->[-]]
    <[
        If the high byte is set print it out
        Cheat slightly because of the following code section
        [-]>[-]
        <<<<
        [>>>+>+<<<<-]>>>>[<<<<+>>>>-]
        <[>++++++++[<++++++>-]<.-.[-]]
    
        If the second byte is set print it out
        This will fail to print the first 0 in "100" so that gets printed above
        [-]>[-]
        <<<
        [>>+>+<<<-]>>>[<<<+>>>-]
        <[>++++++++[<++++++>-]<.[-]]
    
        Print the low byte regardless of value
        [-]>[-]<<[>+>+<<-]>>[<<+>>-]++++++++[<++++++>-]<.[-]
    ]

    Print a space and loop
    >>>>.
    <<<<<<<<<<<-
]
Easy, right?
Join the community to add your comment. Already a deviant? Log In
Featured

Anti-Cheat Countermeasures in the Holiday Puzzle by inazar, journal

DeviantArtist Questionnaire by inazar, journal

RFC 7168: HTCPCP-TEA by inazar, journal

The Lowest Hash by inazar, journal

FizzBuzz in Brainf*ck by inazar, journal

Support My Work
Browse My Shop