Created
January 30, 2014 19:30
-
-
Save mkaufmann/8716922 to your computer and use it in GitHub Desktop.
Stripe-CTF3 Solutions Level -3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Diff for Level0, read file into HashSet: | |
======================================== | |
+require 'set' | |
path = ARGV.length > 0 ? ARGV[0] : '/usr/share/dict/words' | |
-entries = File.read(path).split("\n") | |
+entries = Set.new File.read(path).split("\n") | |
Diff for Level1, replace calculation in bash with inline python: | |
================================================================ | |
parent=$(git rev-parse HEAD) | |
timestamp=$(date +%s) | |
- counter=0 | |
- | |
- while let counter=counter+1; do | |
- echo -n . | |
- | |
- body="tree $tree | |
-parent $parent | |
-author CTF user <me@example.com> $timestamp +0000 | |
-committer CTF user <me@example.com> $timestamp +0000 | |
- | |
-Give me a Gitcoin | |
- | |
-$counter" | |
- | |
- # See http://git-scm.com/book/en/Git-Internals-Git-Objects for | |
- # details on Git objects. | |
- sha1=$(git hash-object -t commit --stdin <<< "$body") | |
- | |
- if [ "$sha1" "<" "$difficulty" ]; then | |
- echo | |
- echo "Mined a Gitcoin with commit: $sha1" | |
- git hash-object -t commit --stdin -w <<< "$body" > /dev/null | |
- git reset --hard "$sha1" > /dev/null | |
- break | |
- fi | |
- done | |
+ body=`python << END | |
+from hashlib import sha1 | |
+digest = "F" | |
+i = 0 | |
+base_body = "tree $tree\n" + "parent $parent\n" + "author CTF user <me@example.com> $timestamp +0000" + "\n" + "committer CTF user <me@example.com> $timestamp +0000" + "\n" + "\n" + "Give me a Gitcoin" + "\n" + "\n" | |
+base_body_len = len(base_body) | |
+while cmp(digest,"$difficulty") > 0: | |
+ i = i + 1 | |
+ str_i = str(i) | |
+ s = sha1() | |
+ s.update("commit %u\0" % (base_body_len+len(str_i)+1)) | |
+ s.update(base_body) | |
+ s.update(str_i) | |
+ s.update("\n") | |
+ digest = s.hexdigest() | |
+print base_body + str(i) | |
+END` | |
+ sha1=$(git hash-object -t commit --stdin <<< "$body") | |
+ echo "Mined a Gitcoin with commit: $sha1" | |
+ git hash-object -t commit --stdin -w <<< "$body" > /dev/null | |
+ git reset --hard "$sha1" > /dev/null | |
} | |
reset() { | |
Diff for Level2, add bot detection with approx histogram: | |
======================================================== | |
package.json: | |
- "seed-random": "*" | |
+ "seed-random": "*", | |
+ "fast-stats": "*" | |
shield: | |
var url = require('url'); | |
+var Stats = require('fast-stats').Stats | |
var RequestData = function (request, response, buffer) { | |
this.request = request; | |
@@ -23,9 +24,36 @@ function rejectRequest(reqData) { | |
reqData.response.end(); | |
} | |
+var BotDet = function() { | |
+ this.banned = false | |
+ this.start_time = new Date().getTime(); | |
+ this.count = 0 | |
+ this.rate = 1 | |
+} | |
+BotDet.prototype.log = function(time, queue) { | |
+ this.count++; | |
+ if(this.count == 3) { | |
+ this.rate = this.count/((time - this.start_time)/1000.0) | |
+ queue.stats.push(this.rate) | |
+ } | |
+} | |
+BotDet.prototype.isBanned = function(queue, ip) { | |
+ if(this.banned) { | |
+ return true | |
+ } | |
+ var percentile = queue.stats.percentile(8) | |
+ if(this.rate > 2*percentile) { | |
+ this.banned = true | |
+ console.log("Banned " + ip) | |
+ return false | |
+ } | |
+} | |
+ | |
var Queue = function (proxies, parameters) { | |
this.proxies = proxies; | |
this.parameters = parameters; | |
+ this.counters = {} | |
+ this.stats = new Stats({ bucket_precision: 50}); | |
}; | |
Queue.prototype.takeRequest = function (reqData) { | |
// Reject traffic as necessary: | |
@@ -34,7 +62,20 @@ Queue.prototype.takeRequest = function (reqData) { | |
// return; | |
// } | |
// Otherwise proxy it through: | |
- this.proxies[0].proxyRequest(reqData.request, reqData.response, reqData.buffer); | |
+ var ip = reqData.request.headers["x-forwarded-for"] | |
+ if(!(ip in this.counters)) { | |
+ this.counters[ip] = new BotDet() | |
+ } | |
+ if(this.counters[ip].banned) { | |
+ rejectRequest(reqData); | |
+ return | |
+ } | |
+ this.counters[ip].inc(new Date().getTime(), this) | |
+ if(this.counters[ip].isBanned(this, ip)) { | |
+ rejectRequest(reqData); | |
+ return; | |
+ } | |
+ this.proxies[Math.floor(Math.random()*this.proxies.length)].proxyRequest(reqData.request, reqData.response, reqData.buffer); | |
}; | |
Queue.prototype.requestFinished = function () { | |
return; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment