Text
Enlightened Hospitality
It’s a bit odd that I wrote my last post (Service Oriented Culture) just before starting Danny Meyer’s fantastic Setting the Table. There are numerous overlapping concepts between my little post and Meyer’s book - about treating people right and trying not to be an asshole. But one thing Danny hits on the head that I failed to mention is that the team comes first in the pyramid-of-needs that makes up his set of “enlightened hospitality” practices. The premier example he gives is banning smoking in Union Square Cafe in an attempt to protect his team from facing the ill effects of smoke exposure. I’ve seen this commitment to protecting the team in my brother when he sticks up for the numerous young women on staff when disrespectful men come out to harass.
But I should also note that it is imperative to be hospitable to your coworkers. Why bother helping out your paying customers if you won’t give your cube-mate or back-waiter a sincere hello? You all have to work towards some common goal, you are in no way competing with one another. If you are trying to find a counter example realize that both you and your internal competitor will both be unemployed if the company isn’t successful. Your company’s success, ironically, also depends on this hospitality. Your client success manager shouldn’t have to tell you that the request they’re making is being passed down from some high-profile client - you should trust that client representative to pass down to you the most important of requests while protecting you from inane bullshit.
tl;dr: continue to be nice to folks both inside and outside of your perceived team.
1 note
·
View note
Text
Service Oriented Culture
I recently took on a second job as a host at a small new restaurant. I wanted in on this place, Juliet, because I love food and doing this on weekends could help me get familiar with the food & bev scene in Charleston. After two weeks on the job I realized that I’m also just into the idea of customer service; the return on investment for things as easy as remembering someone’s name is insane. When expectations are basic, it’s not difficult to exceed patron’s expectations. Well, sure, smiles and customer satisfaction pay off immediately but repeat business pays off in the traditional sense over time.
To be sure, you have to remain genuine throughout any customer interactions. Don’t lie to make things seem more personalized – don’t say you’re going out of your way for this particular patron when you would’ve done it for anyone. Instead, use good old fashioned spin to phrase things that may be unsavory as though they may be in the customer’s interest. Be prepared with alternatives as well: “I can’t offer you tier two, but we’ll give you tier one for no extra charge” or whatever the circumstances allow for.
Being flexible goes miles as well. It piggybacks on being prepared with satisfactory alternatives. Doing something simple may seem like a big effort to your clients. When I worked at J. Crew in high school a nice woman asked me when we would get a particular set of shorts back in stock – we had no idea, so I offered to jot down her number and alert her when a new shipment came in. She was elated and it only cost me one sticky note and, later, a 45 second phone call. Don’t refuse to help someone out because it’s outside of standard practice. Be flexible and come up with a reasonable alternative that will work for you and them. Flexibility also applies to the words you use in these interactions – try not to make things sound like dead ends when there are valuable alternatives within arm’s reach.
Satisfying customers is as easy as seeming human: using full sentences, putting in what would be a normal amount of effort in any other interpersonal interaction, making other folks happy, etc. It makes no sense to me that standards for communication drop in contexts of sales – it’s reasonable for consumers to be wary of salespeople, but that’s unnecessary if everyone stopped trying to take advantage of each other. When being flexible and offering alternatives to your customers, don’t use it as an opportunity to upsell; be a rock of trust for the consumer. Consumers should trust the folks closer to the product, service, menu, etc, but the tendency for those more familiar with the goods to take advantage of their knowledge in order to extract more ‘value’ from the customer forces consumers to stay on guard. Providing good customer service is a win-win: the customer has the best possible experience, making the most of what you have to offer plus they feel comfortable and may be more likely to return in the future. If you go for the short-term win by upselling, putting your reputation on the line, you may lose the opportunity to make sales later. I think it’s a pretty clear embodiment of karma, eh?
I’m thinking about this because last night DJ and I went to Fig for dinner. Juliet’s closed on Mondays so we had the evening off. The experience was extremely smooth – DJ and I sat in awe. Every person we interacted with knew every detail of the menu. They were all exceptionally personable and offered detailed, trustworthy recommendations. There was a clear symbiosis wherein the staff’s commitment and passion for the menu, experience, and service meshed with DJ and I’s fascination with food & wine, commitment to service, and familiarity with the scene. Imagine being a waiter and serving folks who don’t give a hoot about what you’re doing, the experience you’re trying to cultivate; imagine being an eater who’s committed to learning about food and service and facing a stiff or robotic waiter. The more interest people show for each other’s passion areas, the more satisfying these interactions can be.
0 notes
Text
Skirting project goals
In my earlier post, I said I wanted to set up my spring project (a little scheduling web app) only using infrastructure that is free-of-charge. After spending a while trolling the web looking for the cheapest hosted database, I could not find any for less than $10 per month. Most of the popular cloud service providers offer some weird, proprietary “nosql” “database” that’s usually a variant of a key-value store: Amazon has Dynamo, Google has ‘Cloud Datastore’ (creative naming, as always), and I bet Heroku has a similar thing (their free-tier relational database is limited to like 10k rows or 5mb lol).
Alas, my solution, I think, will be to set install mysql-server on the $5/month Digital Ocean box that I keep as a playground (the only things running on this box are my hacker news scraper on a cron job and sshd). It’s a bit of a bummer since I’ll have to maintain the database myself. I am terrified of being #online and will have to lookup how to enable key-based authentication on 32-bit mysql and set up harsh firewall rules, etc, etc.
But, where will the app itself run? I am leaning towards Google App Engine - I used it for my senior project in school so I know know the basics of setting up a new project. More importantly, they have pretty generous ‘always-free’ usage limit: 28 compute-hours per day. They also give you 100 emails per day which should totally cover the amount of notifications I plan to have the service generate.
My other goal was to avoid charging “avoid charging money for the majority of users”. I plan to offer it on a pay-what-you-want model - it seems that a lot of, uh, podcasts and #content #creators get money like that. I like the patreon model that’s like a kickstarter for things that are real; you can set up tiers of ‘rewards’. I’ll have to play that bit by ear though.
0 notes
Text
“Complex Logic” in Go Templates
Last week, I was looking to do something in a Go template that I obviously should not have been trying to do. In my dive through stackoverflow and the mailing lists, I came across a pretty funny quip: Accipiter Nisus said “Whether or not assigning a new value to a variable is considered complex logic might be up for discussion.” And, of course, I sat at my desk laughing at the dystopian hellscape through which we each wade every day.
I don’t entirely agree with the idea but, in this context, it’s right. I was trying to solve the wrong problem. Or the right problem in a sub-optimal way due to a misunderstanding of the tools I had at my disposal.
The problem I was trying to solve was a pretty straightforward web programming task - after a ‘delete’ action, remove an element (and its children) from the page. I already had an AJAX endpoint to handle the delete request and I wanted to add some client-side stuff to handle the clicks. My naive javascript skills told me to add unique IDs to each element that users could click (so I could getElementById later). That’s when I started trying to add some sort of accumulator to the template ({{i := 0}}, etc) which is not possible in Go’s templating engine.
My solution was to set the IDs of those interactive elements via javascript after the page loaded. It is pretty bad. I worked through some of a javascript tutorial like 3 days after I wrote this shitty code and now I think I know a more idiomatic way to do it: using document.querySelecorAll to grab all of the interactive things I wanted to work with. Then add an event listener on the appropriate child element (delete button) that makes the AJAX request and removes the outer element on success. This approach is somewhat limited by scoping issues, for example, if you had:
<div class="”deletable”"> Matt <button type="”button”">delete</button> <div>
The click listener on the button should not remove this, but it could remove this.parentNode or the handler could be bound to the div element.addEventListener(“click”, deleteHandler.bind(outerDiv));
Making use of javascript’s this keyword and iterating across the nodelist returned by querySelectorAll are thousands of times better than trying to cajole a template to do something it wasn’t designed to do.
The moral of the story is that you should learn javascript.
tl;dr: if you’re having trouble doing seemingly simple things in your html templates, you’re probably approaching the problem incorrectly.
0 notes
Text
Spring Project - Scheduling
In the world of computer science, there are many difficult problems under the ‘scheduling’ umbrella - interrupts, multi-threading, locks, and so on. However, in the real world, there are seemingly simple scheduling tasks that human people engage in (either via manual arrangement or with the help of #software). The specific, human example I’m thinking of is scheduling part-time employees in a food & bev environment.
My brother, DJ, is helping open a few restaurants while managing a coffee shop. I have often seen him come home, open up google calendar, and begin to drag and drop 4, 6, and 8 hour blocks while calculating, in his head, which roles (dishwasher, barista, etc) need to be filled when, who can fill them, and who has requested time off. Of course, being an annoying software boy, I made fun of him for not using some product that could take in the resource pool, constraints, and desired staffing and output a decent schedule.
It turns out there are 2 SaaS products that aim to solve this problem and many full-blown HR systems that allow admins to schedule staff. These 2 standalone options are extrememly overpriced (and probably include features that are only used by a small minority of organizations).
When I Work is a beautiful product that has iOS and Android apps ready to download. It's about $1 per user. They have a hard-to-find free tier that is significantly limited (< 6 users, no hallmark features, etc). It seemed like an OK choice for a very-small place. But! It only allows schedules to be planned 2 weeks ahead of time (in the free version only, I think).
Schedulefly is not as sleek as When I Work, but it is at least as powerful (plus you can schedule arbitrarily far into the future as far as I can tell). But it rather expensive - with the cheapest plan starting at $30 per month.
Goal
Write a simple-to-use scheduling web app exclusively using free cloud services. I want to avoid charging money for the majority of users. Sure, it'd be fun to make some money with this, but I think that's where our friends at Schedulefly went wrong. If I can use free-tier AWS/GCE resources, then the only 'cost' of running it will be my time.
Minimum requirements:
employees have skills that correlate with roles they can play for a shift of work (running the register, busboy, etc)
employees can describe their availabilty and a maximum number of hours they're willing to work per week
admins (managers?) can describe which skills each employee has
admins describe how many of each role they want at any time during a day
admins can reassign shifts after the system has assigned them
Table stakes for a real product:
admin-approved shift swaps
notifications of shift changes
templates for typical week schedules
multiple restaurant management (it can probably be more general than restaurants, pretty much any place with multiple parttime employees like retail storefronts and so on)
0 notes
Text
Tech Internship Navigation for Students and Hiring Managers

(four great interns in a decommissioned datacenter)
While I was in school, I had the formative privilege of interning with a range of different organizations. I’ve found that what I aimed to learn in each experience remained fairly consistent, while my employers’ expectations varied wildly. I think of internships as long-term interviews during which the intern should strive to provide value to their employer. It’s also a great opportunity for a young person without a tight grasp on the industrial landscape to get a feel for different work environments before committing to a permanent position. At the same time, employers should dance along with their interns - pushing them to figure out how much value they could bring to the organization in a full-time setting.
Gaining work experience before graduation is one of the most useful, rewarding pursuits a young person can follow. Students have the opportunity to apply what they’re learning in the classroom which helps with both information retention in the classroom and job performance at the office. At the same time, there’s a whole bunch of stuff going on out in the wild that is nowhere on the syllabus; picking up these industry practices is significantly easier in the workplace than in a side project. Internships are possibly the only way to slowly mold your lifestyle from the classroom to the office with limited shock. And, oftentimes, STEM internships offer wages better than standard entry-level part-time jobs. It’s hard to speak for other industries, but no one should be taking unpaid computer science internships in 2017. There are often clear-cut laws regarding how and when internships can be unpaid; interns are usually forbidden from doing work and relegated to ‘shadowing’ or whatever when they’re unpaid. If you’re considering taking an unpaid internship please log on to google.com and search for your local labor laws.
Asking too much of your interns is myopic and greedy. It is very simple: Asking two part-time interns to build your product from the ground up with no technical oversight is exploitative. Sure, it might feel cheap in the short term, but as soon as you scale up and bring in experienced developers to maintain the likely repulsive codebase it will become an obvious sore. Unrestrained youths have a lot of ideas, but let me assure you that only a small fraction of those should be realized and made available to the general public.
I have, however, had the pleasure of re-building a product from the ground up as an intern. The experience was beneficial to me since there was adequate technical oversight and it was at an established company with developed infrastructure. And the company benefited by getting a decent proof-of-concept out of it. The expectations were set along the lines of ‘do you best’ (as you might for an interview) but there was a plan B were I incapable of delivering a satisfactory rewrite. It was a low-risk scenario for my employer while a massive opportunity for myself.
On the other end of the spectrum is when nothing is expected. While less stressful for the intern, setups with non-existent expectations do little to help either party. The intern has to press for tasks and access to relevant systems. And the employer learns little about the skills of the person they’re considering. When I was in a situation like this I felt sort of disrespected - I thought I was being hired for my skills but it turned out that I was more like a corporate requirement that had to be filled. Please don’t hire interns (or full-time employees for that matter) if you have nothing for them to do.
Aside from opportunity cost, Interns usually don’t have much at risk during less-than-ideal internships since they are often at-will or within a set timeframe (the duration of summer break, for example). The main thing to keep in mind (especially for internships that have no set end date) is that internships are a two-party dance in which you must respect your partner while trying to maximize their use to you. If you meet an ambitious entrepreneur who wants you to be a pivotal part of their team (the Woz to their Jobs, if you will), make sure you are adequately compensated - getting in on the ground floor of a budding startup can seem like (and be) a great opportunity, but that only holds true so long as you aren’t overworked and underpaid. Young people are especially easy to take advantage of since they have a limited amount of experience and internships seem like the best low-risk places to gain these sorts of experiences. Engineers must vigilantly screen anyone we work for to protect ourselves from the overzealous and under-technical.
Some of my most rewarding experiences came from part-time internships throughout the school year - it allowed for a smoothing of the flow of intern-appropriate tasks. As a youth I often imagined that internships were only summer things, but the work I did during the school-year ended up being critical to both my understanding of the coursework as well as my performance in industry. I think being ‘always on’ was a fantastic way to immerse myself in the software engineering field. Part-time positions may also be less work for the employers since they’ll only have to deal with (and pay) and intern 10-25 hours per week.
Thanks go out to the folks who hired me while I was in school - I’ll be sure to follow your example if I’m ever in a position to do so.
0 notes
Text
Zero Values and JSON in Go
Go is great, I think that is apparent. If you have talked to me about software development at all in the past 5 months then you have certainly heard me talk about Go and how pleasing I find it to write.
There are great, baked-in features, like documentation, testing, and (obviously) JSON encoding & decoding of native types. It’s very simple to enable - any exported attribute (a field marked public, if you’re java-kin) of a struct can be encoded by the encoding/json package and will give you the obvious result where all struct elements have identical JSON field names. You have the option to override this default behavior and rename the fields or omit them entirely if they’re empty. So if your user has no middleName then the JSON version of that person will just not have a middleName field. Sound strightforward?
How does encoding/json determine which fields to omit? I can’t say that I have read through their implementation, but it is safe to say that the package omits any field that has the zero-value for its type. That is a 0-length string, the int 0, float 0.0, or false. This works sometimes. If you want to pass back a false or a 0, your JSON representation will simply not have the fields you have set to those values.
tl;dr: make sure there is no case where you want to send a zero-value via JSON in a field marked omitempty
0 notes
Text
ringzer0team challenge 113 writeup
big ups to John Anderson (lampwins) for having the curious mind and php know-how to crush this challenge in a matter of minutes – I was just along for the ride really
this challenge came from ringzer0team.com’s set of web challenges. we have been running through them with the cyber security club for the past few weeks for an upcoming web pen-testing engagement (maybe you’ll be able to read about it here later ;) ).
the scenario was that you’re resetting the password to the admin console of a website (the challenge lives here). they provide the source code (php) for the password resetting mechanism. it can be summed up thusly: use the current time to seed a PRNG, grab a ‘random’ number between 1000000000000000 and 9999999999999999 to use as a password reset token. then the page will accept GETs with a url parameter k which is compared to the previously generated token. if they match then your new password is printed to the screen, otherwise you get nothing. there is also a 1hr expiration for each token.
the biggest hint for this challenge is that the current time is included in the page telling you that your password has been reset:
[spoilers follow]
and we know that that time is used to seen the PRNG. once we convert that to unix time (seconds since 1 Jan 1970, UTC) we have the seed and can replicate the line $token = rand(1000000000000000,9999999999999999); to find the token. then use that at the url parameter k to retrieve our new password, login, and grab the flag. cha-ching.
bonus: php one liner (once you have the timestamp): php -r "srand(1447631726); echo rand(1000000000000000,9999999999999999);"
0 notes
Text
2015 CSAW CTF: two forensics 100s flash & keep calm
these two forensics challenges were especially easy – perhaps I just found skiddie workarounds or something. but, points-wise, they were on the same level as notesy so their ease makes some sense :)
keep calm and ctf
the challenge presented us with an image and told us it was special. steganography was likely a force at play.
above is the way I actually solved this one (with david). highlighted, you can see the flag. this solution was inspired by the photo of yoshi in fuzyll's recon challenge. both of these images contained stegonagraphic data inside of an image. for yoshi, I tried to view the source to look for html comments or some other easy hint like that, but instead I saw this steganographic stuff. nice nice. an easier (and more 1337 way to find this) is to combine xxd and vim into a mythical hexeditor. thanks to my coworker, king, for showing me this recently. basically, open img.jpg with vim and type :%!xxd which, if I am interpreting it correctly, runs xxd on the file (aka %) and writes the results back into the buffer. see below. then just slam :q! to exit without saving the hexdump. or you could, ya'know, just hexdump outside of vim.
flash
the challenge statment for this one was: We were able to grab an image of a harddrive. Find out what's on it. tough. I downloaded the file and ran strings on it to see if there was anything especially juicy. the last printable string in the image turned out to be the flag: that's it. welcome to ctfs. flags just sort of plop out of files like that sometimes.
0 notes
Text
2015 CSAW CTF: crypto writeups
all of the 50-point crypto challenges this year were based on Mr Robot episodes – the ciphertext files were named after episodes while all the flags were quotes from that episode. neat.
eps1.1_ones-and-zer0es_c4368e65e1883044f3917485ec928173.mpeg
we were given the following ciphertext: 011001100110110001100001011101000111101101010000011001010110111101110 000011011000110010100100000011000010110110001110111011000010111100101 110011001000000110110101100001011010110110010100100000011101000110100 001100101001000000110001001100101011100110111010000100000011001010111 100001110000011011000110111101101001011101000111001100101110011111010 010000001001001001001110111011001100101001000000110111001100101011101 100110010101110010001000000110011001101111011101010110111001100100001 000000110100101110100001000000110100001100001011100100110010000100000 011101000110111100100000011010000110000101100011011010110010000001101 101011011110111001101110100001000000111000001100101011011110111000001 101100011001010010111000100000010010010110011000100000011110010110111 101110101001000000110110001101001011100110111010001100101011011100010 000001110100011011110010000001110100011010000110010101101101001011000 010000001110111011000010111010001100011011010000010000001110100011010 000110010101101101001011000010000001110100011010000110010101101001011 100100010000001110110011101010110110001101110011001010111001001100001 011000100110100101101100011010010111010001101001011001010111001100100 000011000010111001001100101001000000110110001101001011010110110010100 100000011000010010000001101110011001010110111101101110001000000111001 101101001011001110110111000100000011100110110001101110010011001010111 011101100101011001000010000001101001011011100111010001101111001000000 111010001101000011001010110100101110010001000000110100001100101011000 01011001000111001100101110
obviously this is supposed to represent some binary data. I googled 'binary to ascii' and pasted in the string. which is kind of funny since it's ascii to ascii, really (or, like, ascii to unicode or something). episode 1.1, easy as pie.
eps1.7_wh1ter0se_2b007cf0ba9881d954e85eb475d0d5e4.m4v
this time we were given ciphertext that looked to be produced by a standard rotation or substitution cipher EOY XF, AY VMU M UKFNY TOY YF UFWHYKAXZ EAZZHN. UFWHYKAXZ ZNMXPHN. UFWHYKAXZ EHMOYACOI. VH'JH EHHX CFTOUHP FX VKMY'U AX CNFXY FC OU. EOY VH KMJHX'Y EHHX IFFQAXZ MY VKMY'U MEFJH OU. me, elaina, sarah, and callum swarmed to the file for some quick frequency analysis. such a short piece of ciphertext could only get us so far. sarah had taken some sort of cryptology course in estonia so she told us to examine the frequencies of n-grams. that also gave us some strong candidate translations. but what ended up being the key, was to simply look at the ciphertext and figure out how it could fit into the english language. we focused on EOY and TOY – EOY has to be a word that can start a sentence or phrase and its last two letters must make sense as the last two letters of another 3-letter word. the same tactic was applied to XF (word 2) and YF (word 8). we attempted to uncover the substitution alphabet one or two characters at a time, then translate the ciphertext with each character in the candidate substitution alphabet lowercased so that we would be able to more easily see which character we still had to uncover. the apostrophes helped a lot – VH'JH was likely we're or we've and each of the single characters following an apostrophe was likely a t, s, or maybe even a d. after applying some of these assumptions, more patterns became apparent and some partially decrypted words had an obvious plaintext value that lead to the discovery of more of the substitution alphabet. here's a glamour shot of the finale to this solve:
eps1.9_zer0-day_b7604a922c8feef666a957933751a074.avi
here we started with some base64 encoded data (could it be that easy?!): RXZpbCBDb3JwLCB3ZSBoYXZlIGRlbGl2ZXJlZCBvbiBvdXIgcHJvbWlzZSBhcyBleHBlY 3RlZC4g\nVGhlIHBlb3BsZSBvZiB0aGUgd29ybGQgd2hvIGhhdmUgYmVlbiBlbnNsYXZl ZCBieSB5b3UgaGF2\nZSBiZWVuIGZyZWVkLiBZb3VyIGZpbmFuY2lhbCBkYXRhIGhhcyB iZWVuIGRlc3Ryb3llZC4gQW55\nIGF0dGVtcHRzIHRvIHNhbHZhZ2UgaXQgd2lsbCBiZS B1dHRlcmx5IGZ1dGlsZS4gRmFjZSBpdDog\neW91IGhhdmUgYmVlbiBvd25lZC4gV2UgY XQgZnNvY2lldHkgd2lsbCBzbWlsZSBhcyB3ZSB3YXRj\naCB5b3UgYW5kIHlvdXIgZGFy ayBzb3VscyBkaWUuIFRoYXQgbWVhbnMgYW55IG1vbmV5IHlvdSBv\nd2UgdGhlc2UgcGl ncyBoYXMgYmVlbiBmb3JnaXZlbiBieSB1cywgeW91ciBmcmllbmRzIGF0IGZz\nb2NpZX R5LiBUaGUgbWFya2V0J3Mgb3BlbmluZyBiZWxsIHRoaXMgbW9ybmluZyB3aWxsIGJlIHR o\nZSBmaW5hbCBkZWF0aCBrbmVsbCBvZiBFdmlsIENvcnAuIFdlIGhvcGUgYXMgYSBuZX cgc29jaWV0\neSByaXNlcyBmcm9tIHRoZSBhc2hlcyB0aGF0IHlvdSB3aWxsIGZvcmdlI GEgYmV0dGVyIHdvcmxk\nLiBBIHdvcmxkIHRoYXQgdmFsdWVzIHRoZSBmcmVlIHBlb3Bs ZSwgYSB3b3JsZCB3aGVyZSBncmVl\nZCBpcyBub3QgZW5jb3VyYWdlZCwgYSB3b3JsZCB 0aGF0IGJlbG9uZ3MgdG8gdXMgYWdhaW4sIGEg\nd29ybGQgY2hhbmdlZCBmb3JldmVyLi BBbmQgd2hpbGUgeW91IGRvIHRoYXQsIHJlbWVtYmVyIHRv\nIHJlcGVhdCB0aGVzZSB3b 3JkczogImZsYWd7V2UgYXJlIGZzb2NpZXR5LCB3ZSBhcmUgZmluYWxs\neSBmcmVlLCB3 ZSBhcmUgZmluYWxseSBhd2FrZSF9Ig==
this one was solved by ethan. if you aren't familiar with base64 encoding, I googled it for you. but essentially, it's a way to encode binary data to printable ascii characters. it's used in http basic authentication. you can put binary data in-line in an html file with this sort of encoding. immeiately I try base64 -D eps1.9_zer0-day_b7604a922c8feef666a957933751a074.avi only to see Invalid character in input stream. I determined that it was the backslash (\) that was invalid. so I removed them all and everything came out screwey when I went to decode it again. since each character represents 5 bits, incorrectly removing a single character from base64 encoded data will misalign the following bits. anyway, ethan later told us that the \ I was removing should have been \n – the standard newline escape sequence. thus: sed 's/\\n//g' eps1.9_zer0-day_b7604a922c8feef666a957933751a074.avi | base64 -D -. a few things are going on in this command. first the sed command contains two backslashes \\ to escape a single backslash so that the pattern matches the \n in the input string. then there are two forward slashes // which is normally where we would put the string to replace \n with, but we're just replacing it with nothing. then the - at the very end, this is to represent stdin ie base64 will decode whatever comes into stdin.
very cool. 150 points in the bag.
notesy
next is a 100-point challenge that unfortunately eschews the Mr Robot theme. the challenge is down now so I missed my opportunity to take a gnarly screen grab (jk it was just a input textbox on a page). anything you put in this textbox would be 'encrypted' by what seemd to be yet another substitution cipher. competitors in the #isislab irc channel were flipping out about this one. I admit to having similar frustrations as them – there seemed to be little direction to the challenge. it was easy to figure out what was going on but not to figure out what the flag should be. later on the CSAW team put up some good hints.
these hints came, word for word, from the irc channel. anyway they lead me to the solution – the substitution alphabet which can simply be recovered by entering in the normal alphabet into the encrytor: abcdefghijklmnopqrstuvwxyz if you're not familiar. once you know how the characters are rearranged you have broken the cryptosystem and can go back-n-forth between plaintext and ciphertext as you please. ps – the youtube link in hint no. 2 goes to nic cage teaches the alphabet since you just had to enter the abc's to solve the challenge.
1 note
·
View note
Text
2015 CSAW CTF: web 200 lawn care writeup
I love lawn care. not that I do any, per se. but the the first challenge I attempted with my team for the college of charleston’s cyber security club, was based on a nice, healthy lawn. overall, it was an easy challenge that took a bit of fiddling up front to find the vulnerability. when you first enter the challenge you are presented with the following:
the most interesting things off the bat are the links to careers in the footer for indications of what technologies are in use here as well as the username & password fields at the top. clicking the green grow button makes grass grow through the magic of javascript. the careers page was mostly jokes, but it did include about three interesting bullet points: javascript, git, and erlang. my first thought was sql injection, but that was wrong. time to tap ctrl-u (command-option-u) and view that source. yes, yes, javascript as they mentioned on the careers page. the first block of js on the page does three things:
function init(){ document.getElementById('login_form').onsubmit = function() { var pass_field = document.getElementById('password'); pass_field.value = CryptoJS.MD5(pass_field.value).toString(CryptoJS.enc.Hex); }; $.ajax('.git/refs/heads/master').done(function(version){$('#version').html('Version: ' + version.substring (0,6))}); initGrass(); }
first, it assigns a handler that hashes (md5) the password when submitted. client-side hashing, as the saying goes.
I’m no js professional, but then I think it fills the element at anchor #version with the first six characters from .git/refs/heads/master
lastly it calls initGrass() to start the game
oh wait. is that a reference to the .git hidden directory? (yes). I traipse over to a local git repo of mine and run tree. an interesting file I see whose existence I can easily verify on the lawncare game is .git/COMMIT_EDITMSG. off to COMMIT_EDITMSG I go.
I think I'll just put mah source code riiiiighhhht here. Perfectly safe place for some source code.
it says
ok well their code is somewhere on here. but how do I get it? is it in /src or something? OH WAIT it’s a dang git repo, that I can probably clone.
git clone http://54.165.252.74:8089/.git
does the trick
in the repo there are 4 files to which I previously did not have access. the rest are js and html. the 4 new ones are __HINT__, premium.php, sign_up.php, & validate_pass.php
I start in sign_up.php and saw an easy sqli vulnerability: $query = "SELECT username FROM users WHERE username LIKE '$user';"; obviously the next logical thing to do is to put a '%' in as my username during the signup process. I do that and get:
so close
then I pop into validate_pass.php to find the juicy vulnerability:
you can see there on line 7 that the hash is being pulled out of some users table and compared to the hash that was passed in from the client. first, it immediately fails if the lengths are not equivalent. but we know that an md5 hash is 16 bytes or 32 hex characters, so that is an odd check. finally it iterates through both hashes it has in order to compare the strings. so when would the length of these two hashes be the same, but the values of the hashes be easily computable or guessable?? ah, when the hashes lengths are both 0! if we pass in a username that is not in the users table, then we can assign an empty string to $hash – take your pick of obscure username. on the client side we also have to pass in an empty string as the password hash. two things ‘prevent’ us from doing this: the field is labelled as required in the html so chrome will not let us submit the login form unless that field is populated or the required label is removed. then we have the javascript that is hashing the password on submit. every input to an md5 hashing function will produce 16 bytes of output regardless of the size of the input, so entering an empty password will not result in an empty hash. we can either delete the javascript from the page or remove the identifier by which it is selecting the password field (ie: getElementById). then we can submit a bogus username and a blank password to capture the flag (curl would also be a quick and easy way around the client-side validation/hashing)
neat-o team
0 notes