Louis-Philippe Véronneau - irchttps://veronneau.org/2021-06-24T00:00:00-04:00Hardening Weechat Relays Against RCE on Bullseye2021-06-24T00:00:00-04:002021-06-24T00:00:00-04:00Louis-Philippe Véronneautag:veronneau.org,2021-06-24:/hardening-weechat-relays-against-rce-on-bullseye.html<p>I've been using <code>weechat</code> to connect to IRC <a href="https://veronneau.org/goodbye-pidginznc-hello-weechatrelay.html">since late 2016</a> and one
of its killer feature is relays. They let use other frontends like the <a href="https://f-droid.org/en/packages/com.ubergeek42.WeechatAndroid/">Weechat
Android app</a> or the amazing <a href="https://github.com/glowing-bear/glowing-bear">Glowing Bear</a> (packaged in
Debian Bullseye by yours truly).</p>
<p>Sadly, relays also used to be somewhat of a …</p><p>I've been using <code>weechat</code> to connect to IRC <a href="https://veronneau.org/goodbye-pidginznc-hello-weechatrelay.html">since late 2016</a> and one
of its killer feature is relays. They let use other frontends like the <a href="https://f-droid.org/en/packages/com.ubergeek42.WeechatAndroid/">Weechat
Android app</a> or the amazing <a href="https://github.com/glowing-bear/glowing-bear">Glowing Bear</a> (packaged in
Debian Bullseye by yours truly).</p>
<p>Sadly, relays also used to be somewhat of a security risk: anyone with access to
a relay<sup id="fnref:phone"><a class="footnote-ref" href="#fn:phone">1</a></sup> could run scripts on the machine running <code>weechat</code> by using
commands such as <code>/exec</code> or <code>/script</code>. Not great.</p>
<p><a href="https://github.com/weechat/weechat/commit/80b980b2af71faa9a2d825c61a5d41d7ace0dc60">Since version 2.5</a> (Buster had version 2.3), you can mitigate this
risk by setting a command allowlist for relays. Later versions <a href="https://github.com/weechat/weechat/commit/dd44c1db16d0ec9359f6403337bbff59f98a389b#diff-34e6cf0f77c92bfba0a773c866cfd4333128eeb31cbe25731f04a0eb89bc48a8R1032-R1038">implemented a
sane default</a> by blocking the following commands:</p>
<ul>
<li><code>/exec</code></li>
<li><code>/fset</code></li>
<li><code>/set</code></li>
<li><code>/unset</code></li>
<li><code>/plugin</code></li>
<li><code>/script</code></li>
<li><code>/python</code></li>
<li><code>/perl</code></li>
<li><code>/ruby</code></li>
<li><code>/lua</code></li>
<li><code>/tcl</code></li>
<li><code>/guile</code></li>
<li><code>/javascript</code></li>
<li><code>/php</code></li>
<li><code>/secure</code></li>
<li><code>/upgrade</code></li>
<li><code>/quit</code></li>
</ul>
<p>Sadly, this default <a href="https://salsa.debian.org/kolter/weechat/-/blob/debian/3.0.1-1/src/plugins/relay/relay-config.c#L1274-1288">didn't make in into Bullseye</a>. If you are
running <code>weechat</code> and are using the relays feature, after upgrading to
Bullseye, I would recommend you run the following commands in the <code>weechat</code>
TUI:</p>
<pre>
/set relay.weechat.commands *,!exec,!fset,!set,!unset,!plugin,!script,!python,!perl,!ruby,!lua,!tcl,!guile,!javascript,!php,!secure,!upgrade,!quit
/save
</pre>
<div class="footnote">
<hr>
<ol>
<li id="fn:phone">
<p>For example, someone steals your phone and connects to IRC via the
Weechat app... <a class="footnote-backref" href="#fnref:phone" title="Jump back to footnote 1 in the text">↩</a></p>
</li>
</ol>
</div>Goodbye Pidgin+ZNC, hello Weechat+relay!2016-10-16T00:00:00-04:002016-10-16T00:00:00-04:00Louis-Philippe Véronneautag:veronneau.org,2016-10-16:/goodbye-pidginznc-hello-weechatrelay.html<p>Recently my neighbor moved and I lost my LAN access to his server. That also
meant I got my own ports 80 & 443 though (we shared internet access).</p>
<p>I use IRC a lot, so one of the first things I did was to move from using his
ZNC bouncer with …</p><p>Recently my neighbor moved and I lost my LAN access to his server. That also
meant I got my own ports 80 & 443 though (we shared internet access).</p>
<p>I use IRC a lot, so one of the first things I did was to move from using his
ZNC bouncer with Pidgin to a more "modern" setup using
<a href="https://weechat.org/">Weechat</a>,
<a href="https://github.com/glowing-bear/glowing-bear">Glowing Bear</a> and the Weechat
<a href="https://github.com/ubergeek42/weechat-android">android app</a>.</p>
<p>I have to say I'm happy with this setup, but there are a few caveats, especially
on the security side:</p>
<ul>
<li>Weechat relays send OTR conversations in plain-text to the client</li>
<li>Having access to Weechat means you can pwn the server, since you can use the
<code>/exec</code> command.</li>
</ul>
<p>I guess I can live with those for now. I don't see a way to fix the OTR problem
other than to have the clients use local OTR keys, and in my opinion, having my
private key on Android is way worse.</p>
<p>As for the <code>/exec</code> command, I could always set up a chroot for Weechat to be
sure it's not able to run anything, but I'm sure it's a lot of trouble since
the relay needs to bind ports, and do other stuff.</p>
<h2>Setting up Weechat</h2>
<p>There's a tons of good guides on how to set Weechat on the internet and I won't
be trying to replace them. I recommand you start with Weechat's <a href="https://www.weechat.org/files/doc/devel/weechat_quickstart.en.html">Quickstart
guide</a>.</p>
<p>The only thing I had a little trouble finding info on was how to set my relay
behind Apache. Yes, Weechat does webserver and TLS, but I trust the Apache
people much more on that side. Crypto is hard.</p>
<p>So yeah, to achieve that I recommend reading <a href="https://weblog.lkiesow.de/20160226-nginx-weechat-relay/">this</a>
and adapt it to Apache using <a href="https://github.com/glowing-bear/glowing-bear/wiki/Proxying-WeeChat-relay-with-a-web-server">that</a>.
The result is a relay opened on a firewalled port so no one can connect to it
directly and Apache proxying to it on port 443. That's even better than a simple
relay configuration, since you can now access your relay everywhere without
bothering with closed ports.</p>
<p>In the end, my Apache VHost looks like this:</p>
<div class="highlight"><pre><span></span><code><span class="nt"><VirtualHost</span><span class="w"> </span><span class="s">*:443</span><span class="nt">></span>
<span class="w"> </span><span class="nb">ServerName</span><span class="w"> </span>foobar.org
<span class="w"> </span><span class="nb">ServerAdmin</span><span class="w"> </span>foo@foobar.org
<span class="w"> </span><span class="nb">ErrorLog</span><span class="w"> </span>${APACHE_LOG_DIR}/error.log
<span class="w"> </span><span class="nb">ProxyPass</span><span class="w"> </span>/<span class="w"> </span>ws://127.0.0.1:$port/
<span class="w"> </span><span class="nb">ProxyPassReverse</span><span class="w"> </span>/<span class="w"> </span>ws://127.0.0.1:$port/
<span class="w"> </span><span class="nb">Header</span><span class="w"> </span>always<span class="w"> </span>set<span class="w"> </span>Strict-Transport-Security<span class="w"> </span><span class="s2">"max-age=15768000; includeSubDomains; preload"</span>
<span class="w"> </span><span class="nb">SSLEngine</span><span class="w"> </span><span class="k">on</span>
<span class="w"> </span><span class="nb">SSLCertificateFile</span><span class="w"> </span><span class="sx">/etc/letsencrypt/live/foobar.org/cert.pem</span>
<span class="w"> </span><span class="nb">SSLCertificateKeyFile</span><span class="w"> </span><span class="sx">/etc/letsencrypt/live/foobar.org/privkey.pem</span>
<span class="w"> </span><span class="nb">SSLCertificateChainFile</span><span class="w"> </span><span class="sx">/etc/letsencrypt/live/foobar.org/chain.pem</span>
<span class="w"> </span><span class="nb">SSLProtocol</span><span class="w"> </span><span class="k">all</span><span class="w"> </span>-SSLv2<span class="w"> </span>-SSLv3<span class="w"> </span>-TLSv1<span class="w"> </span>-TLSv1.1
<span class="w"> </span><span class="nb">SSLCipherSuite</span><span class="w"> </span>ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
<span class="w"> </span><span class="nb">SSLHonorCipherOrder</span><span class="w"> </span><span class="k">on</span>
<span class="w"> </span><span class="nb">SSLCompression</span><span class="w"> </span><span class="k">off</span>
<span class="nt"></VirtualHost></span>
<span class="w"> </span><span class="c"># OCSP Stapling</span>
<span class="w"> </span><span class="nb">SSLUseStapling</span><span class="w"> </span><span class="k">on</span>
<span class="w"> </span><span class="nb">SSLStaplingResponderTimeout</span><span class="w"> </span><span class="m">5</span>
<span class="w"> </span><span class="nb">SSLStaplingReturnResponderErrors</span><span class="w"> </span><span class="k">off</span>
<span class="w"> </span><span class="nb">SSLStaplingCache</span><span class="w"> </span>shmcb:/var/run/ocsp(128000)
</code></pre></div>
<p>With that configuration, you can now connect to Weechat with your clients on
<code>foobar.org</code>, port 443. Make sure you use an SSL Websocket connection!</p>
<h2>Glowing Bear</h2>
<p>Glowing Bear is <strong>awsome</strong> but the code does a few things I did not want, such
as importing bootstrap and fonts from Cloudflare. Lucky for me, it's just a
bunch of JavaScript and HTML, so it's really easy to do local modifications.</p>
<p>I also hardcoded a few things, like the relay hostname and the port my server
is on and a few configurations not to have to redo them manually each time.</p>
<p>One of the things I disliked from the switch from Pidgin to a web client like
Glowing Bear was that IRC is now part of my browser. Sometimes I have trouble
finding my Glowing Bear instance in-between tabs I have opened.</p>
<p>I struggled a lot on this side, but after a few hours of work I got a neat
replacement solution. I'm using:</p>
<ul>
<li>A new Firefox profile just for Glowing Bear</li>
<li>A custom Firefox plugin to change the Firefox icon to the Glowing Bear one</li>
</ul>
<p>This way, I can disable NoScript and save my password on this profile and use
my more secured profile for everything else.</p>
<p>Most of the time I spent on this was used trying to understand how to change
Firefox's icon. I really wanted to use Glowing Bear's icon instead to easily
distinguish my browser from IRC and had never written a Firefox add-on before.</p>
<p>Using <a href="https://addons.mozilla.org/en-US/firefox/addon/profile-win-icons-to-aurora">this</a>
add-on, I was able to boil down a custom add-on using <em>very</em> little files. Only
2 files in fact: a config file and the logo. Here a <code>tree</code> of the add-on:</p>
<pre>
└── glowing-bear-icon@veronneau.org
├── chrome
│ └── icons
│ └── default
│ └── main-window.png
└── install.rdf
</pre>
<p>Here's what the <code>install.rdf</code> file looks like:</p>
<div class="highlight"><pre><span></span><code><span class="cp"><?xml version='1.0' encoding='utf-8'?></span>
<span class="nt"><RDF</span><span class="w"> </span><span class="na">xmlns=</span><span class="s">"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</span><span class="w"> </span><span class="na">xmlns:em=</span><span class="s">"http://www.mozilla.org/2004/em-rdf#"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><Description</span><span class="w"> </span><span class="na">about=</span><span class="s">"urn:mozilla:install-manifest"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><em:id></span>glowing-bear-icon@veronneau.org<span class="nt"></em:id></span>
<span class="w"> </span><span class="nt"><em:version></span>1.1.0<span class="nt"></em:version></span>
<span class="w"> </span><span class="nt"><em:name></span>Glowing<span class="w"> </span>Bear<span class="w"> </span>Icon<span class="nt"></em:name></span>
<span class="w"> </span><span class="nt"><em:description></span>Changes<span class="w"> </span>the<span class="w"> </span>main<span class="w"> </span>icon<span class="w"> </span>for<span class="w"> </span>the<span class="w"> </span>Glowing<span class="w"> </span>Bear<span class="w"> </span>one.<span class="nt"></em:description></span>
<span class="w"> </span><span class="nt"><em:creator></span>pollo<span class="nt"></em:creator></span>
<span class="w"> </span><span class="nt"><em:unpack></span>true<span class="nt"></em:unpack></span>
<span class="w"> </span><span class="nt"><em:type></span>2<span class="nt"></em:type></span>
<span class="w"> </span><span class="nt"><em:multiprocessCompatible></span>true<span class="nt"></em:multiprocessCompatible></span>
<span class="w"> </span><span class="nt"><em:targetApplication></span>
<span class="w"> </span><span class="cm"><!--Firefox--></span>
<span class="w"> </span><span class="nt"><Description></span>
<span class="w"> </span><span class="nt"><em:id></span>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}<span class="nt"></em:id></span>
<span class="w"> </span><span class="nt"><em:minVersion></span>3.0a1<span class="nt"></em:minVersion></span>
<span class="w"> </span><span class="nt"><em:maxVersion></span>*<span class="nt"></em:maxVersion></span>
<span class="w"> </span><span class="nt"></Description></span>
<span class="w"> </span><span class="nt"></em:targetApplication></span>
<span class="w"> </span><span class="nt"></Description></span>
<span class="nt"></RDF></span>
</code></pre></div>
<p>Make sure the <code>id</code> is the same as the main directory of your add-on and then put
the directory in your Firefox profile under
<code>/home/$user/.mozilla/firefox/$profile_name/extensions</code>.</p>
<p>Firefox will bug you about the add-on not being signed:
<a href="https://support.mozilla.org/en-US/kb/add-on-signing-in-firefox#w_override-add-on-signing-advanced-users">disable that feature</a>.
It's OK to do this since you won't be installing any other add-on on this
profile or use it for anything else than IRC.</p>
<p>If you want to be sure to use this profile for Glowing Bear only, one trick is
to set a bogus proxy in Firefox's network settings and whitelist your domain
name in the "No proxy for" box.</p>