<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Privacy on PrivSec - A practical approach to Privacy and Security</title>
  <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/tags/privacy/" />
  <link rel="self" href="https://deploy-preview-444--privsec-dev.netlify.app/tags/privacy/index.xml" />
  <subtitle>Recent content in Privacy on PrivSec - A practical approach to Privacy and Security</subtitle>
  <id>https://deploy-preview-444--privsec-dev.netlify.app/tags/privacy/</id>
  <generator uri="http://gohugo.io" version="0.119.0">Hugo</generator>
  <language>en</language>
  <updated>2024-05-16T00:00:00Z</updated>
  <author>
    <name>PrivSec.dev Team</name>
    
  </author>
  <rights>[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)</rights>
      <entry>
        <title>Using IVPN on Qubes OS</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/qubes/using-ivpn-on-qubes-os/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/qubes/using-ivpn-on-qubes-os/</id>
        <published>2024-05-16T00:00:00Z</published>
        <updated>2025-02-03T08:42:42-07:00</updated>
        <summary type="html">IVPN is a fairly popular and generally trustworthy VPN provider. In this post, I will walk you through how to use the official IVPN client in a ProxyVM on Qubes OS. We will deviate from the official guide by using systemd path to handle DNAT. This will provide the same robustness as their approach to modify /opt/ivpn/etc/firewall.sh, while avoiding the risk that the modifications will be overwritten by a future app update.</summary>
          <content type="html"><![CDATA[<p><img loading="lazy" src="ivpn.png" alt="IVPN"  />
</p>
<p>IVPN is a fairly popular and generally trustworthy VPN provider. In this post, I will walk you through how to use the official IVPN client in a ProxyVM on Qubes OS. We will deviate from the <a href="https://www.ivpn.net/knowledgebase/linux/ivpn-on-qubes-os/">official guide</a> by using systemd path to handle DNAT. This will provide the same robustness as their approach to modify <code>/opt/ivpn/etc/firewall.sh</code>, while avoiding the risk that the modifications will be overwritten by a future app update. We will also be using a TemplateVM for IVPN ProxyVMs instead of using Standalone VMs.</p>
<h2 id="preparing-your-templatevm">Preparing your TemplateVM</h2>
<p>I recommend that you make a new TemplateVM based on the latest Fedora GNOME template and remove all unnecessary packages that you might not use. This way, you can minimize the attack surface while not having to deal with missing dependencies like on a minimal template. With that being said, if you do manage to get the minimal template to fully work with IVPN, feel free to <a href="https://github.com/orgs/PrivSec-dev/discussions">open a discussion on GitHub</a> or <a href="https://tommytran.io/contact">contact me directly</a> and I will update the post accordingly.</p>
<p>I run <a href="https://github.com/TommyTran732/QubesOS-Scripts/blob/main/fedora-gnome/fedora-gnome.sh">this script</a> on my template to trim it down.</p>
<p>Next, you need to create the bind directories for IVPN&rsquo;s configurations:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkdir -p /etc/qubes-bind-dirs.d
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;binds+=( &#39;</span><span class="se">\&#39;</span><span class="s1">&#39;&#39;</span>/etc/opt/ivpn/mutable<span class="s1">&#39;&#39;</span><span class="se">\&#39;</span><span class="s1">&#39; )&#39;</span> <span class="p">|</span> sudo tee /etc/qubes-bind-dirs.d/50_user.conf 
</span></span></code></pre></div><h2 id="installing-the-ivpn-app">Installing the IVPN App</h2>
<p>Inside of the TemplateVM you have just created, do the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo dnf config-manager addrepo --from-repofile<span class="o">=</span>https://repo.ivpn.net/stable/fedora/generic/ivpn.repo
</span></span><span class="line"><span class="cl">sudo dnf install -y ivpn-ui
</span></span></code></pre></div><p>IVPN needs to restart <code>systemd-resolved</code> and run <code>/usr/lib/qubes/qubes-setup-dnat-to-ns</code> every time IVPN modifies <code>/etc/resolv.conf</code>. Create the following files:</p>
<ul>
<li><code>/etc/systemd/system/dnat-to-ns.service</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">Description=Run /usr/lib/qubes/qubes-setup-dnat-to-ns
</span></span><span class="line"><span class="cl">StartLimitIntervalSec=0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Service]
</span></span><span class="line"><span class="cl">Type=oneshot
</span></span><span class="line"><span class="cl">ExecStart=/usr/bin/systemctl restart systemd-resolved
</span></span><span class="line"><span class="cl">ExecStart=/usr/lib/qubes/qubes-setup-dnat-to-ns
</span></span></code></pre></div><ul>
<li><code>/etc/systemd/system/dnat-to-ns.path</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">Description=Run /usr/lib/qubes/qubes-setup-dnat-to-ns when /etc/resolv.conf changes
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Path]
</span></span><span class="line"><span class="cl">PathChanged=/etc/resolv.conf
</span></span><span class="line"><span class="cl">Unit=dnat-to-ns.service
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Install]
</span></span><span class="line"><span class="cl">WantedBy=multi-user.target
</span></span></code></pre></div><ul>
<li><code>/etc/systemd/system/dnat-to-ns-boot.service</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">Description=Run /usr/lib/qubes/qubes-setup-dnat-to-ns
</span></span><span class="line"><span class="cl">After=qubes-network-uplink.service
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Service]
</span></span><span class="line"><span class="cl">Type=oneshot
</span></span><span class="line"><span class="cl">ExecStart=sleep 15
</span></span><span class="line"><span class="cl">ExecStart=/usr/lib/qubes/qubes-setup-dnat-to-ns
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Install]
</span></span><span class="line"><span class="cl">WantedBy=multi-user.target
</span></span></code></pre></div><p>Create <code>/etc/systemd/system/systemd-resolved.conf.d/override.conf</code> to disable rate limiting on systemd-resolved restarting:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">StartLimitIntervalSec=0
</span></span></code></pre></div><p>Next, enable the systemd path and service to run at boot:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> dnat-to-ns.path
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> dnat-to-ns-boot.service
</span></span></code></pre></div><p>Finally, shut down the TemplateVM:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo shutdown now
</span></span></code></pre></div><h2 id="creating-the-proxyvm">Creating the ProxyVM</h2>
<p>Create an AppVM based on the TemplateVM you have just created. Set <code>sys-firewall</code> (or whatever FirewallVM you have connected to your <code>sys-net</code>) as the net qube. If you do not have such FirewallVM, use <code>sys-net</code> as the net qube. Next, go to the advanced tab and tick the <code>provides network access to other qubes</code> box.</p>
<p><img loading="lazy" src="provides-network.png" alt="Provides Network"  />
</p>
<p>Open the IVPN and select <code>Settings</code> → <code>DNS</code> → <code>Force management of DNS using resolv.conf</code>.</p>
<p>Go to the <code>IVPN Firewall</code> section and tick the box <code>Allow LAN traffic when IVPN Firewall is enabled</code>. Due to some strange interaction between qubes services and IVPN, certain apps will get internet connections while others do not if this toggle is not enabled. This option will <strong>not</strong> actually allow AppVMs connected to the ProxyVM to connect to the local network.</p>
<p>Enable <code>Always-on firewall</code> to ensure that the killswitch stays on even when the tunnel is disconnected.</p>
<h2 id="additional-assurances">Additional Assurances</h2>
<p>For additional assurances against VPN leaks, you can optionally add these 2 lines to <code>/rw/config/qubes-firewall-user-script</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nft add rule qubes custom-forward oifname eth0 counter drop
</span></span><span class="line"><span class="cl">nft add rule ip6 qubes custom-forward oifname eth0 counter drop
</span></span></code></pre></div><p>This is not strictly necessary, as I have not observed any leaks with the VPN killswitch provided by the app.</p>
<h2 id="notes">Notes</h2>
<p>With this current setup, the ProxyVM you have just created will be responsible for handling Firewall rules for the qubes behind it. This is not ideal, as this is still a fairly large VM, and there is a risk that IVPN or some other apps may interfere with its firewall handling.</p>
<p>Instead, I highly recommend that you <a href="/posts/qubes/firewalling-with-mirageos-on-qubes-os/">create a minimal Mirage FirewallVM</a> and use it as a firewall <strong>behind</strong> the IVPN ProxyVM. Other AppVMs then should use the Mirage Firewall as the net qube instead. This way, you can make sure that firewall rules are properly enforced.</p>
]]></content>
      </entry>
      <entry>
        <title>Android VPN Leakage with Secondary User Profiles</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/archive/android-vpn-leakage-with-secondary-user-profiles/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/archive/android-vpn-leakage-with-secondary-user-profiles/</id>
        <published>2022-10-10T00:00:00Z</published>
        <updated>2023-02-25T15:05:35-05:00</updated>
        <summary type="html">Update: This is no longer reproducible on Android 13 QPR1 and Android 14 Developer Preview 1.
Before We Start&amp;hellip;
I have been aware of this issue for awhile now (since at least Android 11), though I have not done enough testing to see what actually causes the leak nor do I have any workaround at the moment. My guess is that applications which launch early when you log into a secondary profile can bypass the VPN killswitch.</summary>
          <content type="html"><![CDATA[<p><strong>Update</strong>: This is no longer reproducible on Android 13 QPR1 and Android 14 Developer Preview 1.</p>
<p><strong>Before We Start</strong>&hellip;</p>
<p>I have been aware of this issue for awhile now (since at least Android 11), though I have not done enough testing to see what actually causes the leak nor do I have any workaround at the moment. My guess is that applications which launch early when you log into a secondary profile can bypass the VPN killswitch.</p>
<p>I have reported it on <a href="https://issuetracker.google.com/issues/252851265">Google&rsquo;s issue tracker</a>.</p>
<h2 id="the-leak">The Leak</h2>
<p>You can reproduce the leak by doing the following:</p>
<ol>
<li>Create a new user profile (you need to create a secondary user profile for this, as it is not reproducible on your owner profile or a work profile). Do not log into your Google account at this stage.</li>
<li>Sideload a VPN app. The leak happens with every VPN provider I have tried (since it is likely a platform issue), though if you do not have a VPN subscription I would recommend getting a free one with <a href="https://protonvpn.com">ProtonVPN</a>.</li>
<li>Setup the VPN and the <a href="/posts/os/android-tips/#enable-vpn-killswitch">Android VPN killswitch</a>.</li>
<li>Log into your Google account through Play Services.</li>
<li>Restart the phone. Open the secondary user profile again.</li>
<li>Go to Google&rsquo;s <a href="https://myaccount.google.com/device-activity">My Devices</a> page. Observe that one of the sessions for your phone has your actual location obtained with GeoIP. In some cases, your actual IP address will be shown there as well.</li>
</ol>
<h2 id="notes">Notes</h2>
<ol>
<li>
<p>It is unlikely that this is caused by Play Services being privileged applications. This issue is reproducible on GrapheneOS with the Sandboxed Play Services (which runs as a normal, unprivileged application) as well.</p>
</li>
<li>
<p>More testing is needed to find the root cause of the problem. I do not think that this is Play Services specific. Unfortunately, I do not have access to a router to do a packet capture right now. I would appreciate it if someone can help me get to the bottom of this. You can find my contact information <a href="https://tommytran.io/contact/">here</a>.</p>
</li>
</ol>
]]></content>
      </entry>
      <entry>
        <title>ProtonVPN IP Leakage on Linux and Workaround</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/linux/protonvpn-ip-leakage-on-linux-and-workaround/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/linux/protonvpn-ip-leakage-on-linux-and-workaround/</id>
        <published>2022-10-08T00:00:00Z</published>
        <updated>2022-10-17T05:30:43-04:00</updated>
        <summary type="html">Before We Start&amp;hellip;
I sent Proton an email regarding this issue in late August 2022 and was told they are working on fixing it, though it will take some time as it requires some architectural changes in how the killswitch works.
The Leak Ideally, when implementing a killswitch, a VPN client should drop all connections on non-VPN interfaces except when the connection is to the VPN provider&amp;rsquo;s servers. This is necessary to prevent accidental leaks, at least by unprivileged applications.</summary>
          <content type="html"><![CDATA[<p><strong>Before We Start</strong>&hellip;</p>
<p>I sent Proton an email regarding this issue in late August 2022 and was told they are working on fixing it, though it will take some time as it requires some architectural changes in how the killswitch works.</p>
<h2 id="the-leak">The Leak</h2>
<p>Ideally, when implementing a killswitch, a VPN client should drop all connections on non-VPN interfaces except when the connection is to the VPN provider&rsquo;s servers. This is necessary to prevent accidental leaks, at least by unprivileged applications. Unfortunately, the ProtonVPN client does not currently do this.</p>
<p>Effectively, any application that binds to the connected physical interface (as opposed to the VPN&rsquo;s virtual interface) on your Linux system will expose your actual IP address, regardless of the killswitch state. This is problematic, especially for certain applications like Torrent clients, as they tend to use whatever interfaces they can access (rather than just the default one) to connect to the internet.
You can check this with <code>curl</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl --interface &lt;physical interface&gt; https://ipinfo.io
</span></span></code></pre></div><p>This will return your actual IP address.</p>
<h2 id="the-workaround">The Workaround</h2>
<h3 id="qubes-os">Qubes OS</h3>
<p>On Qubes OS, you generally should not have a problem if you use the ProtonVPN client in a ProxyVM. While the same issue still exists within the ProxyVM itself, it is unlikely to manifest as you should not be running any other applications in the same Qube anyways, and apps in an AppVM cannot bind to the public interface of the ProxyVM. I have not observed any leaks from an AppVM behind a ProtonVPN ProxyVM.</p>
<h3 id="general-linux-distributions">General Linux Distributions</h3>
<p>On a general Linux distribution, the workaround is to configure OpenVPN manually and setup a killswitch yourself.</p>
<p>Since ProtonVPN does not support IPv6, you should disable it in your kernel settings:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;net.ipv6.conf.all.disable_ipv6=1
</span></span></span><span class="line"><span class="cl"><span class="s1">net.ipv6.conf.default.disable_ipv6=1
</span></span></span><span class="line"><span class="cl"><span class="s1">net.ipv6.conf.lo.disable_ipv6=1&#39;</span> <span class="p">|</span> sudo tee /etc/sysctl.d/10-disable-ipv6.conf
</span></span><span class="line"><span class="cl">sudo sysctl -p
</span></span></code></pre></div><p>Next, download your OpenVPN configuration files from <a href="https://account.protonvpn.com/">account.protonvpn.com</a>. In those configuration files, you should see a list of IP addresses and ports of ProtonVPN&rsquo;s servers.</p>
<p>Finally, set up the VPN killswitch. The rules I posted here are based on <a href="https://airvpn.org/forums/topic/15061-firewalld-killswitch/">this discussion</a>.</p>
<h4 id="firewalld">Firewalld</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter FORWARD <span class="m">0</span> -o tun+ -j ACCEPT
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter FORWARD <span class="m">0</span> -i tun+ -j ACCEPT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv6 filter INPUT <span class="m">0</span> -j DROP
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT <span class="m">0</span> -i lo -j ACCEPT
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT <span class="m">1</span> -i tun+ -p tcp -j ACCEPT
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT <span class="m">1</span> -i tun+ -p udp -j ACCEPT
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT <span class="m">999</span> -j DROP
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv6 filter OUTPUT <span class="m">0</span> -j DROP
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT <span class="m">0</span> -o lo -j ACCEPT
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT <span class="m">0</span> -o tun+ -j ACCEPT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#You will need to add each of the IP address and port with the following command:</span>
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT <span class="m">1</span> -p udp -m udp --dport <span class="nv">$PORT</span> -d <span class="nv">$IP</span> -j ACCEPT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo firewall-cmd --direct --permanent --add-rule ipv4 filter OUTPUT <span class="m">999</span> -j DROP
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo firewall-cmd --reload
</span></span></code></pre></div><h4 id="ufw">UFW</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw default deny incoming
</span></span><span class="line"><span class="cl">sudo ufw default deny outgoing
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">#You will need to add each of the IP address and port with the following command:</span>
</span></span><span class="line"><span class="cl">sudo ufw allow out to <span class="nv">$IP</span> port <span class="nv">$PORT</span> proto udp
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo ufw allow out on tun0 from any to any
</span></span></code></pre></div>]]></content>
      </entry>
      <entry>
        <title>NetworkManager Trackability Reduction</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/linux/networkmanager-trackability-reduction/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/linux/networkmanager-trackability-reduction/</id>
        <published>2022-09-04T00:00:00Z</published>
        <updated>2024-06-16T21:40:37-07:00</updated>
        <summary type="html">MAC address randomization Note that Ethernet connections can still be tracked via switch ports, and WiFi connections can be broadly localized by access point.
Furthermore, MAC address spoofing and randomization depends on firmware support from the interface. Most modern network interface cards support the feature.
There are three different aspects of MAC address randomization in NetworkManager, each with their own configuration flag:
WiFi scanning [device] wifi.scan-rand-mac-address=yes WiFi connections [connection] wifi.cloned-mac-address=&amp;lt;mode&amp;gt; Ethernet connections [connection] ethernet.</summary>
          <content type="html"><![CDATA[<h2 id="mac-address-randomization">MAC address randomization</h2>
<p>Note that Ethernet connections can still be tracked via switch ports, and WiFi connections can be broadly localized by access point.</p>
<p>Furthermore, MAC address spoofing and randomization depends on firmware support from the interface. Most modern network interface cards support the feature.</p>
<p>There are three different aspects of MAC address randomization in NetworkManager, each with their own configuration flag:</p>
<h4 id="wifi-scanning">WiFi scanning</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[device]
</span></span><span class="line"><span class="cl">wifi.scan-rand-mac-address=yes
</span></span></code></pre></div><h4 id="wifi-connections">WiFi connections</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[connection]
</span></span><span class="line"><span class="cl">wifi.cloned-mac-address=&lt;mode&gt;
</span></span></code></pre></div><h4 id="ethernet-connections">Ethernet connections</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[connection]
</span></span><span class="line"><span class="cl">ethernet.cloned-mac-address=&lt;mode&gt;
</span></span></code></pre></div><h4 id="mode-options">Mode options</h4>
<p><code>random</code>: Generate a new random MAC address every time a connection is activated</p>
<p><code>stable</code>: Assign each connection a random MAC address that will be maintained across activations</p>
<p><code>preserve</code>: Use the MAC address already assigned to the interface (such as from <code>macchanger</code>), or the permanent address if none is assigned</p>
<p><code>permanent</code>: Use the MAC address permanently baked into the hardware</p>
<h3 id="macrand-default-configuration">Setting a default configuration</h3>
<p>It&rsquo;s best to create a dedicated configuration file, such as <code>/etc/NetworkManager/conf.d/99-random-mac.conf</code>, to ensure package updates do not overwrite the configuration. In general, I recommend the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[device]
</span></span><span class="line"><span class="cl">wifi.scan-rand-mac-address=yes
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[connection]
</span></span><span class="line"><span class="cl">wifi.cloned-mac-address=random
</span></span><span class="line"><span class="cl">ethernet.cloned-mac-address=random
</span></span></code></pre></div><p>This configuration randomizes all MAC addresses by default. These settings can of course be <a href="#per-connection-overrides">overridden on a per-connection basis</a>.</p>
<p>After editing the file, run <code>sudo nmcli general reload conf</code> to apply the new configuration.</p>
<h3 id="per-connection-overrides">Per-connection overrides</h3>
<p>Connection-specific settings take precedence over configuration file defaults. They can be set through <code>nm-connection-editor</code> (&ldquo;Network Connections&rdquo;), a DE-specific network settings GUI, <code>nmtui</code>, or <code>nmcli</code>.</p>
<p>Look for &ldquo;Cloned MAC address&rdquo; under the &ldquo;Wi-Fi&rdquo; or &ldquo;Ethernet&rdquo; section:</p>
<p><img loading="lazy" src="/images/nm-connection-editor.webp" alt="nm-connection-editor screenshot"  />
</p>
<p>In addition to the four mode keywords, you can input an exact MAC address to be used for that connection.</p>
<p>For a home or another trusted network, it can be helpful to use <code>stable</code> or even <code>permanent</code>, as MAC address stability can help avoid being repeatedly served a new IP address and DHCP lease (though not all DHCP servers work this way).</p>
<p>For public networks with captive portals (webpages that must be accessed to gain network access), the <code>stable</code> setting can help prevent redirection back to the captive portal after a brief disconnection or roaming to a different access point.</p>
<h3 id="seeing-the-randomized-mac-address">Seeing the randomized MAC address</h3>
<p>Activate the connection in question, and then look for <code>GENERAL.HWADDR</code> in the output of <code>nmcli device show</code>. This represents the MAC address currently in use by the interface, whether randomized or not. It is also visible as &ldquo;Hardware Address&rdquo; (or similar) in NetworkManager GUIs under active connection details.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ nmcli device show
</span></span><span class="line"><span class="cl">GENERAL.DEVICE:                         enp5s0
</span></span><span class="line"><span class="cl">GENERAL.TYPE:                           ethernet
</span></span><span class="line"><span class="cl">GENERAL.HWADDR:                         XX:XX:XX:XX:XX:XX
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">GENERAL.DEVICE:                         wlp3s0
</span></span><span class="line"><span class="cl">GENERAL.TYPE:                           wifi
</span></span><span class="line"><span class="cl">GENERAL.HWADDR:                         XX:XX:XX:XX:XX:XX
</span></span></code></pre></div><hr>
<h2 id="remove-static-hostname-to-prevent-hostname-broadcast">Remove static hostname to prevent hostname broadcast</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hostnamectl hostname <span class="s2">&#34;localhost&#34;</span>
</span></span></code></pre></div><p>An empty (blank) hostname is also an option, but a static hostname of &ldquo;localhost&rdquo; is less likely to cause breakage. Both will result in no hostname being broadcasted to the DHCP server.</p>
<hr>
<h2 id="disable-sending-hostname-to-dhcp-server">Disable sending hostname to DHCP server</h2>
<p><strong>This configuration will leak your hostname on first connection.</strong> Setting a generic or random hostname is strongly recommended if possible.</p>
<p>Due to <a href="https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/584" title="NetworkManager issue: No way to set dhcp-send-hostname globally">limitations in NetworkManager</a>, it is not possible to reliably disable sending hostnames by default. This setup is very much a hack.</p>
<p>Due to being leaky, this configuration is virtually useless without also <a href="#macrand-default-configuration" title="MAC address randomization — Setting a default configuration">randomizing MAC addresses by default</a>. Your MAC address and hostname will not be correlated starting with the second connection, assuming the first connection used a random MAC address.</p>
<p>Create <code>/etc/NetworkManager/dispatcher.d/no-wait.d/01-no-send-hostname.sh</code> as follows:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="k">$(</span>nmcli -g 802-11-wireless.cloned-mac-address c show <span class="s2">&#34;</span><span class="nv">$CONNECTION_UUID</span><span class="s2">&#34;</span><span class="k">)</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s1">&#39;permanent&#39;</span> <span class="o">]</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>        <span class="o">||</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="k">$(</span>nmcli -g 802-3-ethernet.cloned-mac-address c show <span class="s2">&#34;</span><span class="nv">$CONNECTION_UUID</span><span class="s2">&#34;</span><span class="k">)</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s1">&#39;permanent&#39;</span> <span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="k">then</span>
</span></span><span class="line"><span class="cl">    nmcli connection modify <span class="s2">&#34;</span><span class="nv">$CONNECTION_UUID</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>            ipv4.dhcp-send-hostname <span class="nb">true</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>            ipv6.dhcp-send-hostname <span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">    nmcli connection modify <span class="s2">&#34;</span><span class="nv">$CONNECTION_UUID</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>            ipv4.dhcp-send-hostname <span class="nb">false</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>            ipv6.dhcp-send-hostname <span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div><p>The script must have specific file permissions and a symlink to take effect:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /etc/NetworkManager/dispatcher.d/
</span></span><span class="line"><span class="cl">sudo chown root:root no-wait.d/01-no-send-hostname.sh
</span></span><span class="line"><span class="cl">sudo chmod <span class="m">744</span> no-wait.d/01-no-send-hostname.sh
</span></span><span class="line"><span class="cl">sudo ln -s no-wait.d/01-no-send-hostname.sh ./
</span></span></code></pre></div><p>This script will be automatically triggered on connection events to modify the connection&rsquo;s <code>dhcp-send-hostname</code> settings. If the connection&rsquo;s <em>cloned MAC address</em> is <a href="#per-connection-overrides">explicitly overridden</a> to <code>permanent</code>, the hostname will be sent to the DHCP server on future connections. In all other cases, the hostname will be masked on future connections, so the DHCP server will only see the MAC address.</p>
<h3 id="verifying-proper-operation">Verifying proper operation</h3>
<p>After initiating first connection with a network:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ nmcli c show &lt;connection&gt; <span class="p">|</span> grep dhcp-send-hostname
</span></span><span class="line"><span class="cl">ipv4.dhcp-send-hostname:                no
</span></span><span class="line"><span class="cl">ipv6.dhcp-send-hostname:                no
</span></span></code></pre></div><p><code>&lt;connection&gt;</code> can be the connection name (usually the SSID for WiFi networks) or UUID, obtained from <code>nmcli c show [--active]</code>.</p>
<p><em>Recall that these setting values are set based on the previous connection activation and take effect for the next connection activation.</em></p>
<hr>
<h2 id="sources">Sources</h2>
<ul>
<li><a href="https://wiki.archlinux.org/title/NetworkManager#Configuring_MAC_address_randomization">ArchWiki &mdash; NetworkManager</a></li>
<li><a href="https://www.freedesktop.org/software/systemd/man/hostnamectl">hostnamectl man page</a></li>
<li><a href="https://blogs.gnome.org/thaller/2016/08/26/mac-address-spoofing-in-networkmanager-1-4-0/">MAC Address Spoofing in NetworkManager 1.4.0</a></li>
<li><a href="https://networkmanager.dev/docs/api/latest/NetworkManager.conf.html">NetworkManager.conf man page</a></li>
<li><a href="https://networkmanager.dev/docs/api/latest/NetworkManager-dispatcher.html">NetworkManager-dispatcher man page</a></li>
<li><a href="https://viliampucik.blogspot.com/2016/09/networkmanager-disable-sending-hostname.html">NetworkManager: Disable Sending Hostname to DHCP Server</a></li>
<li><a href="https://networkmanager.dev/docs/api/latest/nmcli.html">nmcli man page</a></li>
</ul>
]]></content>
      </entry>
      <entry>
        <title>Using Mullvad VPN on Qubes OS</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/qubes/using-mullvad-vpn-on-qubes-os/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/qubes/using-mullvad-vpn-on-qubes-os/</id>
        <published>2022-09-03T00:00:00Z</published>
        <updated>2025-02-03T08:42:42-07:00</updated>
        <summary type="html">Mullvad is a fairly popular and generally trustworthy VPN provider. In this post, I will walk you through how to use the official Mullvad client in a ProxyVM on Qubes OS. This method is a lot more convenient than the official guide from Mullvad (which recommends that you manually load in OpenVPN or Wireguard profiles) and will let you seamlessly switch between different location and network setups just as you would on a normal Linux installation.</summary>
          <content type="html"><![CDATA[<p><img loading="lazy" src="mullvad-vpn.png" alt="Mullvad VPN"  />
</p>
<p>Mullvad is a fairly popular and generally trustworthy VPN provider. In this post, I will walk you through how to use the official Mullvad client in a ProxyVM on Qubes OS. This method is a lot more convenient than the <a href="https://mullvad.net/en/help/qubes-os-4-and-mullvad-vpn/">official guide</a> from Mullvad (which recommends that you manually load in OpenVPN or Wireguard profiles) and will let you seamlessly switch between different location and network setups just as you would on a normal Linux installation.</p>
<h2 id="preparing-your-templatevm">Preparing your TemplateVM</h2>
<p>I recommend that you make a new TemplateVM based on the latest Fedora GNOME template and remove all unnecessary packages that you might not use. This way, you can minimize the attack surface while not having to deal with missing dependencies like on a minimal template. With that being said, if you do manage to get the minimal template to fully work with Mullvad, feel free to <a href="https://github.com/orgs/PrivSec-dev/discussions">open a discussion on GitHub</a> or <a href="https://tommytran.io/contact">contact me directly</a> and I will update the post accordingly.</p>
<p>I run <a href="https://github.com/TommyTran732/QubesOS-Scripts/blob/main/fedora-gnome/fedora-gnome.sh">this script</a> on my template to trim it down.</p>
<p>Next, you need to create the bind directories for Mullvad&rsquo;s configurations:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkdir -p /etc/qubes-bind-dirs.d
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;binds+=( &#39;</span><span class="se">\&#39;</span><span class="s1">&#39;&#39;</span>/etc/mullvad-vpn<span class="s1">&#39;&#39;</span><span class="se">\&#39;</span><span class="s1">&#39; )&#39;</span> <span class="p">|</span> sudo tee /etc/qubes-bind-dirs.d/50_user.conf 
</span></span></code></pre></div><h2 id="installing-the-mullvad-app">Installing the Mullvad App</h2>
<p>Inside of the TemplateVM you have just created, do the following:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo dnf config-manager addrepo --from-repofile<span class="o">=</span>https://repository.mullvad.net/rpm/stable/mullvad.repo
</span></span><span class="line"><span class="cl">sudo dnf install -y mullvad-vpn
</span></span></code></pre></div><p>To work around <a href="https://github.com/mullvad/mullvadvpn-app/issues/3803">issue 3803</a>, we will be using systemd path to run <code>/usr/lib/qubes/qubes-setup-dnat-to-ns</code> every time Mullvad modifies <code>/etc/resolv.conf</code>. Create the following files:</p>
<ul>
<li><code>/etc/systemd/system/dnat-to-ns.service</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">Description=Run /usr/lib/qubes/qubes-setup-dnat-to-ns
</span></span><span class="line"><span class="cl">StartLimitIntervalSec=0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Service]
</span></span><span class="line"><span class="cl">Type=oneshot
</span></span><span class="line"><span class="cl">ExecStart=/usr/bin/systemctl restart systemd-resolved
</span></span><span class="line"><span class="cl">ExecStart=/usr/lib/qubes/qubes-setup-dnat-to-ns
</span></span></code></pre></div><ul>
<li><code>/etc/systemd/system/dnat-to-ns.path</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">Description=Run /usr/lib/qubes/qubes-setup-dnat-to-ns when /etc/resolv.conf changes
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Path]
</span></span><span class="line"><span class="cl">PathChanged=/etc/resolv.conf
</span></span><span class="line"><span class="cl">Unit=dnat-to-ns.service
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Install]
</span></span><span class="line"><span class="cl">WantedBy=multi-user.target
</span></span></code></pre></div><p>Create <code>/etc/systemd/system/systemd-resolved.conf.d/override.conf</code> to disable rate limiting on systemd-resolved restarting:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">StartLimitIntervalSec=0
</span></span></code></pre></div><p>Next, enable the systemd path:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> dnat-to-ns.path
</span></span></code></pre></div><p>Finally, shut down the TemplateVM:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo shutdown now
</span></span></code></pre></div><h2 id="creating-the-proxyvm">Creating the ProxyVM</h2>
<p>Create an AppVM based on the TemplateVM you have just created. Set <code>sys-firewall</code> (or whatever FirewallVM you have connected to your <code>sys-net</code>) as the net qube. If you do not have such FirewallVM, use <code>sys-net</code> as the net qube. Next, go to the advanced tab and tick the <code>provides network access to other qubes</code> box.</p>
<p><img loading="lazy" src="provides-network.png" alt="Provides Network"  />
</p>
<p>Open the Mullvad VPN app. Go to <code>Settings</code> → <code>VPN settings</code> and toggle <code>Local network sharing</code>. Due to some strange interaction between qubes services and Mullvad VPN, certain apps will get internet connections while others do not if this toggle is not enabled. This toggle will <strong>not</strong> actually allow AppVMs connected to the ProxyVM to connect to the local network.</p>
<p>Enable <code>Lockdown mode</code> to ensure that the killswitch stays on even when the tunnel is disconnected.</p>
<h2 id="additional-assurances">Additional Assurances</h2>
<p>For additional assurances against VPN leaks, you can optionally add these 2 lines to <code>/rw/config/qubes-firewall-user-script</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nft add rule qubes custom-forward oifname eth0 counter drop
</span></span><span class="line"><span class="cl">nft add rule ip6 qubes custom-forward oifname eth0 counter drop
</span></span></code></pre></div><p>This is not strictly necessary, as I have not observed any leaks with the VPN killswitch provided by the app.</p>
<h2 id="notes">Notes</h2>
<p>With this current setup, the ProxyVM you have just created will be responsible for handling Firewall rules for the qubes behind it. This is not ideal, as this is still a fairly large VM, and there is a risk that Mullvad or some other apps may interfere with its firewall handling.</p>
<p>Instead, I highly recommend that you <a href="/posts/qubes/firewalling-with-mirageos-on-qubes-os/">create a minimal Mirage FirewallVM</a> and use it as a firewall <strong>behind</strong> the Mullvad ProxyVM. Other AppVMs then should use the Mirage Firewall as the net qube instead. This way, you can make sure that firewall rules are properly enforced.</p>
]]></content>
      </entry>
      <entry>
        <title>Desktop Linux Hardening</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/linux/desktop-linux-hardening/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/linux/desktop-linux-hardening/</id>
        <published>2022-08-17T00:00:00Z</published>
        <updated>2025-04-18T17:08:08-04:00</updated>
        <summary type="html">Linux is not a secure desktop operating system. However, there are steps you can take to harden it, reduce its attack surface, and improve its privacy.
Before we start&amp;hellip;
Some of the sections will include mentions of unofficial builds of packages like linux‑hardened, akmod, hardened_malloc, and so on. These are not endorsements &amp;mdash; they are merely to show that you have options to easily obtain and update these packages. Using unofficial builds of packages means adding more parties to trust, and you have to evaluate whether it is worth doing so for the potential privacy/security benefits or not.</summary>
          <content type="html"><![CDATA[<p>Linux is <a href="/posts/linux/linux-insecurities/">not a secure desktop operating system</a>. However, there are steps you can take to harden it, reduce its attack surface, and improve its privacy.</p>
<p><strong>Before we start&hellip;</strong></p>
<p>Some of the sections will include mentions of unofficial builds of packages like linux‑hardened, akmod, hardened_malloc, and so on. These are not endorsements &mdash; they are merely to show that you have options to easily obtain and update these packages. Using unofficial builds of packages means adding more parties to trust, and you have to evaluate whether it is worth doing so for the potential privacy/security benefits or not.</p>
<p><img loading="lazy" src="/images/fedora-tux.png" alt="Fedora Tux"  />
</p>
<h2 id="during-installation">During Installation</h2>
<h3 id="drive-encryption">Drive Encryption</h3>
<p>Most Linux distributions have an option within its installer for enabling LUKS full disk encryption. If this option isn&rsquo;t set at installation time, you will have to backup your data and re-install, as encryption is applied after <a href="https://en.wikipedia.org/wiki/Disk_partitioning">disk partitioning</a> but before <a href="https://en.wikipedia.org/wiki/File_system">filesystem</a> creation.</p>
<p>By default, <code>cryptsetup</code> does not set up authenticated encryption. If you are configuring partitioning using the command line, you can enable integrity with the <code>--integrity</code> argument.</p>
<h3 id="encrypted-swap">Encrypted Swap</h3>
<p>Consider using <a href="https://wiki.archlinux.org/title/Dm-crypt/Swap_encryption">encrypted swap</a> or <a href="https://wiki.archlinux.org/title/Swap#zram-generator">ZRAM</a> instead of unencrypted swap to avoid potential security issues with sensitive data being pushed to <a href="https://en.wikipedia.org/wiki/Memory_paging">swap space</a>. While ZRAM can be set up post-installation, if you want to use encrypted swap, you should set it up while partitioning your drive.</p>
<p>Depending on your distribution, encrypted swap may be automatically set up if you choose to encrypt your drive. Fedora <a href="https://fedoraproject.org/wiki/Changes/SwapOnZRAM">uses ZRAM by default</a>, regardless of whether you enable drive encryption or not.</p>
<h2 id="privacy-tweaks">Privacy Tweaks</h2>
<h3 id="networkmanager-trackability-reduction">NetworkManager Trackability Reduction</h3>
<p>Most desktop Linux distributions including Fedora, openSUSE, Ubuntu, and so on come with <a href="https://en.wikipedia.org/wiki/NetworkManager">NetworkManager</a> by default to configure Ethernet and Wi-Fi settings.</p>
<p>wj25czxj47bu6q has detailed guide on <a href="/posts/linux/networkmanager-trackability-reduction/">trackability reduction with NetworkManager</a> which I highly recommend you check out.</p>
<p>In short, if you use NetworkManager, add the following to your <code>/etc/NetworkManager/conf.d/00-macrandomize.conf</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[device]
</span></span><span class="line"><span class="cl">wifi.scan-rand-mac-address=yes
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[connection]
</span></span><span class="line"><span class="cl">wifi.cloned-mac-address=random
</span></span><span class="line"><span class="cl">ethernet.cloned-mac-address=random
</span></span></code></pre></div><p>Then, restart your NetworkManager service:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl restart NetworkManager
</span></span></code></pre></div><p>Finally, set your hostname to <code>localhost</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo hostnamectl hostname <span class="s2">&#34;localhost&#34;</span>
</span></span></code></pre></div><p>Note that randomizing Wi-Fi MAC addresses depends on support from the Wi-Fi card firmware.</p>
<h3 id="other-identifiers">Other Identifiers</h3>
<p>There are other system identifiers which you may wish to be careful about. You should give this some thought to see if it applies to your <a href="/posts/knowledge/threat-modeling/">threat model</a>:</p>
<dl>
<dt>Username</dt>
<dd>Your username is used in a variety of ways across your system. Consider using generic terms like &ldquo;user&rdquo; rather than your actual name.</dd>
<dt>Machine ID</dt>
<dd>During installation a unique machine ID is generated and stored on your device. Consider <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#machine-id">setting it to a generic ID</a>.</dd>
</dl>
<h4 id="system-counting">System Counting</h4>
<p>Many Linux distributions send some telemetry by default to count how many systems are using their software. Consider disabling this depending on your threat model.</p>
<p>The Fedora Project offers a <a href="https://dnf.readthedocs.io/en/latest/conf_ref.html#countme-label">&ldquo;countme&rdquo; variable</a> to much more accurately <a href="https://fedoraproject.org/wiki/Changes/DNF_Better_Counting">count unique systems accessing its mirrors</a> without involving unique IDs. While currently disabled by default, you could add <code>countme=false</code> to <code>/etc/dnf/dnf.conf</code> in case the default changes in the future. On rpm‑ostree systems such as Fedora Silverblue and Kinoite, the <code>countme</code> option can be disabled by <a href="https://coreos.github.io/rpm-ostree/countme/">masking the rpm-ostree-countme timer</a>.</p>
<p><a href="https://en.opensuse.org/openSUSE:Statistics">openSUSE uses a unique ID to count systems</a>, which can be disabled by emptying the <code>/var/lib/zypp/AnonymousUniqueId</code> file.</p>
<p><a href="https://zorin.com/legal/privacy/#census">Zorin OS also uses a unique ID to count systems.</a> You can opt‑out by running <code>sudo apt purge zorin-os-census</code> and optionally holding the package with <code>sudo apt-mark hold zorin-os-census</code> to avoid accidental reinstallation.</p>
<p><a href="https://snapcraft.io/docs/snap-store-metrics">snapd (Snap) assigns a unique ID to your installation and uses it for telemetry.</a> While this is generally not a problem, if your threat model calls for anonymity, you should avoid using Snap packages and uninstall snapd. Accidental reinstallation on Ubuntu can be prevented with <code>sudo apt-mark hold snapd</code>.</p>
<p><em>Of course, this is a non‑exhaustive list of telemetry on different Linux distributions. If you are aware of other tracking mechanisms used by these or other distributions, feel free to make a <a href="https://github.com/PrivSec-dev/privsec.dev/blob/main/content/posts/linux/Desktop%20Linux%20Hardening.md">pull request</a> or <a href="https://github.com/PrivSec-dev/privsec.dev/discussions">discussion post</a> detailing them!</em></p>
<h3 id="keystroke-anonymization">Keystroke Anonymization</h3>
<p>You could be <a href="https://www.whonix.org/wiki/Keystroke_Deanonymization">fingerprinted based on soft biometric traits</a> when you use the keyboard. The <a href="https://github.com/vmonaco/kloak">Kloak</a> package could help you mitigate this threat. It is available as a .deb package from <a href="https://www.kicksecure.com/wiki/Packages_for_Debian_Hosts">Kicksecure&rsquo;s repository</a> and an <a href="https://aur.archlinux.org/packages/kloak-git">AUR package</a>.</p>
<p>With that being said, if your threat model calls for using something like Kloak, you are probably better off just using Whonix.</p>
<h2 id="application-confinement">Application Confinement</h2>
<p>Some sandboxing solutions for desktop Linux distributions do exist; however, they are not as strict as those found in macOS or ChromeOS. Software installed with distro package managers (DNF, APT, etc.) typically have <strong>no</strong> sandboxing or confinement whatsoever. Several projects which aim to tackle this problem are discussed here.</p>
<h3 id="flatpak">Flatpak</h3>
<div class="youtube-embed-div">
    <iframe src="https://www.youtube-nocookie.com/embed/GkgPIJp8_30" class="youtube-embed-frame" allowfullscreen title="YouTube Video"></iframe>
</div>  
<p><a href="https://flatpak.org">Flatpak</a> aims to be a distribution-agnostic package manager for Linux. One of its main goals is to provide a universal package format which can be used in most Linux distributions. It provides some <a href="https://docs.flatpak.org/en/latest/sandbox-permissions.html">permission control</a>. With that being said, <a href="https://madaidans-insecurities.github.io/linux.html#flatpak">Flatpak sandboxing is quite weak</a>.</p>
<p>You can restrict applications further by setting <a href="https://docs.flatpak.org/en/latest/flatpak-command-reference.html#flatpak-override">Flatpak overrides</a>. This can be done with the command line or by using <a href="https://github.com/tchx84/Flatseal">Flatseal</a>. To deny common dangerous Flatpak permissions globally, run the following commands:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo flatpak override --system --nosocket<span class="o">=</span>x11 --nosocket<span class="o">=</span>fallback-x11 --nosocket<span class="o">=</span>pulseaudio --nosocket<span class="o">=</span>session-bus --nosocket<span class="o">=</span>system-bus --unshare<span class="o">=</span>network --unshare<span class="o">=</span>ipc --nofilesystem<span class="o">=</span>host:reset --nodevice<span class="o">=</span>input --nodevice<span class="o">=</span>shm --nodevice<span class="o">=</span>all --no-talk-name<span class="o">=</span>org.freedesktop.Flatpak --no-talk-name<span class="o">=</span>org.freedesktop.systemd1 --no-talk-name<span class="o">=</span>ca.desrt.dconf --no-talk-name<span class="o">=</span>org.gnome.Shell.Extensions
</span></span><span class="line"><span class="cl">flatpak override --user --nosocket<span class="o">=</span>x11 --nosocket<span class="o">=</span>fallback-x11 --nosocket<span class="o">=</span>pulseaudio --nosocket<span class="o">=</span>session-bus --nosocket<span class="o">=</span>system-bus --unshare<span class="o">=</span>network --unshare<span class="o">=</span>ipc --nofilesystem<span class="o">=</span>host:reset --nodevice<span class="o">=</span>input --nodevice<span class="o">=</span>shm --nodevice<span class="o">=</span>all --no-talk-name<span class="o">=</span>org.freedesktop.Flatpak --no-talk-name<span class="o">=</span>org.freedesktop.systemd1 --no-talk-name<span class="o">=</span>ca.desrt.dconf --no-talk-name<span class="o">=</span>org.gnome.Shell.Extensions
</span></span></code></pre></div><p>To allow Flatseal to function after applying the overrides above, run the following command:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">flatpak --user override com.github.tchx84.Flatseal --filesystem<span class="o">=</span>/var/lib/flatpak/app:ro --filesystem<span class="o">=</span>xdg-data/flatpak/app:ro --filesystem<span class="o">=</span>xdg-data/flatpak/overrides:create
</span></span></code></pre></div><p>Note that this only helps with lax, high‑level default permissions and cannot solve the low‑level issues like <code>/proc</code> and <code>/sys</code> access or an insufficient seccomp blacklist.</p>
<p>Some sensitive permissions of note:</p>
<ul>
<li><code>--share=network</code>: network and internet access</li>
<li><code>--socket=pulseaudio</code>: the PulseAudio socket, grants access to all audio devices (including inputs)</li>
<li><code>--socket=session-bus</code>: access to the entire session bus, which can be used to break out of the sandbox by abusing dangerous D‑Buses.</li>
<li><code>--socket=system-bus</code>: access to the entire system bus, which can be used to break out of the sandbox by abusing dangerous D‑Buses.</li>
<li><code>--device=all</code>: access to all devices (including webcams)</li>
<li><code>--talk-name=org.freedesktop.secrets</code>: D‑Bus access to secrets stored on your keychain</li>
<li><code>--talk-name=org.freedesktop.Flatpak</code>: D‑Bus access to run <code>flatpak run</code>. This D‑Bus is a sandbox escape.</li>
<li><code>talk-name=org.freedesktop.systemd1</code>: D‑Bus access to systemd. This D‑Bus can be used to load in systemd services with arbitary code and run them.</li>
<li><code>--talk-name=ca.desrt.dconf</code>: D‑Bus access to dconf. This D‑Bus can be abused to run arbitary commands by changing key bindings.</li>
<li><code>--talk-name=org.gnome.Shell.Extensions</code>: D‑Bus access to install and manage GNOME shell extensions. This D‑Bus can be abused to add malicious extensions to GNOME.
If an application works natively with Wayland (<em>not</em> running through the <a href="https://wayland.freedesktop.org/xserver.html">XWayland</a> compatibility layer), consider revoking its access to X11 (<code>--nosocket=x11</code>) and the <a href="https://en.wikipedia.org/wiki/Unix_domain_socket">inter‑process communications (IPC)</a> socket (<code>--unshare=ipc</code>) as well.</li>
</ul>
<p>Many Flatpak apps ship with broad filesystem permissions such as <code>--filesystem=home</code> and <code>--filesystem=host</code>. Some applications implement the <a href="https://docs.flatpak.org/en/latest/portal-api-reference.html">Portal API</a>, which allows a file manager to pass files to the Flatpak application (e.g. VLC) without specific filesystem access privileges. Despite this, many of them <a href="https://github.com/flathub/org.videolan.VLC/blob/master/org.videolan.VLC.yaml">still declare <code>--filesystem=host</code></a>.</p>
<p>My strategy to deal with this is to revoke all filesystem access first, then test if an application works without it. If it does, it means the app is already using portals and no further action is needed. If it doesn&rsquo;t, then I start granting permission to specific directories.</p>
<p>As odd as this may sound, <strong>you should not enable (blind) unattended updates of Flatpak packages</strong>. If you or a Flatpak frontend (app store) simply executes <code>flatpak update -y</code>, Flatpaks will be automatically granted any new permissions declared upstream without notifying you. Enabling automatic updates with GNOME Software is fine, as it does not automatically update Flatpaks with permission changes and notifies the user instead.</p>
<h3 id="snap">Snap</h3>
<p>Snap is another distribution-agnostic package manager with some sandboxing support. It is developed by Canonical and heavily promoted in Ubuntu.</p>
<p>Snap packages come in <a href="https://snapcraft.io/docs/snap-confinement">two variants</a>: classic, with no confinement, and strictly confined, where AppArmor and cgroups v1 are used to facilitate sandboxing. If a snap uses classic confinement (&ldquo;classic snap&rdquo;), you are better off installing an equivalent package from your distribution&rsquo;s repository if possible. If your system does not have AppArmor, then you should avoid Snap entirely. Additionally, most modern systems outside of Ubuntu and its derivatives use cgroups v2 by default, so you have to set <code>systemd.unified_cgroup_hierarchy=0</code> in your kernel parameters to get cgroups v1 working.</p>
<p>Snap permissions can be managed via the Snap Store or Ubuntu&rsquo;s custom patched GNOME Control Center.</p>
<p>On Ubuntu, you can replace various .deb packages with strictly confined snaps to minimize the attack surface. Some examples of these packages are the printing stack or <code>ufw</code>:</p>
<p><img loading="lazy" src="/images/ubuntu-cups-snap.png" alt="Cups Snap"  />

<img loading="lazy" src="/images/ubuntu-ufw-snap.png" alt="UFW Snap"  />
</p>
<p>One caveat with Snap packages is that you only have control over the interfaces declared in their manifests. For example, Snap has separate interfaces for <code>audio-playback</code> and <code>audio-record</code>, but some packages will only declare the legacy <code>pulseaudio</code> interface which grants access to both play and record audio. Likewise, some applications may work perfectly fine with Wayland, but the package maintainer may only declare the X11 interface in their manifest. For these cases, you need to reach out to the maintainer of the snap to update the manifest accordingly.</p>
<h3 id="firejail">Firejail</h3>
<div class="youtube-embed-div">
    <iframe src="https://www.youtube-nocookie.com/embed/uUEkHd60Zyo" class="youtube-embed-frame" allowfullscreen title="YouTube Video"></iframe>
</div>  
<p><a href="https://firejail.wordpress.com/">Firejail</a> is another method of sandboxing. As it is a large <a href="https://en.wikipedia.org/wiki/Setuid">setuid</a> binary, it has a large attack surface which increase susceptibility to <a href="https://en.wikipedia.org/wiki/Privilege_escalation">privilege escalation vulnerabilities</a>. <a href="https://madaidans-insecurities.github.io/linux.html#firejail">Madaidan offers additional details on how Firejail can worsen the security of your device.</a></p>
<p>If you do use Firejail, <a href="https://github.com/netblue30/firetools">Firetools</a> can help to quickly manage application permissions and launch sandboxed applications. Note that Firetools configurations are temporary with no option to save profiles for long‑term use.</p>
<p>Firejail can also confine X11 windows using Xpra or Xephr, something that Flatpak and Snap cannot do. I highly recommend checking out <a href="https://firejail.wordpress.com/documentation-2/x11-guide/">their documentation on X11 sandboxing</a>.</p>
<p>One trick to launch applications with their Firejail profile is to use the <code>sudo firecfg</code> command. This will create a symlink <code>/usr/local/bin/app_name_here</code> pointing to Firejail, which will get used automatically by most .desktop files (which do not specify the absolute paths of their binaries) to use will launch the application through the symlink and have Firejail sandbox them this way. Of course, this is bypassable if you or some other applications launch the application directly from <code>/usr/bin/app_name_here</code> instead.</p>
<h3 id="mandatory-access-control">Mandatory Access Control</h3>
<p>Common Linux <a href="https://en.wikipedia.org/wiki/Mandatory_access_control">mandatory access control (MAC)</a> frameworks require policy files in order to force constraints on the system. The two most notable are <a href="https://github.com/SELinuxProject/selinux">SELinux</a> (used on Android and Fedora‑based distributions) and <a href="https://gitlab.com/apparmor/apparmor">AppArmor</a> (used on Debian‑based distributions and most openSUSE variants).</p>
<p>Fedora includes SELinux preconfigured with some policies to confine system daemons (background processes). You should keep it in <em>enforcing</em> mode.</p>
<p>openSUSE gives the choice of SELinux or AppArmor during the installation process. You should stick to the default for each variant (AppArmor for <a href="https://get.opensuse.org/tumbleweed/">Tumbleweed</a> and SELinux for <a href="https://microos.opensuse.org/">MicroOS</a>). openSUSE’s SELinux policies are derived from Fedora.</p>
<p>Arch and its derivatives often do not come with a mandatory access control system, and you must manually install and configure <a href="https://wiki.archlinux.org/title/AppArmor">AppArmor</a>.</p>
<p>Note that, unlike Android, traditional desktop Linux distributions typically do not have full system Mandatory Access Control policies; only a few system daemons are actually confined.</p>
<h3 id="making-your-own-policiesprofiles">Making Your Own Policies/Profiles</h3>
<p>You can make your own AppArmor profiles, SELinux policies, <a href="https://github.com/containers/bubblewrap">bubblewrap</a> profiles, and <a href="https://docs.kernel.org/userspace-api/seccomp_filter.html">seccomp</a> blacklists to have better confinement of applications. This is an advanced and sometimes tedious task, but there are various projects you could use as reference:</p>
<ul>
<li><a href="https://github.com/krathalan/apparmor-profiles">Krathalan’s AppArmor profiles</a></li>
<li><a href="https://github.com/roddhjav/apparmor.d">roddhjav&rsquo;s AppArmor profiles</a></li>
<li><a href="https://github.com/noatsecure/hardhat-selinux-templates">noatsecure’s SELinux templates</a></li>
<li><a href="https://sr.ht/~seirdy/bwrap-scripts">Seirdy’s bubblewrap scripts</a></li>
</ul>
<h3 id="securing-linux-containers">Securing Linux Containers</h3>
<p>If you’re running a server, you may have heard of containers. They are more common in server environments where individual services are built to operate independently. However, you may sometimes see them on desktop systems as well, especially for development purposes.</p>
<p><a href="https://www.docker.com/">Docker</a> is one of the most popular container solutions. It does <strong>not</strong> offer a proper sandbox, meaning there is a large kernel attack surface. You should follow the <a href="/posts/linux/docker-and-oci-hardening/">Docker and OCI Hardening guide</a> to mitigate this problem. In short, there are things you can do like using rootless containers (via configuration changes or <a href="https://podman.io/">Podman</a>), using a runtime which provides a pseudo‑kernel for each container (<a href="https://gvisor.dev/">gVisor</a>), and so on.</p>
<p>Another option is <a href="https://katacontainers.io/">Kata Containers</a> which masquerades virtual machines as containers. Each Kata container has its own kernel and is isolated from the host.</p>
<h2 id="security-hardening">Security Hardening</h2>
<p><img loading="lazy" src="/images/opensuse-computer.jpg" alt="opensuse-computer.jpg"  />
</p>
<h3 id="ubuntu-pro">Ubuntu Pro</h3>
<p>If you are using Ubuntu LTS, consider subscribing to <a href="https://ubuntu.com/pro">Ubuntu Pro</a>. Canonical currently allows up to 5 machines with the free subscription.</p>
<p>You will also gain access to the <a href="https://ubuntu.com/security/livepatch">Canonical Livepatch Service</a>, which provides livepatching for <a href="https://ubuntu.com/security/livepatch/docs/livepatch/reference/kernels">certain kernel variants</a>. Note that the <a href="https://ubuntu.com/kernel/lifecycle">Hardware Enablement (HWE)</a> kernel is not supported.</p>
<p>While livepatching is less than ideal and I still recommend regularly rebooting your computer, it is quite nice to have.</p>
<h3 id="umask-077">Umask 077</h3>
<p>On distributions besides openSUSE, consider changing the default <a href="https://wiki.archlinux.org/title/Umask">umask</a> for both root and regular users to <code>077</code> (symbolically, <code>u=rwx,g=,o=</code>). <em>On openSUSE, a umask of 077 can break snapper and is thus not recommended.</em></p>
<p>On Ubuntu, the &ldquo;Software &amp; Update&rdquo; application will not work properly if the repository lists in <code>/etc/apt/sources.list.d</code> have the 600 permission. You should make sure that they have the 644 permission instead.</p>
<p>The configuration for this varies per distribution, but typically it can be set in <code>/etc/profile</code>, <code>/etc/bashrc</code>, or <code>/etc/login.defs</code>.</p>
<p>Note that, unlike on macOS, this will only change the umask for the shell. Files created by running applications will not have their permissions set to 600.</p>
<h3 id="microcode-updates">Microcode Updates</h3>
<p>You should make sure your system receives microcode updates to get fixes and mitigations for CPU vulnerabilities like <a href="https://meltdownattack.com/">Meltdown and Spectre</a>.</p>
<p>Debian does not ship microcode updates by default, so be sure to <a href="https://wiki.debian.org/SourcesList">enable the non-free repository</a> and install the <code>microcode</code> package.</p>
<p>On Arch Linux, make sure you have the <code>intel-ucode</code> or <code>amd-ucode</code> package installed.</p>
<p>If you are looking to use the <a href="https://guix.gnu.org/en/download/">GNU Guix</a> distribution, you should absolutely use the <a href="https://gitlab.com/nonguix/nonguix">Nonguix channel</a> or similar to get microcode updates.</p>
<p>Avoid the Linux-libre kernel at all costs, as they <a href="https://www.phoronix.com/news/GNU-Linux-Libre-5.13">actively block loading binary‑only microcode</a>.</p>
<h3 id="firmware-updates">Firmware Updates</h3>
<p>Many hardware vendors offer firmware updates to Linux systems through the <a href="https://fwupd.org/">Linux Vendor Firmware Service</a>. You can download and install updates using the following commands:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Update metadata</span>
</span></span><span class="line"><span class="cl">fwupdmgr refresh
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Download and install firmware updates</span>
</span></span><span class="line"><span class="cl">fwupdmgr update
</span></span></code></pre></div><p>Some distributions like Debian do not have fwupd installed by default, so you should check for its existence on your system and install it if needed.</p>
<p>Several graphical frontends integrate with fwupd to offer firmware updates (GNOME Software, KDE Discover, Snap Store, <a href="https://gitlab.gnome.org/World/gnome-firmware">GNOME Firmware</a>, Pop!_OS Settings app). However, not all distributions offer this integration by default, so you should check your specific system and set up scheduled update notifications using <a href="https://wiki.archlinux.org/title/systemd/Timers">systemd timers</a> or <a href="https://wiki.archlinux.org/title/Cron">cron</a> if needed.</p>
<h3 id="firewall">Firewall</h3>
<p>A <a href="https://en.wikipedia.org/wiki/Firewall_(computing)">firewall</a> may be used to secure connections to your system.</p>
<p>Red Hat distributions (such as Fedora) and openSUSE typically use <a href="https://firewalld.org/">firewalld</a>. Red Hat maintains <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/using-and-configuring-firewalld_configuring-and-managing-networking">extensive documentation about firewalld and its graphical frontend firewall-config</a>.</p>
<p>Distributions based on Debian or Ubuntu typically use the <a href="https://wiki.ubuntu.com/UncomplicatedFirewall">Uncomplicated Firewall (ufw)</a>. As the name suggests, it is much less sophisticated than firewalld. One notable missing feature is the ability to apply different firewall rules for different connections (see <em>zones</em> in firewalld).</p>
<p>You could also set your default firewall zone to drop packets. To implement this with firewalld (with the necessary exceptions for IPv6):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">firewall-cmd --set-default-zone=drop
</span></span><span class="line"><span class="cl">firewall-cmd --add-protocol=ipv6-icmp --permanent
</span></span><span class="line"><span class="cl">firewall-cmd --add-service=dhcpv6-client --permanent
</span></span><span class="line"><span class="cl">firewall-cmd --reload
</span></span></code></pre></div><p>On some distributions, it may be possible for applications running as a <code>wheel</code> or <code>sudo</code> user to make firewall changes through polkit. To prevent this, enable firewalld <em>lockdown mode</em> with <code>sudo firewall-cmd --lockdown-on</code>.</p>
<p>These firewalls use the <a href="https://netfilter.org/">netfilter</a> framework and therefore cannot (without the help of strict <a href="#mandatory-access-control">mandatory access control</a>) protect against malicious software running privileged on the system, which can insert their own routing rules that sidestep firewalld/ufw.</p>
<p>There are some per‑binary outbound firewalls such as <a href="https://github.com/evilsocket/opensnitch">OpenSnitch</a> and <a href="https://safing.io/portmaster/">Portmaster</a> that you could use as well. But, just like firewalld and ufw, they are bypassable.</p>
<p>If you are using Flatpak packages, you can <a href="#flatpak">set an override to block network access</a>. This is not bypassable.</p>
<p>If you are using non‑classic Snap packages on a system that <a href="#snap">supports proper confinement (both AppArmor and cgroups v1 present)</a>, you can use the Snap Store to revoke network permission. This is also not bypassable.</p>
<h3 id="kernel-hardening">Kernel Hardening</h3>
<p>There are several things you can do to harden the Linux kernel, including setting appropriate <a href="https://wiki.archlinux.org/title/Kernel_parameters">kernel parameters</a> and blacklisting unnecessary kernel modules. If you are using Kicksecure or Whonix, most of this hardening is included by default. If you are using Debian, you should consider <a href="https://www.kicksecure.com/wiki/Debian">morphing it into Kicksecure</a>.</p>
<p><em>This section extensively references <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html">Madaidan&rsquo;s Linux Hardening Guide</a> and in the interest of brevity does not repeat all the information contained there. You are strongly encouraged to read through the relevant sections of Madaidan&rsquo;s guide (linked for convenience).</em></p>
<h4 id="runtime-kernel-parameters-sysctl">Runtime Kernel Parameters (sysctl)</h4>
<p><em>See <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#sysctl">&ldquo;2.2 Sysctl&rdquo;</a> in Madaidan&rsquo;s guide.</em></p>
<p>Madaidan recommends that you disable <a href="https://github.com/sangam14/CloudNativeLab/blob/master/LXC/Linux%20Containers/User_namespaces.md">unprivileged user namespaces</a> due to the <a href="https://madaidans-insecurities.github.io/linux.html#kernel">significant attack surface for privilege escalation</a>. However, some software such as Podman and LXC relies on unprivileged user namespaces. If you wish to use such software, do not disable <code>kernel.unprivileged_userns_clone</code>. Note that this setting does not exist in the upstream kernel and is added downstream by some distributions.</p>
<p>On distributions other than Whonix and Kicksecure, you can copy the configuration file from <a href="https://github.com/TommyTran732/Linux-Setup-Scripts/blob/main/etc/sysctl.d/99-workstation.conf">Tommy&rsquo;s repository</a>.</p>
<h4 id="boot-parameters">Boot Parameters</h4>
<p><em>See <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#boot-parameters">&ldquo;2.3 Boot parameters&rdquo;</a> in Madaidan&rsquo;s guide. If desired, <a href="https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html">formal documentation of boot parameters</a> is available upstream.</em></p>
<p>Copy these parameters into <a href="https://wiki.archlinux.org/title/Kernel_parameters#Configuration">your bootloader&rsquo;s configuration</a>. On rpm‑ostree distributions, make sure to use <code>rpm-ostree kargs</code> rather than editing GRUB configuration directly.</p>
<h5 id="cpu-mitigations">CPU mitigations</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mitigations=auto,nosmt spectre_v2=on spectre_bhi=on spec_store_bypass_disable=on tsx=off kvm.nx_huge_pages=force nosmt=force l1d_flush=on spec_rstack_overflow=safe-ret gather_data_sampling=force reg_file_data_sampling=on
</span></span></code></pre></div><p><a href="https://en.wikipedia.org/wiki/Simultaneous_multithreading">Simultaneous multithreading (SMT)</a> has been the cause of numerous hardware‑level vulnerabilities and is thus disabled here. If the option is available, you should disable SMT/&ldquo;Hyper‑Threading&rdquo; in your firmware as well.</p>
<p>Note however that disabling SMT may have a significant performance impact &mdash; <a href="https://github.com/anthraxx/linux-hardened/issues/37#issuecomment-619597365">for this reason the popular linux‑hardened kernel for Arch does not disable SMT</a> by default. Assess your own risk tolerance, and, if you choose to keep SMT enabled, simply remove all occurrences of <code>nosmt</code> and <code>nosmt=force</code> from these parameters.</p>
<h5 id="kernel">Kernel</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">slab_nomerge init_on_alloc=1 init_on_free=1 pti=on vsyscall=none ia32_emulation=0 page_alloc.shuffle=1 randomize_kstack_offset=on debugfs=off oops=panic quiet loglevel=0
</span></span></code></pre></div><p>Kicksecure does not enforce either <code>module.sig_enforce=1</code> or <code>lockdown=confidentiality</code> by default as they lead to a lot of hardware compatibility issues; consider enabling these if possible on your system. Additionally, <a href="https://forums.whonix.org/t/kernel-hardening/7296/493"><code>mce=0</code> is no longer recommended</a>.</p>
<h5 id="entropy-generation">Entropy generation</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">random.trust_cpu=off random.trust_bootloader=off
</span></span></code></pre></div><p>Some implementations of the RDRAND instruction (by which the CPU offers a random number generator to the OS) have proven to be <a href="https://en.wikipedia.org/wiki/RDRAND#Security_issues">vulnerable</a> or <a href="https://arstechnica.com/gadgets/2019/10/how-a-months-old-amd-microcode-bug-destroyed-my-weekend/">outright defective</a>. RDRAND is also impossible to audit, being part of the CPU itself.</p>
<p>As a precaution for the integrity of cryptographic operations, the CPU and bootloader should not be used as <em>credited</em> entropy sources. Note that this change will increase boot time.</p>
<p>Further reading:</p>
<ul>
<li><a href="https://systemd.io/RANDOM_SEEDS/">systemd: Random Seeds</a></li>
<li><a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#rdrand">Madaidan: RDRAND</a></li>
<li><a href="https://lore.kernel.org/lkml/20220605171539.417872-1-Jason@zx2c4.com/T/">Linux kernel mailing list</a></li>
<li><a href="https://news.ycombinator.com/item?id=33223232">Hacker News discussion</a></li>
<li><a href="https://github.com/NixOS/nixpkgs/pull/165355">NixOS discussion</a> (also cites many additional sources)</li>
</ul>
<h5 id="dma-mitigations">DMA mitigations</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">intel_iommu=on amd_iommu=force_isolation efi=disable_early_pci_dma iommu=force iommu.passthrough=0 iommu.strict=1
</span></span></code></pre></div><p><a href="https://en.wikipedia.org/wiki/DMA_attack">Direct memory access (DMA) attacks</a> can be mitigated via IOMMU and <a href="#kernel-modules">disabling certain kernel modules</a>. Furthermore, <a href="https://github.com/Kicksecure/security-misc/blob/master/etc/default/grub.d/40_enable_iommu.cfg">strict enforcement of IOMMU TLB invalidation</a> should be applied so devices will never be able to access stale data contents.</p>
<p><a href="https://github.com/PrivSec-dev/privsec.dev/pull/81#issuecomment-1367511126">These parameters <strong>do not provide comprehensive DMA protection</strong>.</a> In early boot (before the kernel has loaded), only the system firmware can enforce IOMMU and thus provide DMA protection. A DMA attack in early boot can patch the kernel in memory to completely undermine these parameters.</p>
<p><em>Note that disabling the busmaster bit on all PCI bridges during very early boot (<code>efi=disable_early_pci_dma</code>) can cause complete boot failure on certain systems with inadequate resources. Therefore, as always, ensure you have a fallback option to boot into the system whenever modifying any kernel parameters.</em></p>
<p>Further reading:</p>
<ul>
<li><a href="https://vfio.blogspot.com/2014/08/iommu-groups-inside-and-out.html">IOMMU Groups, inside and out</a></li>
<li><a href="https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2019/08/04/iommu-introduction">IOMMU introduction</a></li>
<li><a href="https://terenceli.github.io/%E6%8A%80%E6%9C%AF/2019/08/10/iommu-driver-analysis">intel IOMMU driver analysis</a></li>
<li><a href="https://mjg59.dreamwidth.org/54433.html">Avoiding gaps in IOMMU protection at boot</a></li>
<li><a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#dma-attacks">Madaidan: DMA attacks</a></li>
</ul>
<h4 id="kernel-modules">Kernel Modules</h4>
<p><em>See <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#kasr-kernel-modules">&ldquo;2.5.2 Blacklisting kernel modules&rdquo;</a> in Madaidan&rsquo;s guide.</em></p>
<p>On distributions other than Whonix and Kicksecure, you can copy the configuration file from <a href="https://github.com/secureblue/secureblue/blob/live/files/system/etc/modprobe.d/blacklist.conf">secureblue&rsquo;s repository</a> into <code>/etc/modprobe.d/</code>.</p>
<p>There are a few things in this config to keep in mind:</p>
<ul>
<li>Bluetooth is disabled. Comment out the <code>install bluetooth</code> and <code>install btusb</code> lines to use Bluetooth.</li>
<li>Thunderbolt is disabled. Comment out the <code>install thunderbolt</code> line to use Thunderbolt devices.</li>
<li>The <code>cdrom</code> and <code>sr_mod</code> modules are merely <em>blacklisted</em>; they can still be loaded at runtime with <code>modprobe</code>. If you have no intention to ever use CD‑ROM devices, they should be <em>disabled</em> by adding the lines <code>install cdrom /bin/false</code> and <code>install sr_mod /bin/false</code> to the config. (<a href="https://wiki.archlinux.org/title/Kernel_module#Using_files_in_/etc/modprobe.d/_2">More about how this works on the ArchWiki</a>)</li>
<li>Apple filesystems are disabled. While generally fine on non‑Apple systems, if you are using an Apple device you <strong>must</strong> check the filesystem of your EFI partition and comment out the relevant <code>install</code> line, otherwise your Linux install will not boot. For example, comment out the <code>install hfsplus</code> line if your ESP filesystem is HFS+.</li>
</ul>
<h4 id="restricting-access-to-proc-and-sys">Restricting access to /proc and /sys</h4>
<p><em>See <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#hidepid">&ldquo;2.4 hidepid&rdquo;</a> and <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#restricting-sysfs">&ldquo;2.7 Restricting access to sysfs&rdquo;</a> in Madaidan&rsquo;s guide.</em></p>
<p>Disabling access to <code>/sys</code> without a proper whitelist will lead to various applications breaking. Developing such a whitelist will unfortunately be extremely tedious for most users. Kicksecure, and by extension Whonix, has the experimental <a href="https://github.com/Kicksecure/security-misc/blob/master/usr/lib/systemd/system/proc-hidepid.service">proc-hidepid</a> and <a href="https://github.com/Kicksecure/security-misc/blob/master/usr/lib/systemd/system/hide-hardware-info.service">hide-hardware-info</a> services which do just this. From my testing, these work perfectly fine on minimal Kicksecure installations and both Qubes-Whonix-Workstation and Qubes-Whonix-Gateway.</p>
<h4 id="linux-hardened">linux-hardened</h4>
<p>Some distributions like Arch Linux offer the <a href="https://github.com/anthraxx/linux-hardened">linux‑hardened</a> kernel package. It includes <a href="https://wiki.archlinux.org/title/security#Kernel_hardening">hardening patches</a> and more security-conscious defaults.</p>
<p>linux‑hardened disables unprivileged user namespaces (<code>kernel.unprivileged_userns_clone</code>) by default. <a href="#runtime-kernel-parameters-sysctl">This may impact some software.</a></p>
<h4 id="grsecurity">grsecurity</h4>
<p><a href="https://grsecurity.net/">Grsecurity</a> offers a set of kernel patches that attempt to improve security of the Linux kernel. Payment is required, but grsecurity is worth using if you have a subscription.</p>
<h3 id="hardened-memory-allocator">Hardened Memory Allocator</h3>
<p>The <a href="https://github.com/GrapheneOS/hardened_malloc">hardened memory allocator (hardened_malloc)</a> from GrapheneOS can be used on general Linux distributions, though <a href="https://www.kicksecure.com/wiki/Hardened_Malloc">only for some programs</a>.</p>
<p>On Fedora and Red Hat Enterprise Linux, secureblue provides a <a href="https://copr.fedorainfracloud.org/coprs/secureblue/hardened_malloc/">Copr repository</a> with both x86_64 and aarch64 architecture support. Divested Computing Group has a <a href="https://github.com/divestedcg/rpm-hardened_malloc">similar build</a> for Fedora, but with only x86_64 support. Using secureblue&rsquo;s repository is recommended, as the Divested repository is known to <a href="https://grapheneos.social/@Tommy/112274772803550392">block certain IP addresses</a>.</p>
<p>On Arch-based systems, hardened_malloc is <a href="https://wiki.archlinux.org/title/Security#Hardened_malloc">available through the AUR</a>.</p>
<h3 id="disabling-xwayland">Disabling XWayland</h3>
<p>To disable XWayland with GNOME, create <code>/etc/systemd/user/org.gnome.Shell@wayland.service.d/override.conf</code> with the following content:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Service]
</span></span><span class="line"><span class="cl">ExecStart=
</span></span><span class="line"><span class="cl">ExecStart=/usr/bin/gnome-shell --no-x11
</span></span></code></pre></div><h3 id="mountpoint-hardening">Mountpoint Hardening</h3>
<p>Consider adding the <a href="https://man7.org/linux/man-pages/man8/mount.8.html#FILESYSTEM-INDEPENDENT_MOUNT_OPTIONS">mount options</a> <code>nodev</code>, <code>noexec</code>, and <code>nosuid</code> to mountpoints which do not need the respective capabilities. Typically, these can be applied to <code>/boot</code>, <code>/boot/efi</code>, and <code>/var</code>. These flags could also be applied to <code>/home</code> and <code>/root</code>, however <code>noexec</code> will prevent applications that require binary execution in those locations from working (including Flatpak and Snap).</p>
<p>It should be noted that <code>noexec</code> is not foolproof and actually <a href="https://www.chromium.org/chromium-os/developer-library/guides/security/noexec-shell-scripts/#what-about-interpreted-code">quite easy to bypass</a>.</p>
<p>If you use <a href="https://docs.fedoraproject.org/en-US/fedora-silverblue/toolbox/">Toolbox</a>, do not set any of these mount options on <code>/var/log/journal</code>. From my testing, the Toolbox container will fail to start if you have <code>nodev</code>, <code>nosuid</code>, or <code>noexec</code> on said directory. If you are on Arch Linux, you probably do not want to set <code>noexec</code> on <code>/var/tmp</code>, as some AUR packages will then fail to build.</p>
<h3 id="disabling-suid">Disabling SUID</h3>
<p>SUID allows a user to execute an application as the owner of that application, which in many cases is the <code>root</code> user. Vulnerable SUID executables could lead to privilege escalation vulnerabilities.</p>
<p>It is desirable to remove SUID from as many binaries as possible; however, this takes substantial effort and trial and error on the user&rsquo;s part, as some applications require SUID to function.</p>
<p>Kicksecure, and by extension Whonix, has an experimental <a href="https://github.com/Kicksecure/security-misc/blob/master/usr/lib/systemd/system/permission-hardener.service">permission hardening service</a> and <a href="https://github.com/Kicksecure/security-misc/tree/master/etc/permission-hardener.d">application whitelist</a> to automate SUID removal from most binaries and libraries on the system. From my testing, these work perfectly fine on minimal Kicksecure installations and both Qubes-Whonix-Workstation and Qubes-Whonix-Gateway.</p>
<h3 id="dnssec">DNSSEC</h3>
<p>Most Linux distributions do not enable <a href="https://www.icann.org/resources/pages/dnssec-what-is-it-why-important-2019-03-05-en">DNSSEC</a> by default. I recommend that you enable it to make sure that the responses to your DNS queries are authentic. You will need a DNS provider that supports DNSSEC. Ideally, you should use a VPN which provides this feature with its DNS servers so that you can also blend in with other people.</p>
<p>On systems with <code>systemd-resolved</code>, you can edit the <code>/etc/systemd/resolved.conf</code> file and add <code>DNSSEC=yes</code> to enable it. Run <code>systemctl restart systemd-resolved</code> after you are done editing to apply your configuration.</p>
<p>If you are a Whonix or Tails user, you can disregard setting up DNSSEC, as Tor DNS resolution does not support it. Alternatively, you can <a href="https://www.whonix.org/wiki/Alternative_DNS_Resolver">use a non-Tor resolver</a>, though it is not recommended that you do this for an extended amount of time.</p>
<h3 id="time-synchronization">Time Synchronization</h3>
<p>Most Linux distributions by default use the unencrypted and unauthenticated <a href="https://en.wikipedia.org/wiki/Network_Time_Protocol">Network Time Protocol (NTP)</a> for time synchronization. There are two ways to easily solve this problem:</p>
<ul>
<li><a href="https://fedoramagazine.org/secure-ntp-with-nts/">Configure Network Time Security (NTS) with chronyd</a></li>
<li>Use Kicksecure&rsquo;s <a href="https://github.com/Kicksecure/sdwdate">sdwdate</a> on Debian‑based distributions.</li>
</ul>
<p>If you decide on using NTS with chronyd, consider using multiple, independent time providers and setting <a href="https://chrony-project.org/doc/4.4/chrony.conf.html#minsources"><code>minsources</code></a> to a value greater than 1.</p>
<p>GrapheneOS uses a <a href="https://github.com/GrapheneOS/infrastructure/blob/main/etc/chrony.conf">quite nice chrony configuration</a> for their infrastructure. I recommend that you replicate their <code>chrony.conf</code> on your system.</p>
<p>Next, enable the secommp filter for chronyd. On Fedora and Arch Linux, you will need to edit Chrony&rsquo;s environment file in <code>/etc/sysconfig/chronyd</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># Command-line options for chronyd
</span></span><span class="line"><span class="cl">OPTIONS=&#34;-F 1&#34;
</span></span></code></pre></div><p>On Ubuntu and Debian, the environment file is <code>/etc/default/chrony</code>, and the seccomp filter should already be enabled by default.</p>
<p><img loading="lazy" src="/images/nts.png" alt="Verifying NTS configuration"  />
</p>
<h3 id="pluggable-authentication-modules-pam">Pluggable Authentication Modules (PAM)</h3>
<p><a href="https://wiki.archlinux.org/title/PAM">PAM</a>&rsquo;s <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#pam">settings can be hardened</a> to improve authentication security (though keep in mind the bypassable nature of PAM as opposed to encryption).</p>
<p>On Red Hat distributions, you can use <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_authentication_and_authorization_in_rhel/configuring-user-authentication-using-authselect_configuring-authentication-and-authorization-in-rhel">authselect</a> to configure this, e.g.:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo authselect select &lt;profile_id, default: sssd&gt; with-faillock without-nullok with-pamaccess
</span></span></code></pre></div><p>On systems where <code>pam_faillock</code> is not available, consider using <a href="https://www.man7.org/linux/man-pages/man8/pam_tally2.8.html"><code>pam_tally2</code></a> instead.</p>
<p>If you have a YubiKey or another U2F/FIDO2 authenticator, you can use <a href="https://github.com/Yubico/pam-u2f">pam-u2f</a> to implement two‑factor authentication for login. <strong>Make sure to use a hardcoded <code>origin</code> and <code>appid</code> as <a href="https://wiki.archlinux.org/title/Universal_2nd_Factor#Authentication_for_user_sessions">indicated in the ArchWiki</a>. Do not use the default identifier <code>pam://$HOSTNAME</code> which will break if your hostname changes.</strong></p>
<h3 id="storage-media-handling">Storage Media Handling</h3>
<p>Some Linux distributions and desktop environments automatically mount arbitary filesystems upon storage media insertion. This is a security risk, as an adversary can attach a malicious storage device to your computer to exploit vulnerable filesystem drivers.</p>
<p><em>This behavior is disabled by default on Whonix.</em></p>
<h4 id="udisks">UDisks</h4>
<p>GNOME users on systems with UDisks can mitigate this risk by running the following commands:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;[org/gnome/desktop/media-handling]
</span></span></span><span class="line"><span class="cl"><span class="s1">automount=false
</span></span></span><span class="line"><span class="cl"><span class="s1">automount-open=false&#39;</span> <span class="p">|</span> sudo tee /etc/dconf/db/local.d/automount-disable
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;org/gnome/desktop/media-handling/automount
</span></span></span><span class="line"><span class="cl"><span class="s1">org/gnome/desktop/media-handling/automount-open&#39;</span> <span class="p">|</span> sudo tee /etc/dconf/db/local.d/locks/automount-disable
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sudo dconf update
</span></span></code></pre></div><p>This will disable automounting and prevent users from overriding that setting (without privileges).</p>
<p><em>Cinnamon uses the same configuration/commands except with <code>cinnamon</code> substituted in place of <code>gnome</code>. Other desktop environments based on GNOME 3 likely follow a similar pattern &mdash; use <code>gsettings</code> to investigate.</em></p>
<h4 id="autofs">autofs</h4>
<p>On older systems where <code>autofs</code> is used, you should mask the <code>autofs</code> service to disable this behavior.</p>
<h3 id="usb-port-protection">USB Port Protection</h3>
<p>To better protect your USB ports from attacks such as <a href="https://www.srlabs.de/bites/usb-peripherals-turn">BadUSB</a> and the infamous <a href="https://hak5.org/products/usb-rubber-ducky">Hak5 USB Rubber Ducky</a>, I recommend <a href="https://usbguard.github.io">USBGuard</a>. Documentation is available on the <a href="https://usbguard.github.io">USBGuard website</a> and <a href="https://wiki.archlinux.org/title/USBGuard">ArchWiki</a>.</p>
<p>If you are using <a href="#linux-hardened">linux‑hardened</a>, you can alternatively use the <code>deny_new_usb</code> kernel parameter &mdash; see <a href="https://blog.lizzie.io/preventing-usb-attacks-with-linux-hardened.html">&ldquo;Preventing USB Attacks with <code>linux-hardened</code>&rdquo;</a>.</p>
<h2 id="secure-boot">Secure Boot</h2>
<p><a href="https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface#Secure_Boot">Secure Boot</a> can be used to secure the boot process by preventing the loading of unsigned UEFI drivers and bootloaders.</p>
<p>One of the problems with Secure Boot, particularly on Linux, is that <a href="https://wiki.ubuntu.com/UEFI/SecureBoot#How_UEFI_Secure_Boot_works_on_Ubuntu">only the chainloader (shim), bootloader (GRUB), and kernel are verified in a typical setup</a>. The <a href="https://wiki.ubuntu.com/Initramfs#Detailed_Description">initramfs</a> is often left unverified and unencrypted, leaving the door open for an <a href="https://en.wikipedia.org/wiki/Evil_maid_attack">evil maid attack</a>.</p>
<p>The firmware on most devices is also preconfigured to trust Microsoft&rsquo;s keys for both Windows and third‑parties, leading to a <a href="https://github.com/ventoy/Ventoy/issues/135">large attack surface</a>.</p>
<h3 id="enrolling-your-own-keys">Enrolling your own keys</h3>
<hr>
<p><em><strong>Please note that this procedure <a href="https://forums.lenovo.com/t5/Other-Linux-Discussions/Reports-of-custom-secure-boot-keys-bricking-recent-X-P-and-T-series-laptops/m-p/5105571">will brick some non‑compliant UEFI implementations</a>.</strong> You should research your specific computer/motherboard, looking for reported successes and failures alike, before attempting. Ideally, you should be prepared to reprogram the EEPROM to a known‑good state if something goes catastrophically wrong. Integrated &lsquo;BIOS flashback&rsquo; functionality may be an adequate recovery option.</em></p>
<hr>
<p>To eliminate the need to trust the OEM&rsquo;s keys, I recommend using <a href="https://github.com/Foxboron/sbctl">sbctl</a>.</p>
<p>First, you need to boot into your firmware interface and enter Secure Boot setup mode. Then boot back into Linux and <a href="https://github.com/Foxboron/sbctl/blob/master/README.md#key-creation-and-enrollment">follow the instructions</a> to generate and enroll your own keys.</p>
<p>On certain hardware, this will not work. Instead, you will need to export the public key to your EFI partition and manually import it through your firmware interface:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">openssl x509 -in /usr/share/secureboot/keys/db/db.pem -outform DER -out /boot/efi/EFI/fedora/DB.der
</span></span></code></pre></div><h3 id="unified-kernel-image">Unified Kernel Image</h3>
<p>On most desktop Linux systems, it is possible to create a <a href="https://wiki.archlinux.org/title/Unified_kernel_image">unified kernel image</a> (UKI) that contains the kernel, initramfs, and microcode. This unified kernel image can then be signed with the keys created by sbctl.</p>
<p>For Fedora Workstation, you can follow <a href="https://haavard.name/2022/06/22/full-uefi-secure-boot-on-fedora-using-signed-initrd-and-systemd-boot/">Håvard Moen&rsquo;s guide</a> which covers sbctl installation, unified kernel image generation with <a href="https://wiki.archlinux.org/title/Dracut">dracut</a>, and automatic signing with systemd‑boot.</p>
<p>On Arch, the process is very similar, though sbctl is already included in the official repositories and you will need to switch from <a href="https://wiki.archlinux.org/title/Mkinitcpio">mkinitcpio</a> to dracut. Arch with linux‑hardened works well with sbctl, but some level of tedious pacman hooks are required for appropriately timing the re‑signing of all relevant files every time the kernel or bootloader is updated.</p>
<p>Afterwards, you need to use <code>systemd-cryptenoll</code> and pin your encryption key against <a href="https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/">certain PCRs</a> to detect tampering against the firmware. At minimum, you should pin PCR 7 for Secure Boot polices. Personally, I pin PCR 0,1,2,3,5,7, and 14.</p>
<p>Whenever you manually generate a UKI, make sure that the kernel is from the distribution vendor, and that initramfs is freshly generated. Reinstall the kernel package if you have to.</p>
<p>In my opinion, this is the most straightforward setup. However, it does not appear to work well with specialized setups such as Fedora Silverblue/Kinoite. More testing is needed to see if they can be made to work.</p>
<h3 id="notes-on-secure-boot">Notes on Secure Boot</h3>
<p>After setting up Secure Boot, you should password-protect your UEFI settings (sometimes called &lsquo;supervisor&rsquo; or &lsquo;administrator&rsquo; password) as it is good security practice. This does not protect against an attacker with a programmer however - you need to pin PCRs to detect tampering as mentioned above.</p>
<p>These recommendations can make you a little more resistant to evil maid attacks, but they <a href="https://madaidans-insecurities.github.io/guides/linux-hardening.html#verified-boot">do not constitute a proper verified boot process</a> as found on <a href="https://source.android.com/security/verifiedboot">Android</a>, <a href="https://support.google.com/chromebook/answer/3438631">ChromeOS</a>, or <a href="https://docs.microsoft.com/en-us/windows/security/information-protection/secure-the-windows-10-boot-process">Windows</a>.</p>
]]></content>
      </entry>
      <entry>
        <title>Badness Enumeration</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/knowledge/badness-enumeration/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/knowledge/badness-enumeration/</id>
        <published>2022-07-27T00:00:00Z</published>
        <updated>2023-12-10T02:18:15+01:00</updated>
        <summary type="html">Badness enumeration is the concept of making a list of known bad actors and attempting to block them. While it seems intuitive at first glance, badness enumeration should not be relied on for privacy or security. In many cases, it actually does the exact opposite and directly harms the user. This post will attempt to explain why badness enumeration as a concept is flawed and give some examples of its failings in practice.</summary>
          <content type="html"><![CDATA[<p>Badness enumeration is the concept of making a list of known bad actors and attempting to block them. While it seems intuitive at first glance, badness enumeration should not be relied on for privacy or security. In many cases, it actually does the exact opposite and directly harms the user. This post will attempt to explain why badness enumeration as a concept is flawed and give <em>some</em> examples of its failings in practice.</p>
<h2 id="the-obvious-problem">The Obvious Problem</h2>
<p>The obvious argument against badness enumeration is that there are so many threat actors out there, it is impossible to make a list to block all of them. Even when you make a magical list that somehow includes all of the threat actors that exist today, tomorrow a new threat actor will pop up and attack you anyways. Enumerating badness does not systematically solve the underlying problem. Instead, it is running away from the problem and hoping that a competent adversary will not come after you. Badness enumeration does not work, cannot work, has never worked, and will never work.</p>
<h2 id="adblocking-extensions">Adblocking Extensions</h2>
<p>On top of the <a href="#the-obvious-problem">obvious problem</a> mentioned above, there are various technical reasons why advertisement/tracker blocking extensions cannot provide privacy. One of which is the fact that tracking can be done without any scripts at all. For example, a website only needs to know your session ID using a cookie and save all logs associated with that ID. It can then analyze when you visited the website, how long you visited the website for, which page on the website you spent the most time on, what you looked at, and so on. Another problem is that a website can just host its own tracking code or <a href="https://gist.github.com/paivaric/211ca15afd48c5686226f5f747539e8b">proxy third party tracking code under its own domain</a>. Just because your adblocker blocks connections to Google Analytics does not mean that you you are actually &ldquo;safe&rdquo; from Google Analytics at all. Even if you are successful in doing so, there is nothing stopping the website from sharing the analytics data it collected on its own with Google either.</p>
<p>&ldquo;Okay, so adblockers are unreliable, but what is the harm?&rdquo; you may ask.</p>
<p>The problem here is that adblockers (especially with Manifest v2) are highly privileged and have access to all of your data within the browser. All it takes is for the extension developer to turn malicious for your passwords, session ids, TOTP secrets, etc to get compromised. Even if you were to assume that the extension developer is trustworthy, one vulnerability within the extension could still be catastrophic. This is made worse by the fact that adblockers typically use third-party blocklists, extending trust to the blocklist maintainers to not exploit the extension should a vulnerability be found. The <a href="https://portswigger.net/research/ublock-i-exfiltrate-exploiting-ad-blockers-with-css">&ldquo;uBlock, I exfiltrate&rdquo;</a> blog post describes in detail how a CSS injection vulnerability in uBlockOrigin lead to data exfiltration with one single bad filtering rule.</p>
<p>Overall, adblockers increase your attack surface for dubious privacy benefits. If you insist on getting an adblocker however, I highly recommend that you use purely declarative, permission less Manifest V3 ones like <a href="https://chrome.google.com/webstore/detail/ublock-origin-lite/ddkjiahejlhfcafbddmgiahcphecmpfh">uBlock Origin Lite</a>. While they do block fewer ads and trackers than their Manifest V2 counterparts and V3 extensions with &ldquo;Read and change all your data on all websites&rdquo;, they pose much less of a threat to your privacy and security while still providing the convenience of blocking annoyances.</p>
<h2 id="dns-filtering">DNS Filtering</h2>
<p>DNS filtering solutions. while not having any negative impact on security, are trivially bypassable by just hosting the advertisement and trackers under the apex domain instead of a subdomain. For example, instead of hosting advertisement and trackers under ads.example.com, the webmaster can move them to be under example.com/ads and it would be impossible for DNS filters to block. Other bypasses include an application implementing its own DNS resolution instead of relying on the DNS servers set by the operating system, or connecting directly to certain IP addresses without any DNS resolution at all.</p>
<p>It should also be noted that websites can detect which DNS servers a visitor uses. You can look at <a href="https://www.dnsleaktest.com/">DNSLeakTest</a> as an example. Using non-network provided DNS servers adds to the fingerprint and make you more identifiable.</p>
<p>The best way to do DNS filtering is to use a VPN provider which has this feature built in like <a href="https://protonvpn.com">ProtonVPN</a>, <a href="https://mullvad.net">Mullvad</a>, and <a href="https://www.ivpn.net/">IVPN</a> in order to not standout from other users of the same VPN provider. Even then, DNS filtering is purely a convenience feature and cannot be relied on for privacy and security.</p>
<h2 id="antiviruses">Antiviruses</h2>
<p>Antiviruses are highly privileged processes with access to virtually all of your files and data, parsing through them trying to find something that matches a known bad signature. Beyond the fact that you need to trust the Antivirus company to not exfiltrate your sensitive data and that the signature list will never have all of the malware in existence, a vulnerable parser could lead to a system compromise. The <a href="/researches/Abusing-File-Processing-in-Malware-Detectors-for-Fun-and-Profit.pdf">Abusing File Processing in Malware Detectors for Fun and Profit</a> research paper by Suman Jana and Vitaly Shmatikov discusses this in detail.</p>
<p>Here are some other examples of Antiviruses being attack surfaces on their own:</p>
<ul>
<li><a href="https://github.com/taviso/avscript">Arbitrary Code Execution with Avast&rsquo;s Javascript Interpreter</a></li>
<li><a href="https://landave.io/2020/11/bitdefender-upx-unpacking-featuring-ten-memory-corruptions/">Memory Corruption with Bitdefender</a></li>
<li><a href="https://web.archive.org/web/20210729054039/https://palant.info/2019/08/19/kaspersky-in-the-middle-what-could-possibly-go-wrong/">Kaspersky in the Middle</a></li>
</ul>
<p>The proper way to deal with untrusted applications is not to scan them with an Antivirus, but to confine them in such a way that even if they were malicious, they cannot do much damage at all. This has already been achieved on secure mobile operating systems like Android and iOS with their application sandbox. Typically, attacks against these systems require an exploit chain against the operating system, or for the user to actually mess up and grant an app access to sensitive data. On desktop operating systems, you should utilize virtualization to contain untrusted applications in their own virtual machine. This can be done with a system like Qubes OS, the <a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-sandbox/windows-sandbox-overview">Windows Sandbox</a>, or just general KVM / HyperV virtual machines.</p>
<h2 id="default-permit">Default Permit</h2>
<p>Surprisingly (or unsurprisingly), the <a href="https://www.ranum.com/security/computer_security/editorials/dumb/">The Six Dumbest Ideas in Computer Security</a> article from almost 20 years ago still holds true today. It explains the problem with Default Permit better than I ever could. In short, when setting up a Firewall or some sort of filter list, it is better to start out by blocking everything, then allowing only the traffic that you need. That way, you don&rsquo;t have to worry about applications that you didn&rsquo;t care enough to block turning out to be vulnerable. Sometimes, &ldquo;goodness enumeration&rdquo; is the solution to the problem.</p>
<h2 id="conclusion">Conclusion</h2>
<p>By now, I hope I have clearly explained why badness enumeration is never the solution to the problem. Sometimes, it can be a nice-to-have thing, like a VPN provider blocking advertisements and trackers on the DNS level to make the web experience more enjoyable. Other times, it can be harmful to your privacy and security, like with a malicious/vulnerable extension or antivirus. The important thing to keep in mind is that you cannot rely on badness enumeration for true privacy and security, and you should always be aware of the privacy and security implications that certain options may entail.</p>
]]></content>
      </entry>
      <entry>
        <title>Using Lokinet on Qubes OS</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/qubes/using-lokinet-on-qubes-os/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/qubes/using-lokinet-on-qubes-os/</id>
        <published>2022-07-27T00:00:00Z</published>
        <updated>2025-02-03T08:42:42-07:00</updated>
        <summary type="html">Lokinet is an Internet overlay network utilizing onion routing to provide anonymity for its users, similar to Tor network. This post will go over how to set it up on Qubes OS.
Before we start&amp;hellip;
This post should not be considered an endorsement of Lokinet in any shape or form. Lokinet is currently not in a good state &amp;mdash; it has not had a public release since 2022, and most free public exit nodes have gone offline.</summary>
          <content type="html"><![CDATA[<p><img loading="lazy" src="lokinet.png" alt="Lokinet"  />
</p>
<p><a href="https://lokinet.org">Lokinet</a> is an Internet overlay network utilizing onion routing to provide anonymity for its users, similar to Tor network. This post will go over how to set it up on Qubes OS.</p>
<p><strong>Before we start&hellip;</strong></p>
<p>This post should not be considered an endorsement of Lokinet in any shape or form. Lokinet is currently not in a good state &mdash; it has not had a public release since 2022, and most free public exit nodes have gone offline. According to the developers, they are doing major rewrites of the code, and it should not be used in production at the moment.</p>
<h2 id="creating-the-templatevm">Creating the TemplateVM</h2>
<p>Currently, the Lokinet client seems to work well with only Debian-based distributions. This means that our template will have to be one of the Debian-based ones. Personally, I use <a href="https://github.com/TommyTran732/QubesOS-Scripts/blob/main/debian-gnome/debian-gnome.sh">this script</a> to trim down the Debian GNOME template and convert it to Kicksecure. Kicksecure reduces the attack surface of Debian with a substantial set of hardening configurations, and a nice feature to go with an anonymity network like Lokinet is <a href="https://www.kicksecure.com/wiki/Boot_Clock_Randomization">Boot Clock Randomization</a> which helps defend against <a href="https://www.whonix.org/wiki/Time_Attacks">time-based denonymization attacks</a>.</p>
<p>Start by creating the bind directories for Lokinet&rsquo;s configurations:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo mkdir -p /etc/qubes-bind-dirs.d
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;binds+=( &#39;</span><span class="se">\&#39;</span><span class="s1">&#39;&#39;</span>/etc/loki<span class="s1">&#39;&#39;</span><span class="se">\&#39;</span><span class="s1">&#39; )&#39;</span> <span class="p">|</span> sudo tee /etc/qubes-bind-dirs.d/50_user.conf 
</span></span></code></pre></div><p>Next, add the Oxen PGP key and the Lokinet template. We will deviate from the <a href="https://github.com/oxen-io/lokinet/blob/dev/docs/install.md#linux-install">official documentation</a> and pin the PGP key to only be used for this repository:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl --proxy http://127.0.0.1:8082 https://deb.oxen.io/pub.gpg <span class="p">|</span> sudo tee /usr/share/keyrings/oxen.gpg
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;deb [signed-by=/usr/share/keyrings/oxen.gpg] https://deb.oxen.io </span><span class="k">$(</span>lsb_release -sc<span class="k">)</span><span class="s2"> main&#34;</span> <span class="p">|</span> sudo tee /etc/apt/sources.list.d/oxen.list
</span></span></code></pre></div><p>Next, <code>lokinet</code> and <code>resolvconf</code>. <code>lokinet-gui</code> was very buggy when I tested it inside my VM, so I recommend installing only the daemon. <code>resolvconf</code> is used by the Lokinet init script but is not declared as a dependency for some reason, so you have to manually install it as well:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update
</span></span><span class="line"><span class="cl">sudo apt install lokinet-gui resolvconf
</span></span></code></pre></div><p>To work around the problem where Qubes overrides the DNS configuration at boot, create <code>/etc/systemd/system/lokinet-dns-fix.service</code> with the following content:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[Unit]
</span></span><span class="line"><span class="cl">Description=Fix DNS for Lokinet
</span></span><span class="line"><span class="cl">After=qubes-network-uplink.service
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Service]
</span></span><span class="line"><span class="cl">Type=oneshot
</span></span><span class="line"><span class="cl">ExecStart=/usr/bin/rm /etc/resolv.conf
</span></span><span class="line"><span class="cl">ExecStart=/usr/bin/ln -s /run/resolvconf/resolv.conf /etc/resolv.conf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">[Install]
</span></span><span class="line"><span class="cl">WantedBy=multi-user.target
</span></span></code></pre></div><p>Enable the <code>lokinet-dns-fix</code> service:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> lokinet-dns-fix
</span></span></code></pre></div><p>At this stage, you can install any .deb app you want to use with Lokinet in the TemplateVM. I have been unable to get DNS working properly with Lokinet as a network VM, so for now we will have to use a Lokinet in each individual AppVM.</p>
<p>Finally, shut down the TemplateVM:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo shutdown now
</span></span></code></pre></div><h2 id="creating-the-appvm">Creating the AppVM</h2>
<p>Create an AppVM based on the TemplateVM you have just created. Set <code>sys-firewall</code> (or whatever FirewallVM you have connected to your <code>sys-net</code>) as the net qube. If you do not have such FirewallVM, use <code>sys-net</code> as the net qube.</p>
<p>Edit <code>/etc/loki/lokinet.ini</code> and add the exit node you want to use. At the moment, the only free exit node that I am aware of is <code>euroexit.loki</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">[network]
</span></span><span class="line"><span class="cl">exit-node=euroexit.loki
</span></span></code></pre></div>]]></content>
      </entry>
      <entry>
        <title>Android Tips</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/android/android-tips/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/android/android-tips/</id>
        <published>2022-07-22T00:00:00Z</published>
        <updated>2025-02-02T08:50:02-07:00</updated>
        <summary type="html">Android is a very secure and robust operating system out of the box. This post will be less of a &amp;ldquo;hardening guide&amp;rdquo;, but more of a non-exhaustive list of tips when it comes to buying and using Android phones.
Android Devices Recommended Phones Google Pixel phones are the only devices I would recommend for purchase. Pixel phones have stronger hardware security than any other Android devices currently on the market, due to proper AVB support for third-party operating systems and Google&amp;rsquo;s custom Titan security chips acting as the Secure Element.</summary>
          <content type="html"><![CDATA[<p>Android is a very secure and robust operating system out of the box. This post will be less of a &ldquo;hardening guide&rdquo;, but more of a non-exhaustive list of tips when it comes to buying and using Android phones.</p>
<h2 id="android-devices">Android Devices</h2>
<h3 id="recommended-phones">Recommended Phones</h3>
<p><img loading="lazy" src="/images/google-store.png" alt="Google Store"  />
</p>
<p>Google Pixel phones are the <strong>only</strong> devices I would recommend for purchase. Pixel phones have stronger hardware security than any other Android devices currently on the market, due to proper AVB support for third-party operating systems and Google&rsquo;s custom <a href="https://security.googleblog.com/2021/10/pixel-6-setting-new-standard-for-mobile.html">Titan</a> security chips acting as the Secure Element.</p>
<p>When purchasing a device, you should buy one as new as possible. The software and firmware of mobile devices are only supported for a limited time, so buying new extends that lifespan as much as possible. Also, beginning with the <strong>Pixel 8</strong> and <strong>8 Pro</strong>, Pixel devices receive a minimum of 7 years of guaranteed security updates, ensuring a much longer lifespan compared to the 2-4 years competing OEMs typically offer.</p>
<h3 id="phones-to-avoid">Phones to Avoid</h3>
<p>Avoid buying the Fairphone 4, which only has just over 2 years of full security updates since its release date despite them advertising 6 years of support. This is because the System on a Chip they use (Snapdragon 750G) only has 3 years of support from Qualcomm, and the SoC was already old when the phone came out. This is not to mention, the Fairphone 4 <a href="https://forum.fairphone.com/t/bootloader-avb-keys-used-in-roms-for-fairphone-3-4/83448/11">uses the Android Verified Boot Test Key as their OEM keys</a>, effectively making Verified Boot useless. In general, you should check for how long the SoC a phone uses is supported for and not blindly trust the phone manufacturer&rsquo;s claims.</p>
<p>You should also avoid buying phones preloaded with /e/ OS (sometimes branded as the Murena phones). /e/ OS in itself is extremely insecure, engaging in security bad practices that include, but are not limited to, not supporting verified boot; shipping userdebug build; <a href="https://divestos.org/misc/e.txt">shipping months-old version of Chromium; and bundling years-old version of Orbot into their operating system, then marketing it as &ldquo;Advanced Privacy&rdquo;</a>. There was also a recent incident where their cloud service mishandled session keys and gave users access to other&rsquo;s files, then proceeded to <a href="https://community.e.foundation/t/service-announcement-26-may/41252/30">mislead users that the server cannot see their files</a>, despite there being no end-to-end encryption.</p>
<p>You should also be very wary of low quality privacy branded phones like the Freedom Phone, BraX2 Phone, Volta Phone, and the like. These are cheap Chinese phones with the <a href="https://i.mediatek.com/p60">Mediatek Helio P60</a> from 2018, which has already reached or is near end-of-life. Needless to say, you should also avoid any vendor who claims they are Zero-day proof like this:</p>
<p><img loading="lazy" src="/images/volta-phone.png" alt="Volta phone"  />
</p>
<h2 id="android-based-operating-systems">Android-based Operating Systems</h2>
<p><img loading="lazy" src="/images/grapheneos-aurora.jpg" alt="GrapheneOS Aurora"  />
</p>
<p>In certain cases, installing a custom Android-based operating system can help increase your privacy and security. This is rather tricky, however, as the vast majority of these operating systems (a.k.a. &ldquo;custom ROMs&rdquo;) do exactly the opposite: break the Android security model, thereby ruining your security while providing no or dubious privacy benefits.</p>
<p>I have written a detailed post on selecting your Android-based operating system, which you can find <a href="/posts/android/choosing-your-android-based-operating-system">here</a>.</p>
<p><strong>TLDR</strong>: If you are using a modern Pixel, install <a href="https://grapheneos.org">GrapheneOS</a>. Otherwise, stick to your stock operating system. Do not blindly use an OS just because it is advertised as &ldquo;degoogled&rdquo;.</p>
<h2 id="use-new-android-versions">Use New Android Versions</h2>
<p>It&rsquo;s important to not use an <a href="https://endoflife.date/android">end-of-life</a> version of Android. Newer versions of Android receive not only security updates for the operating system but also important privacy enhancing updates too. For example, <a href="https://developer.android.com/about/versions/10/privacy/changes">prior to Android 10</a>, any apps with the <a href="https://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE"><code>READ_PHONE_STATE</code></a> permission could access sensitive and unique serial numbers of your phone such as <a href="https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity">IMEI</a>, <a href="https://en.wikipedia.org/wiki/Mobile_equipment_identifier">MEID</a>, your SIM card&rsquo;s <a href="https://en.wikipedia.org/wiki/International_mobile_subscriber_identity">IMSI</a>, whereas now they must be system apps to do so. System apps are only provided by the OEM or Android distribution.</p>
<h2 id="do-not-root-your-phone">Do Not Root Your Phone</h2>
<p><a href="https://en.wikipedia.org/wiki/Rooting_(Android)">Rooting</a> Android phones can decrease security significantly as it weakens the complete <a href="https://en.wikipedia.org/wiki/Android_(operating_system)#Security_and_privacy">Android security model</a>. This can decrease privacy should there be an exploit that is assisted by the decreased security. Common rooting methods involve directly tampering with the boot partition, making it impossible to perform successful Verified Boot. Apps that require root will also modify the system partition meaning that Verified Boot would have to remain disabled. Having root exposed directly in the user interface also increases the <a href="https://en.wikipedia.org/wiki/Attack_surface">attack surface</a> of your device and may assist in <a href="https://en.wikipedia.org/wiki/Privilege_escalation">privilege escalation</a> vulnerabilities and SELinux policy bypasses.</p>
<h2 id="use-a-diceware-passphrase-avoid-pattern-unlock">Use a diceware passphrase, avoid pattern unlock</h2>
<p>On Android, the phone unlock (Password, Pin, Pattern) is used to protect the encryption key for your device. Thus, it is vital that your unlock secret is secure and can withstand Bruteforce attacks.</p>
<p>Pattern unlock is extremely insecure and should be avoided at all costs. This is discussed in detail in the <a href="/researches/Cracking-Android-Pattern-Lock-in-Five-Attempts.pdf">Cracking Android Pattern Lock in Five Attempts</a> research paper.</p>
<p>If you trust the hardware enforced rate limiting features (typically done by the <a href="https://en.wikipedia.org/wiki/Secure_cryptoprocessor">Secure Element</a> or <a href="https://en.wikipedia.org/wiki/Trusted_execution_environment">Trusted Execution Environment</a>) of your device, a 8+ digit PIN may be sufficient.</p>
<p>Ideally, you should use a randomly generated passphrase of 8 words or longer to secure your phone. These are practically impossible to bruteforce with current technology, regardless of the efficacy of any ratelimiting that may be present.</p>
<h2 id="setup-auditor">Setup Auditor</h2>
<p><a href="https://github.com/GrapheneOS/Auditor">Auditor</a> provides attestation for GrapheneOS phones and the stock operating systems on <a href="https://attestation.app/about">a number of devices</a>. It uses hardware security features to make sure that the firmware and operating system have not been downgraded or tampered with.</p>
<p>Attestation can be done <a href="https://grapheneos.org/install/web#verifying-installation">locally</a> by pairing with another Android 8+ device or remotely using <a href="https://attestation.app/tutorial#scheduled-remote-verification">the remote attestation service</a>. To make sure that your hardware and operating system is genuine, perform local attestation immediately after the device has been set up and before connecting to the internet.</p>
<h2 id="use-global-toggles">Use Global Toggles</h2>
<p>Modern Android devices have global toggles for disabling Bluetooth and location services. Android 12 introduced toggles for the camera and microphone. When not in use, you should disable these features. Apps cannot use disabled features (even if granted individual permissions) until re-enabled.</p>
<h2 id="manage-android-permissions">Manage Android Permissions</h2>
<p><a href="https://developer.android.com/guide/topics/permissions/overview">Permissions on Android</a> grant you control over what apps are allowed to access. Google regularly makes <a href="https://developer.android.com/about/versions/11/privacy/permissions">improvements</a> on the permission system in each successive version. All apps you install are strictly <a href="https://source.android.com/security/app-sandbox">sandboxed</a>, therefore, there is no need to install any antivirus apps.</p>
<p>You can manage Android permissions by going to <strong>Settings</strong> → <strong>Privacy</strong> → <strong>Permission Manager</strong>. Be sure to remove from apps any permissions that they do not need.</p>
<h2 id="enable-vpn-killswitch">Enable VPN Killswitch</h2>
<p>Android 7 and above supports a VPN killswitch and it is available without the need to install third-party apps. This feature can prevent leaks if the VPN is disconnected. It can be found in <strong>Settings</strong> → <strong>Network &amp; internet</strong> → <strong>VPN</strong> → <strong>Block connections without VPN</strong>.</p>
<h2 id="connectivity-check">Connectivity Check</h2>
<p>Connectivity checks on Android <a href="https://mullvad.net/en/blog/2022/10/10/android-leaks-connectivity-check-traffic/">do not go through the VPN tunnel</a> (they are not supposed to anyway). This is generally not a cause for concern, however, you should be aware that Google and a network observer on your internet service provider (ISP)&rsquo;s network can see that there is an Android device with your actual IP address.</p>
<p>On GrapheneOS, connectivity checks by default are done with GrapheneOS&rsquo;s own servers, instead of with Google ones. A network observer on your ISP’s network can see that you are using a GrapheneOS device. If you are using a VPN and want to appear like a regular Android device to your ISP, go to <strong>Settings</strong> → <strong>Network &amp; internet</strong> → <strong>Internet connectivity check</strong> and select <strong>Standard (Google)</strong> instead. Note that this will not stop a determined adversarial ISP from finding out you are not using stock OS <a href="https://grapheneos.org/faq#default-dns">through your DNS fallback</a>.</p>
<p>If you want to, you can disable connectivity check altogether. Note that this will stop captive portals from working.</p>
<ul>
<li>On GrapheneOS, go to <strong>Settings</strong> → <strong>Network &amp; internet</strong> → <strong>Internet connectivity check</strong> and select <strong>Disabled</strong>.</li>
<li>On other Android-based operating systems, you can <a href="https://gitlab.com/CalyxOS/calyxos/-/issues/1226#note_1130393164">disable captive portal via ADB</a>.</li>
</ul>
<p>To disable:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">adb shell settings put global captive_portal_mode <span class="m">0</span>
</span></span></code></pre></div><p>To re-enable:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">adb shell settings delete global captive_portal_mode
</span></span></code></pre></div><h2 id="restrict-usb-peripherals">Restrict USB Peripherals</h2>
<p>USB peripherals should be disabled or set to only be allowed when the device is unlocked if possible.</p>
<p>On GrapheneOS, you can adjust this setting in <strong>Settings</strong> → <strong>Security</strong> → <strong>USB accessories</strong>. The OS defaults to &ldquo;Allow new USB peripherals when unlocked&rdquo;.</p>
<h2 id="media-access">Media Access</h2>
<p>Quite a few applications allow you to &ldquo;share&rdquo; a file with them for media upload. If you want to, for example, tweet a picture to Twitter, do not grant Twitter access to your &ldquo;media and photos&rdquo;, because it will have access to all of your pictures then. Instead, go to your file manager (documentsUI), hold onto the picture, then share it with Twitter.</p>
<p>If you are using GrapheneOS, you should utilize the Storage Scopes feature to force apps that request broad storage access permission to function with scoped storage.</p>
<p><img loading="lazy" src="/images/vlc-storage-scopes.png" alt="VLC Storage Scopes"  />
</p>
<h2 id="user-profiles">User Profiles</h2>
<p>Multiple user profiles can be found in <strong>Settings</strong> → <strong>System</strong> → <strong>Multiple users</strong> and are the simplest way to isolate in Android.</p>
<p>With user profiles, you can impose restrictions on a specific profile, such as: making calls, using SMS, or installing apps on the device. Each profile is encrypted using its own encryption key and cannot access the data of any other profiles. Even the device owner cannot view the data of other profiles without knowing their password. Multiple user profiles are a more secure method of isolation.</p>
<h2 id="work-profile">Work Profile</h2>
<p><a href="https://support.google.com/work/android/answer/6191949">Work Profiles</a> are another way to isolate individual apps and may be more convenient than separate user profiles.</p>
<p>A <strong>device controller</strong> such as <a href="https://gitea.angry.im/PeterCxy/Shelter#shelter">Shelter</a> is required, unless you&rsquo;re using CalyxOS which includes one.</p>
<p>The work profile is dependent on a device controller to function. Features such as <em>File Shuttle</em> and <em>contact search blocking</em> or any kind of isolation features must be implemented by the controller. You must also fully trust the device controller app, as it has full access to your data inside of the work profile.</p>
<p>This method is generally less secure than a secondary user profile; however, it does allow you the convenience of running apps in both the work and personal profiles simultaneously.</p>
<h2 id="baseband-modem-attack-surface-reduction">Baseband Modem Attack Surface Reduction</h2>
<p>By default, your baseband modem will typically be set to support just about every generation of mobile cellular technology, from 2G to 5G. This exposes a large attack surface.</p>
<p>You can reduce this attack surface by limiting the baseband modem to using just the generation that it needs. In most cases, this would be 4G/LTE.</p>
<p>GrapheneOS has the LTE only mode exposed in settings. You can set this by going to <strong>Settings</strong> → <strong>Internet</strong> → <strong>Your carrier name</strong> → <strong>Preferred network type</strong> → <strong>LTE Only</strong>.</p>
<p>If your Android-based operating system does not expose this setting in the Settings app, or if you want to set your baseband modem to a less restrictive mode, dial <code>*#*#4636#*#*</code> then hit <strong>Phone information</strong>. Here, you can set preferred network type to just the generations that you intend to use. For example, if you only want to use 5G and 4G, you can set it to <code>NR/LTE</code>.</p>
<h2 id="carrier-tracking">Carrier Tracking</h2>
<p>Carriers can track your coarse location through various means. At minimum, you need to use airplane mode to turn off the baseband modem, and turn off Wifi-calling which bypasses the system VPN. There may also be additional connections to the carrier&rsquo;s servers outside of the VPN tunnel, so you need to use Wireshark to verify this for your specific setup.</p>
<p><strong>Exact behavior does differ across SoCs and may vary between carriers as well</strong>, so I cannot give exact instructions for every setup. On a Google Pixel 7 Pro running GrapheneOS, you need to do the following:</p>
<ul>
<li>
<p>Disable Wi‑Fi calling.</p>
</li>
<li>
<p>Disable the SIMs/eSIMs in <strong>Settings</strong> → <strong>Network &amp; internet</strong> → <strong>SIMs</strong>. On GrapheneOS, if you are using an eSIM, you will need to enable privileged eSIM management. With certain carriers, there will be an ePDG server defined which the operating system will connect to outside of a VPN tunnel. While unlikely, a malicious carrier can track a user by giving them a unique ePDG server.</p>
</li>
<li>
<p>Turn on airplane mode. This will turn off the modem and disable all transmission to cell towers. Note that simply removing SIM cards is not enough &mdash; your phone will still connect to cellular networks to permit emergency calling.</p>
</li>
<li>
<p>Disable privileged eSIM management after you have disabled all of the eSIMs. With certain carriers, the eSIM management app will connect to the provisioning server to check for eSIM update, even if the eSIMs are disabled.</p>
</li>
</ul>
<h2 id="where-to-get-your-applications">Where to Get Your Applications</h2>
<h3 id="grapheneos-app-store">GrapheneOS App Store</h3>
<p>GrapheneOS&rsquo;s app store is available on <a href="https://github.com/GrapheneOS/Apps/releases">GitHub</a>. It supports Android 12 and above and is capable of updating itself. The app store has standalone applications built by the GrapheneOS project such as the <a href="https://attestation.app/">Auditor</a>, <a href="https://github.com/GrapheneOS/Camera">Camera</a>, and <a href="https://github.com/GrapheneOS/PdfViewer">PDF Viewer</a>. If you are looking for these applications, I highly recommend that you get them from GrapheneOS&rsquo;s app store instead of the Play Store, as the apps on their store are signed by the GrapheneOS&rsquo;s project own signature that Google does not have access to.</p>
<h3 id="aurora-store">Aurora Store</h3>
<p>The <a href="https://auroraoss.com/downloads/AuroraStore/">Aurora Store</a> is a proxy for the Google Play Store. It is great for privacy in the sense that it automatically gives you a disposable account to download apps, and it works on Android-based distributions that do not support Google Play Services. That being said, it lacks security features like certificate pinning and does not support Play Asset Delivery.</p>
<p>My recommendation is to stick with the Google Play Store unless your threat model calls for not logging into Google Services at all.</p>
<h3 id="f-droid">F-Droid</h3>
<p>F-Droid, despite being often recommended in the privacy community, has various security deficiencies. You can read more about them <a href="/posts/android/f-droid-security-issues/">here</a>.</p>
<p>I do not recommend that you use F-Droid at all unless you have no other choice to obtain certain apps. In some rare cases, there may be some apps which require the F-Droid version to work properly without Google Play Services. If you do end up using F-Droid, I highly recommend that you avoid the official F-Droid client (which is extremely outdated and targets API level 25) and use a more modern client with seamless updates such as <a href="https://github.com/NeoApplications/Neo-Store">NeoStore</a>. You should also avoid using the official F-Droid repository as much as possible and stick to the F-Droid repositories hosted by the app developers instead.</p>
<h3 id="github">GitHub</h3>
<p>You can also obtain your apps directly from their GitHub repositories. In most cases, there would be a pre-built APK for you to download. You can verify the signature of the downloaded using <code>apksigner</code>:</p>
<ul>
<li>Install <a href="https://developer.android.com/studio">Android Studio</a> which includes <code>apksigner</code>. On macOS, <code>apksigner</code> can be found at <code>~/Library/Android/sdk/build-tools/&lt;version&gt;/apksigner</code>.</li>
<li>Run <code>apksigner verify --print-certs --verbose myCoolApp.apk</code> to verify the certificate of the apk.</li>
</ul>
<p>After you have verified the signature of the apk and installed it on your phone, there are several strategies you can use to keep the application up-to-date.</p>
<p>The first strategy is to add the atom feed of the application&rsquo;s release page to an RSS Reader like <a href="https://github.com/Ashinch/ReadYou">ReadYou</a> to get notified of new releases. You will still need to download and install the new releases manually. If you are confused, here is a video that could help with this process:</p>
<div class="youtube-embed-div">
    <iframe src="https://www.youtube-nocookie.com/embed/FFz57zNR_M0" class="youtube-embed-frame" allowfullscreen title="YouTube Video"></iframe>
</div>  
<p>The second strategy is to use the <a href="https://apt.izzysoft.de/fdroid/">IzzyOnDroid</a> F-Droid repository with a modern F-Droid client like <a href="https://github.com/NeoApplications/Neo-Store">NeoStore</a>, as mentioned <a href="#f-droid">above</a>. The IzzyOnDroid repository pulls new releases from various GitHub repositories to their server, which can then be automatically downloaded and installed by NeoStore. The downside of this strategy is that not every application on GitHub is on IzzyOnDroid, and sometimes IzzyOnDroid fails to pull a new release, resulting in you not getting any updates at all.</p>
<p>It should be noted that since Android has automatic signature checking for existing applications on the system; that is, you only need to manually check the signature of the apk the first time you install an application. If you do use IzzyOnDroid to update applications, you will need to manually confirm the first update of an application to authorize the NeoStore as the installation source. After that, future updates will be seamless.</p>
<h2 id="google">Google</h2>
<p>If you are using a device with Google services, either with the stock operating system or an operating system that safely sandboxes Google Play Services like GrapheneOS, there are a number of additional changes you can make to improve your privacy.</p>
<h3 id="enroll-in-the-advanced-protection-program">Enroll in the Advanced Protection Program</h3>
<p><img loading="lazy" src="/images/advanced-protection-program.png" alt="Advanced Protection Program"  />
</p>
<p>If you have a Google account we suggest enrolling in the <a href="https://landing.google.com/advancedprotection/">Advanced Protection Program</a>. It is available at no cost to anyone with two or more hardware security keys with <a href="/knowledge/multi-factor-authentication/#fido2-fast-identity-online">FIDO2</a> support.</p>
<p>The Advanced Protection Program provides enhanced threat monitoring and enables:</p>
<ul>
<li>Stricter two factor authentication; e.g. that <a href="/posts/knowledge/multi-factor-authentication/#fido2-fast-identity-online">FIDO2</a> <strong>must</strong> be used and disallows the use of <a href="/posts/knowledge/multi-factor-authentication/#email-and-sms-mfa">SMS OTP</a>, <a href="/posts/knowledge/multi-factor-authentication/#time-based-one-time-password-totp">TOTP</a> and <a href="https://en.wikipedia.org/wiki/OAuth">OAuth</a></li>
<li>Only Google and verified third-party apps can access account data</li>
<li>Scanning of incoming emails on Gmail accounts for <a href="https://en.wikipedia.org/wiki/Phishing#Email_phishing">phishing</a> attempts</li>
<li>Stricter <a href="https://www.google.com/chrome/privacy/whitepaper.html#malware">safe browser scanning</a> with Google Chrome</li>
<li>Stricter recovery process for accounts with lost credentials</li>
</ul>
<p>If you use non-sandboxed Google Play Services (common on stock operating systems), the Advanced Protection Program also comes with <a href="https://support.google.com/accounts/answer/9764949?hl=en">additional benefits</a> such as:</p>
<ul>
<li>Not allowing app installation outside of the Google Play Store, the OS vendor&rsquo;s app store, or via <a href="https://en.wikipedia.org/wiki/Android_Debug_Bridge"><code>adb</code></a></li>
<li>Mandatory automatic device scanning with <a href="https://support.google.com/googleplay/answer/2812853?hl=en#zippy=%2Chow-malware-protection-works%2Chow-privacy-alerts-work">Play Protect</a></li>
<li>Warning you about unverified applications</li>
</ul>
<h3 id="google-play-system-updates">Google Play System Updates</h3>
<p>In the past, Android security updates had to be shipped by the operating system vendor. Android has become more modular beginning with <a href="https://www.android.com/android-10/">Android 10</a>, and Google <a href="https://blog.google/products/android-enterprise/android-10-security/">can push security updates</a> for <strong>some</strong> system components via the privileged Play Services.</p>
<p>If you have an EOL device shipped with Android 10 or above (shipped beginning 2020), you may be better off sticking with the stock OS in the short term as opposed to running an insecure alternative operating system. This will allow you to receive <strong>some</strong> security fixes from Google, while not violating the Android security model and increasing your attack surface. You should still upgrade to a supported device as soon as possible.</p>
<h3 id="disable-advertising-id">Disable Advertising ID</h3>
<p>All devices with Google Play Services installed automatically generate an <a href="https://support.google.com/googleplay/android-developer/answer/6048248?hl=en">advertising ID</a> used for targeted advertising. Disable this feature to limit the data collected about you.</p>
<p>On Android distributions with <a href="https://grapheneos.org/usage#sandboxed-google-play">Sandboxed Google Play</a>, go to <strong>Settings</strong> → <strong>Apps</strong> → <strong>Sandboxed Google Play</strong> → <strong>Google Settings</strong> → <strong>Ads</strong>, and select <em>Delete advertising ID</em>.</p>
<p>On Android distributions with privileged Google Play Services (such as stock OSes), the setting may be in one of several locations:</p>
<ul>
<li><strong>Settings</strong> → <strong>Google</strong> → <strong>Ads</strong></li>
<li><strong>Settings</strong> → <strong>Privacy</strong> → <strong>Ads</strong></li>
</ul>
<p><img loading="lazy" src="/images/ads-id.png" alt="Ads id"  />
</p>
<p>You will be given the option to either delete your advertising ID or <em>Opt out of interest-based ads</em> &mdash; this varies between OEM distributions of Android. If presented with the option to delete the advertising ID, choosing that is preferred. If not, then make sure to opt out and reset your advertising ID.</p>
<h3 id="google-messages">Google Messages</h3>
<p>Google is currently pushing for the adoption of <a href="https://support.google.com/messages/answer/10262381?hl=en">RCS with end to end encryption</a> to compete with iMessage. On certain Android devices, especially Google Pixels with stock OS, <a href="https://messages.google.com/">Google Messages</a> is set as the default SMS app to provide this feature.</p>
<p>If you are on an OS with Play Services installed, I highly recommend that you use Google Messages as the SMS app to get opportunistic end to end encryption with your contacts. It works fairly well on GrapheneOS with Sandboxed Play Services, too.</p>
<p>You can disable telemetry in Google Messages by tapping the profile in the top right → <strong>Messages settings</strong> → <strong>Help Improve Messages</strong> and toggling it off. There are also some other configurations in <strong>Messages settings</strong> → <strong>RCS chats</strong> that you might want to go over, such as <strong>Show typing indicators</strong> or <strong>Send read receipts</strong>.</p>
<p>If you have trouble connecting to RCS, try disabling your VPN and the VPN killswitch first, then reconnect to RCS. Once you have connected to the server, you can re-enable your VPN and the killswitch, and it should work just fine across reboots. I am not sure what is causing this issue, but it might be related to <a href="https://issuetracker.google.com/issues/189577131">this bug</a>.</p>
<h3 id="google-fi">Google Fi</h3>
<p>Google Fi provides <a href="https://fi.google.com/about/end-to-end-encrypted-calls">opportunistic end‑to‑end encryption</a> for phone calls between Fi users on Android and <a href="https://support.google.com/fi/answer/9040000">includes a VPN service</a>. Fi also implements a unique privacy‑bolstering <a href="https://www.gstatic.com/fi/wormhole/whitepaper-a00cc4732620f382da5b7aac2bcb6905f970ba6b.pdf">virtual carrier network</a> (VCN) architecture on supported devices, but it is <a href="https://support.google.com/fi/answer/9040000">temporarily disabled</a>.</p>
<p>This is not without its caveats:</p>
<ul>
<li>Google Fi requires Play Services and the <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.tycho&amp;hl=en_US">Fi app</a> to work properly. Without Play Services, all of the features mentioned above, along with visual voicemail, will not work. SMS messages will have random strings added at the end of each of them.</li>
<li>The Google Fi app needs to be installed in the owner profile for SIM/eSIM activation.</li>
<li>Google Fi Wi‑Fi calling does not work behind a VPN with the killswitch enabled in the owner profile.</li>
</ul>
<p>If you live in the United States and use the stock operating system, I highly recommend using Google Fi as your carrier to take advantage of the end to end encrypted calls and Fi VPN. People using a Pixel 4 and above will benefit the most from the VCN as mentioned.</p>
<p>If you use GrapheneOS and do not mind installing Sandboxed Play Services, Fi is still a better option than other providers thanks to Google&rsquo;s general good security practices and the fact that you can enroll in the Advanced Protection Program to have much better protection for your account. Some other providers do not even have multi-factor authentication support, and most will not let you enforce FIDO2 as the authentication method.</p>
]]></content>
      </entry>
      <entry>
        <title>Commercial VPN Use Cases</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/proxies/commercial-vpn-use-cases/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/proxies/commercial-vpn-use-cases/</id>
        <published>2022-07-19T00:00:00Z</published>
        <updated>2025-02-02T06:48:56-07:00</updated>
        <summary type="html">Virtual Private Networks are a way of creating a protected and private network over the open Internet. It was originally designed to provide remote access to an internal corporate network. However, in recent years, it has also been used by commercial VPN companies to hide their clients&amp;rsquo; real IP address from third-party websites and services.
Should I use a VPN? Yes, unless you are already using Tor. A VPN does two things: shifting the risks from your Internet Service Provider to itself and hiding your IP from a third-party service.</summary>
          <content type="html"><![CDATA[<p>Virtual Private Networks are a way of creating a protected and private network over the open Internet. It was originally designed to provide remote access to an internal corporate network. However, in recent years, it has also been used by commercial VPN companies to hide their clients&rsquo; real IP address from third-party websites and services.</p>
<h2 id="should-i-use-a-vpn">Should I use a VPN?</h2>
<p><strong>Yes</strong>, unless you are already using Tor. A VPN does two things: shifting the risks from your Internet Service Provider to itself and hiding your IP from a third-party service.</p>
<p>VPNs cannot encrypt data outside of the connection between your device and the VPN server. VPN providers can see and modify your traffic the same way your ISP could. And there is no way to verify a VPN provider&rsquo;s &ldquo;no logging&rdquo; policies in any way.</p>
<p>However, they do hide your actual IP from a third-party service, provided that there are no IP leaks. They help you blend in with others and mitigate IP based tracking.</p>
<h2 id="what-about-encryption">What about encryption?</h2>
<p>Encryption offered by VPN providers are between your devices and their servers. It guarantees that this specific link is secure. This is a step up from using unencrypted proxies where an adversary on the network can intercept the communications between your devices and said proxies and modify them. However, encryption between your apps or browsers with the service providers are not handled by this encryption.</p>
<p>In order to keep what you actually do on the websites you visit private and secure, you must use <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">TLS</a>. This will keep your passwords, session tokens, and queries safe from the VPN provider. Consider enabling &ldquo;HTTPS everywhere&rdquo; in your browser to mitigate downgrade attacks like <a href="https://www.blackhat.com/presentations/bh-dc-09/Marlinspike/BlackHat-DC-09-Marlinspike-Defeating-SSL.pdf">SSL Strip</a>.</p>
<h2 id="should-i-use-encrypted-dns-with-a-vpn">Should I use encrypted DNS with a VPN?</h2>
<p>Unless your VPN provider hosts the encrypted DNS servers, <strong>no</strong>. Using DOH/DOT (or any other form of encrypted DNS) with third-party servers will simply add more entities to trust and does <strong>absolutely nothing</strong> to improve your privacy/security. Your VPN provider can still see which websites you visit based on the IP addresses and other methods. Instead of just trusting your VPN provider, you are now trusting both the VPN provider and the DNS provider.</p>
<p>A common reason to recommend encrypted DNS is that it helps against DNS spoofing. However, your browser should already be checking for <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security#Digital_certificates">TLS certificates</a> with <strong>HTTPS</strong> and warn you about it. If you are not using <strong>HTTPS</strong>, then an adversary can still just modify anything other than your DNS queries and the end result will be little different.</p>
<p>Needless to say, <strong>you shouldn&rsquo;t use encrypted DNS with Tor</strong>. This would direct all of your DNS requests to a single entity and make you stand out from the rest of Tor users who would be using the exit node&rsquo;s DNS configuration.</p>
<h2 id="what-if-i-need-anonymity">What if I need anonymity?</h2>
<p>VPNs cannot provide anonymity. Your VPN provider will still see your real IP address, and often has a money trail that can be linked directly back to you. You cannot rely on &ldquo;no logging&rdquo; policies to protect your data. Use <a href="https://www.torproject.org/">Tor</a> instead.</p>
<h2 id="should-i-use-tor-over-vpn">Should I use Tor over VPN?</h2>
<p>By using Tor over VPN, you are creating essentially adding an extra node in the beginning of the circuit. This provides zero additional benefits to you, while increasing the latency of your connection dramatically. If you wish to hide your Tor usage from your ISP or your government, consider using Tor bridges with obfuscation methods.</p>
<h2 id="what-about-vpn-over-tor">What about VPN over Tor?</h2>
<p>By using VPN over Tor, you are adding an extra node at the end of a circuit, which is always controlled by the same entity. If you pay for the VPN using the traditional banking system, it essentially breaks the anonymity that the three hops in front of it would provide. If you pay for the VPN subscription using cash or a private cryptocurrency like Monero, your privacy is reduced to that of pseudonymity, since the VPN provider still knows the connections being made are from the same individual, they just do not know who you really are. Even if you are using a free VPN, you would still break <a href="https://www.whonix.org/wiki/Stream_Isolation">Stream Isolation</a>, one of Tor&rsquo;s important anonymity features. There are very few use cases where it would make sense to add a VPN server at the end of the chain.</p>
<h2 id="what-about-vpn-providers-that-provide-tor-nodes">What about VPN providers that provide Tor nodes?</h2>
<p>Do not use that feature. The point of using Tor is that you do not trust your VPN provider. Currently Tor only supports the <a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a> protocol. Through Tor, <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a> (used in <a href="https://en.wikipedia.org/wiki/WebRTC">WebRTC</a> for voice and video sharing, the new <a href="https://en.wikipedia.org/wiki/HTTP/3">HTTP3/QUIC</a> protocol, etc), <a href="https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol">ICMP</a> and other packets will be dropped. To compensate for this, VPN providers typically will route all non-TCP packets through their VPN server (your first hop). This is the case with <a href="https://protonvpn.com/support/tor-vpn/">ProtonVPN</a>. Additionally, like VPN over Tor, you lose control over other important Tor features like Stream Isolation.
Thus, this feature should be viewed as a convenient way to access the Tor Network, not to stay anonymous. For true anonymity, use the Tor Browser Bundle, TorSocks, or a Tor gateway.</p>
<h2 id="when-are-vpns-useful">When are VPNs useful?</h2>
<p>A VPN is useful in a variety of scenarios, such as:</p>
<ul>
<li>Hiding your traffic from <strong>only</strong> your Internet Service Provider.</li>
<li>Hiding your downloads (such as torrents) from your ISP and anti-piracy organizations.</li>
<li>Hiding your IP from third-party websites and services, preventing IP based tracking.</li>
</ul>
]]></content>
      </entry>
      <entry>
        <title>Choosing Your Android-Based Operating System</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/android/choosing-your-android-based-operating-system/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/android/choosing-your-android-based-operating-system/</id>
        <published>2022-07-18T00:00:00Z</published>
        <updated>2024-10-13T07:33:26-06:00</updated>
        <summary type="html">Android is a secure operating system that has strong app sandboxing, Verified Boot (AVB), and a robust permission control system.
When you buy an Android phone, the device&amp;rsquo;s default operating system often comes with invasive integration with apps and services that are not part of the Android Open-Source Project. An example of such is Google Play Services, which has irrevocable privileges to access your files, contacts storage, call logs, SMS messages, location, camera, microphone, hardware identifiers, and so on.</summary>
          <content type="html"><![CDATA[<p>Android is a secure operating system that has strong <a href="https://source.android.com/security/app-sandbox">app sandboxing</a>, <a href="https://source.android.com/security/verifiedboot">Verified Boot</a> (AVB), and a robust <a href="https://developer.android.com/guide/topics/permissions/overview">permission</a> control system.</p>
<p>When you buy an Android phone, the device&rsquo;s default operating system often comes with invasive integration with apps and services that are not part of the <a href="https://source.android.com/">Android Open-Source Project</a>. An example of such is Google Play Services, which has irrevocable privileges to access your files, contacts storage, call logs, SMS messages, location, camera, microphone, hardware identifiers, and so on. These apps and services increase the attack surface of your device and are the source of various privacy concerns with Android.</p>
<p>This problem could be solved by using a custom Android-based operating system that does not come with such invasive integration. Unfortunately, many custom Android-based operating systems often violate the Android security model by not supporting critical security features such as AVB, rollback protection, firmware updates, and so on. Some of them also ship <a href="https://source.android.com/setup/build/building#choose-a-target"><code>userdebug</code></a> builds which expose root over <a href="https://developer.android.com/studio/command-line/adb">ADB</a> and require <a href="https://github.com/LineageOS/android_system_sepolicy/search?q=userdebug&amp;type=code">more permissive</a> SELinux policies to accommodate debugging features, resulting in a further increased attack surface and weakened security model.</p>
<p>When choosing a custom Android-based operating system, you should make sure that it upholds the Android security model. Ideally, the custom operating system should have substantial privacy and security improvements to justify adding yet another party to trust.</p>
<h2 id="baseline-security">Baseline Security</h2>
<h3 id="verified-boot">Verified Boot</h3>
<p><img loading="lazy" src="/images/verified-boot.png" alt="Verified Boot"  />
</p>
<p><a href="https://source.android.com/security/verifiedboot">Verified Boot</a> is an important part of the Android security model. It provides protection against <a href="https://en.wikipedia.org/wiki/Evil_maid_attack">evil maid</a> attacks, malware persistence, and ensures security updates cannot be downgraded with <a href="https://source.android.com/security/verifiedboot/verified-boot#rollback-protection">rollback protection</a>.</p>
<p>On Android, only your data (inside of the /data partition) is encrypted, and the operating system files are left unencrypted. Verified Boot ensures the integrity of the operating system files, thereby preventing an adversary with physical access from tampering or installing malware on the device. In the unlikely case that malware is able to exploit other parts of the system and gain higher privileged access, Verified Boot will prevent and revert changes to the system partition upon rebooting the device.</p>
<p>Unfortunately, OEMs are only obliged to support Verified Boot on their stock Android distribution. Only a few OEMs such as Google support custom AVB key enrollment on their devices. Additionally, some AOSP derivatives such as LineageOS or /e/ OS do not support Verified Boot even on hardware with Verified Boot support for third-party operating systems. In most cases, trading off verified boot for simply not having Play Services is not worth it.</p>
<h3 id="firmware-updates">Firmware Updates</h3>
<p>Firmware updates are critical for maintaining security and without them your device cannot be secure. OEMs have support agreements with their partners to provide the closed-source components for a limited support period. These are detailed in the monthly <a href="https://source.android.com/security/bulletin">Android Security Bulletins</a>.</p>
<p>On a custom Android distribution, it is the responsibility of the operating system vendor to extract the firmware from the stock operating system, test it against their Android builds, then ship them to the user.</p>
<p>Unfortunately, many custom Android distributions, including extremely popular ones like LineageOS and /e/ OS do not ship firmware updates for most of their supported device. Instead, they expect the user to keep track of stock OS updates, extract and flash the firmware themselves. Beyond the lack of testing, this is extremely burdensome and not feasible for most end users and is yet another reason to not use these distributions.</p>
<h3 id="patch-levels">Patch Levels</h3>
<p>As the <a href="https://source.android.com/security/bulletin">Android Security Bulletins</a> is updated every month, Android-Based operating systems are expected to apply all security fixes before the next bulletin update comes out. Beside extracting the firmware, testing it and shipping it to the end user as described <a href="#firmware-updates">above</a>, the AOSP based system also need to be updated.</p>
<p>This is a particularly challenging thing to do, especially around the time of a new major Android release since there are a lot of changes. Sometimes, newer firmware versions require newer major versions of AOSP, and if the developer takes too long to update their base operating system to the next major AOSP version, they cannot ship firmware updates either, leaving users vulnerable.</p>
<p>This has happened to CalyxOS during the Android 11 to Android 12 transition. It took them <a href="https://github.com/privacyguides/privacyguides.org/pull/578#issue-1112002737">4 months</a> to update to Android 12; and during those 4 months, they could not ship any firmware updates at all, leaving the user vulnerable during that time period.</p>
<p>It would be much better if you just stick to the stock operating system (which got updated to Android 12 shortly after the AOSP 12 release) instead of using a custom operating system which could not keep up with updates as described.</p>
<h3 id="chromium-webview-updates">Chromium Webview Updates</h3>
<p>Android comes with a system <a href="https://developer.android.com/reference/android/webkit/WebView">webview</a>, a component that many apps rely on to use as part of their activity layout. It effectively behaves like a minimal browser, opening random websites with arbitrary code the internet. Thus, it is very important that this component is consistently kept up to date.</p>
<p>Some Android-based operating systems, including ones like CalyxOS, often fall behind on security updates for this component. Particularly, this has gotten so bad that they actually fell behind for <a href="https://github.com/privacyguides/privacyguides.org/pull/548#issuecomment-1018245074">3 months</a> back in January 2022 and <a href="https://github.com/privacyguides/privacyguides.org/pull/1378">2 months</a> in June 2022. It is a good indication that these operating systems cannot keep up with security updates and should not be used.</p>
<h3 id="user-builds">User Builds</h3>
<p>As mentioned <a href="/posts/os/choosing-your-android-based-operating-system/">above</a>, <code>userdebug</code> builds expose root over ADB and require more permissive SELinux policies to accommodate debugging features. They violate the Android security model and are really only meant for developers to test out their android builds during development.</p>
<p>End users should be using the production <code>user</code> builds. Distributions which do not ship <code>user</code> builds like LineageOS or /e/ OS should be avoided, especially if your device has not reached end of life.</p>
<h3 id="selinux-in-enforcing-mode">SELinux in Enforcing Mode</h3>
<p><a href="https://source.android.com/security/selinux">SELinux</a> is a critical part of the Android security model, having the Linux kernel enforcing confinement for all processes, including system processes running as root.</p>
<p>In order for a system to be secure, it must have SELinux in Enforcing mode, accompanied by fine-grained SELinux policies.</p>
<p>Unfortunately, many custom Android-based operating system builds (especially unofficial LineageOS builds) disables SELinux or set it into Permissive mode. You can check whether SELinux is in enforcing mode or not by executing <code>getenforce</code> in the ADB shell (the expected output is <code>Enforcing</code>). You should avoid any Android-based operating system builds that do not have SELinux in enforcing mode at all cost.</p>
<p><img loading="lazy" src="/images/adb-selinux.png" alt="ADB SELinux"  />
</p>
<h2 id="recommended-android-based-operating-systems">Recommended Android-Based Operating Systems</h2>
<p>Currently, I am only aware of two Android-based operating systems that should be used over the stock operating systems:</p>
<h3 id="grapheneos">GrapheneOS</h3>
<p><img loading="lazy" src="/images/grapheneos-aurora.jpg" alt="GrapheneOS Aurora"  />
</p>
<p><a href="https://grapheneos.org">GrapheneOS</a> is the <strong>only</strong> custom Android-based operating system you should buy a new phone for. It provides additional <a href="https://en.wikipedia.org/wiki/Hardening_(computing)">security hardening</a> and privacy improvements over the stock operating system from Google. It has a <a href="https://github.com/GrapheneOS/hardened_malloc">hardened memory allocator</a>, network and sensor permissions, and various other <a href="https://grapheneos.org/features">security feature</a>. GrapheneOS also comes with full firmware updates and signed builds, so verified boot is fully supported. Here is a quick video demonstrating the network and sensors permissions:</p>
<div class="youtube-embed-div">
    <iframe src="https://www.youtube-nocookie.com/embed/0ic6QK0xUMY" class="youtube-embed-frame" allowfullscreen title="YouTube Video"></iframe>
</div>  
<p>For usability purposes, GrapheneOS supports <a href="https://grapheneos.org/usage#sandboxed-google-play">Sandboxed Google Play</a>, which runs Google Play Services fully sandboxed like any other regular app. This means you can take advantage of most Google Play Services, such as <a href="https://firebase.google.com/docs/cloud-messaging/">push notifications</a>, while giving you full control over their permissions and access, and while containing them to a specific work profile or user profile of your choice. Most interestingly, the <a href="https://android-doc.github.io/google/play/billing/api.html">In-app Billing API</a>, <a href="https://play.google.com/googleplaygames">Google Play Games</a>, <a href="https://developer.android.com/guide/playcore/asset-delivery">Play Asset Delivery</a>, <a href="/posts/knowledge/multi-factor-authentication/#fido2-fast-identity-online">FIDO2</a> all work exceptionally well. Most <a href="https://landing.google.com/advancedprotection/">Advanced Protection Program</a> features, except for <a href="https://support.google.com/googleplay/answer/2812853?hl=en">Play Protect</a> and restricted app installation, also work.</p>
<p>Because GrapheneOS does not grant any Google Apps and Services apart from the opt-in eSIM action app privileged access to the system, Play Protect cannot disable or uninstall known malicious applications when it detects them. As for restricted app installation, this feature is not that useful on stock operating system anyways, since it is bypassable with <code>adb push</code>.</p>
<p>Recently, GrapheneOS has also added the <a href="https://grapheneos.org/usage#storage-access">Storage Scopes</a> feature, allowing you to force apps that request broad storage access permission to function with scoped storage. With this new feature, you no longer have to grant certain apps access to all of your media or files to use them anymore. You can watch a video of Storage Scope in action here:</p>
<div class="youtube-embed-div">
    <iframe src="https://www.youtube-nocookie.com/embed/WjrANjvrSzw" class="youtube-embed-frame" allowfullscreen title="YouTube Video"></iframe>
</div>  
<p>Currently, Google Pixel phones are the only devices that meet GrapheneOS&rsquo;s <a href="https://grapheneos.org/faq#device-support">hardware security requirements</a>.</p>
<h3 id="divestos">DivestOS</h3>
<p><a href="https://divestos.org/">DivestOS</a> is a great aftermarket operating system for devices that have gone end-of-life or are near end-of-life. Note that this is a harm reduction project, ran by one developer on the best effort basis, and you should not buy a new device just to run DivestOS.</p>
<p>Being a soft-fork of <a href="https://lineageos.org/">LineageOS</a>, DivestOS inherits many <a href="https://divestos.org/index.php?page=devices&amp;base=LineageOS">supported devices</a> from LineageOS. It has signed builds, making it possible to have <a href="https://source.android.com/security/verifiedboot">verified boot</a> on some non-Pixel devices. Unlike its upstream, it does ship <code>user</code> builds.</p>
<p>It comes with substantial hardening over AOSP. DivestOS has automated kernel vulnerability (<a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures">CVE</a>) <a href="https://gitlab.com/divested-mobile/cve_checker">patching</a>, fewer proprietary blobs, a custom <a href="https://divested.dev/index.php?page=dnsbl">hosts</a> file, and various security features ported from GrapheneOS. A non-exhaustive list of this includes:</p>
<ul>
<li>A hardened webview. <a href="https://gitlab.com/divested-mobile/mulch">Mulch</a> comes with <em>some</em> patches from GrapheneOS&rsquo;s Vanadium browser and the <a href="https://github.com/bromite/bromite">Bromite</a> project. It gets updated fairly quickly and does not fall behind nearly as much as Bromite did.</li>
<li>Kernel patches from GrapheneOS and enables all available kernel security features via <a href="https://github.com/Divested-Mobile/DivestOS-Build/blob/master/Scripts/Common/Functions.sh#L758">defconfig hardening</a>. All kernels newer than version 3.4 include full page <a href="https://lwn.net/Articles/334747/">sanitization</a> and all ~22 Clang-compiled kernels have <a href="https://reviews.llvm.org/D54604?id=174471"><code>-ftrivial-auto-var-init=zero</code></a> enabled.</li>
<li>GrapheneOS&rsquo;s <a href="https://developer.android.com/training/basics/network-ops/connecting"><code>INTERNET</code></a> and SENSORS permission toggle.</li>
<li><a href="https://github.com/GrapheneOS/hardened_malloc">Hardened memory allocator</a></li>
<li><a href="https://grapheneos.org/usage#exec-spawning">Secure Exec-Spawning</a></li>
<li>Partial <a href="https://en.wikipedia.org/wiki/Bionic_(software)">bionic</a> hardening patchsets from GrapheneOS</li>
<li>GrapheneOS&rsquo;s per-network full <a href="https://en.wikipedia.org/wiki/MAC_address#Randomization">MAC randomization</a> option on version 17.1 and higher</li>
<li>Automatic reboot/Wi-Fi/Bluetooth <a href="https://grapheneos.org/features">timeout options</a></li>
</ul>
<p>With that being said, DivestOS is not without its faults. The developer does not have all of the devices he is building for, and for a lot of them he simply publishes the builds blind without actually testing them. Firmware update support <a href="https://gitlab.com/divested-mobile/firmware-empty/-/blob/master/STATUS">varies</a> across devices. DivestOS also takes a very long time to update to a new major Android, and actually took longer than CalyxOS did as mentioned <a href="#firmware-updates">above</a>. It does not tend to fall behind on Chromium updates like CalyxOS, however.</p>
<p>Also, please note that I am only recommending DivestOS here, and not any of its related apps. For instance, I would not recommend using Mull, since it is just a Firefox Android fork with better defaults and still inherits many security deficiencies from its upstream, including the lack of support for <a href="https://wiki.mozilla.org/Project_Fission">site isolation</a> and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1565196">isolatedProcess</a>.</p>
]]></content>
      </entry>
      <entry>
        <title>Threat Modeling</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/knowledge/threat-modeling/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/knowledge/threat-modeling/</id>
        <published>2022-07-18T00:00:00Z</published>
        <updated>2024-06-11T14:20:47-07:00</updated>
        <summary type="html">The first task a person should do when taking steps to protect their privacy and security is to make a threat model.
Defining a threat To make a threat model, we must first define a threat. A common mistake made by people who are just getting into the privacy space is to define the threat as &amp;ldquo;big-tech companies.&amp;rdquo; There is a fundamental problem with this definition:
Why are we not trusting &amp;ldquo;big-tech companies,&amp;rdquo; but then shifting our trust to &amp;ldquo;small-tech companies&amp;rdquo;?</summary>
          <content type="html"><![CDATA[<p>The first task a person should do when taking steps to protect their privacy and security is to make a threat model.</p>
<h2 id="defining-a-threat">Defining a threat</h2>
<p><img loading="lazy" src="/images/cameras-1.jpg" alt="Cameras"  />
</p>
<p>To make a threat model, we must first define a threat. A common mistake made by people who are just getting into the privacy space is to define the threat as &ldquo;big-tech companies.&rdquo; There is a fundamental problem with this definition:</p>
<p>Why are we not trusting &ldquo;big-tech companies,&rdquo; but then shifting our trust to &ldquo;small-tech companies&rdquo;? What happens if those &ldquo;small-tech companies&rdquo; turn out to be malicious? What happens when our favorite &ldquo;small-tech company&rdquo; becomes successful and grows exponentially? <strong>The proper way to define the threat here is the &ldquo;service provider,&rdquo; not &ldquo;big-tech.&rdquo;</strong></p>
<p>Generally, there are four primary threats a person would want to protect themselves from:</p>
<ul>
<li>A service provider spying their users</li>
<li>Cross site/service tracking and data sharing, a.k.a. &ldquo;mass surveillance&rdquo;</li>
<li>An app developer spying on users through their malicious software</li>
<li>A hacker trying to get into users&rsquo; computers</li>
</ul>
<p>A typical person would have several of these threats in their threat model. Some of these threats may weigh more than others. For example, a software developer would have a hacker stealing their source code, signing keys, and secrets as their primary threat, but beyond that they would also want privacy from the websites they visit and so on. Likewise, an average Joe may have their primary threat as mass surveillance and service providers, but beyond that they also need to have decent security to prevent a hacker from stealing their data.</p>
<p>For whistleblowers, the threat model is much more extreme. Beyond what is mentioned above, they also need anonymity. Beyond just hiding what they do, what data they have, not getting hacked by hackers or governments, they also have to hide who they are.</p>
<h2 id="privacy-from-service-providers">Privacy from service providers</h2>
<p>In most setups, our &ldquo;private&rdquo; messages, emails, social interactions are typically stored on a server somewhere. The obvious problem with this is that the service provider (or a hacker who has compromised the server) can look into your &ldquo;private&rdquo; conversations whenever and however they want, without you ever knowing. This applies to many common services like SMS messaging, Telegram, Discord, and so on.</p>
<p>With end-to-end encryption, you can alleviate this issue by encrypting communications between you and your desired recipients before they are even sent to the server. The confidentiality of your messages is guaranteed, so long as the service provider does not have access to the private keys of either party.</p>
<p>In practice, the effectiveness of different end-to-end encryption implementations varies. Applications such as Signal run natively on your device, and every copy of the application is the same across different installations. If the service provider were to backdoor their application in an attempt to steal your private keys, that could later be detected using reverse engineering.</p>
<p>On the other hand, web-based end-to-end encryption implementations such as Proton Mail&rsquo;s webmail or Bitwarden&rsquo;s web vault rely on the server dynamically serving JavaScript code to the browser to handle cryptographic operations. A malicious server could target a specific user and send them malicious JavaScript code to steal their encryption key, and it would be extremely hard for the user to ever notice such a thing. Even if the user does notice the attempt to steal their key, it would be incredibly hard to prove that it is the provider trying to do so, because the server can choose to serve different web clients to different users.</p>
<p>Therefore, when relying on end-to-end encryption, you should choose to use native applications over web clients whenever possible.</p>
<p>Even with end-to-end encryption, service providers can still profile you based on <strong>metadata</strong>, which is typically not protected. While the service provider could not read your messages to see what you&rsquo;re saying, they can still observe things like who you&rsquo;re talking to, how often you message them, and what times you&rsquo;re typically active. Protection of metadata is fairly uncommon, and you should pay close attention to the technical documentation of the software you are using to see if there is any metadata minimization or protection at all, if that is a concern for you.</p>
<h2 id="protection-from-cross-siteservice-tracking">Protection from cross site/service tracking</h2>
<p>You can be tracked across websites and services using some form of identifiers. These are typically:</p>
<ul>
<li>Your IP address</li>
<li>Browser cookies</li>
<li>Your browser fingerprint</li>
<li>Data you submit to websites</li>
<li>Payment method correlation</li>
</ul>
<p>Your goals should be to segregate your online identities from each other, to blend in with other people, and simply to avoid giving out identifying information to anyone as much as possible.</p>
<p>Instead of relying on privacy policies (which are promises that could be violated), try to obfuscate your information in such a way that it is very difficult for different providers to correlate data with each other and build a profile on you. This could come in the form of using encryption tools like Cryptomator prior to uploading your data to cloud services, using prepaid cards or cryptocurrency to protect your credit/debit card information, using a VPN to hide your IP address from websites and services on the internet, etc. A privacy policy should only be relied upon as a last resort, when you have exhausted all of your options for true privacy and need to put complete trust in your service provider.</p>
<p>Bear in mind that companies can hide their ownership or share your information with data brokers, even if they are not in the advertising business. Thus, it makes little sense to solely focus on the &ldquo;ad-tech&rdquo; industry as a threat in your threat model. Rather, it makes a lot more sense to protect yourself from service providers as a whole, and any kind of corporate surveillance threat that most people are concerned about will be thwarted along with the rest.</p>
<h2 id="limiting-public-information">Limiting Public Information</h2>
<p>The best way to ensure your data is private is to simply not put it out there in the first place. Deleting information you find about yourself online is one of the best first steps you can take to regain your privacy.</p>
<p>On sites where you do share information, checking the privacy settings of your account to limit how widely that data is spread is very important. For example, if your accounts have a &ldquo;private mode,&rdquo; enable it to make sure your account isn&rsquo;t being indexed by search engines and can&rsquo;t be viewed by people you don&rsquo;t vet beforehand.</p>
<p>If you have already submitted your real information to a number of sites which shouldn&rsquo;t have it, consider employing disinformation tactics such as submitting fictitious information related to the same online identity to make your real information indistinguishable from the false information.</p>
<h2 id="protection-from-malware-and-hackers">Protection from malware and hackers</h2>
<p><img loading="lazy" src="/images/motherboard-1.jpg" alt="Motherboard"  />
</p>
<p>You need security to obtain any semblance of privacy: <strong>Using tools which appear private is futile if they could easily be exploited by attackers to release your data later.</strong></p>
<p>When it comes to application security, we generally do not (and sometimes cannot) know if the software that we use is malicious, or might one day become malicious. Even with the most trustworthy developers, there is generally no guarantee that their software does not have a serious vulnerability that could later be exploited.</p>
<p>To minimize the potential damage that a malicious piece of software can do, you should employ security by compartmentalization. This could come in the form of using different computers for different jobs, using virtual machines to separate different groups of related applications, or using a secure operating system with a strong focus on application sandboxing and mandatory access control.</p>
<p>Mobile operating systems are generally safer than desktop operating systems when it comes to application sandboxing. Apps cannot obtain root access and only have access to system resources which you grant them.</p>
<p>Desktop operating systems generally lag behind on proper sandboxing. ChromeOS has similar sandboxing properties to Android, and macOS has full system permission control and opt-in (for developers) sandboxing for applications, however these operating systems do transmit identifying information to their respective OEMs. Linux tends to not submit information to system vendors, but it has poor protection against exploits and malicious apps. This can be mitigated somewhat with specialized distributions which make heavy use of virtual machines or containers, such as Qubes OS.</p>
<p>Web browsers, email clients, and office applications all typically run untrusted code sent to you from third-parties. Running multiple virtual machines to separate applications like these from your host system as well as each other is one technique you can use to avoid an exploit in these applications from compromising the rest of your system. Technologies like Qubes OS or Microsoft Defender Application Guard on Windows provide convenient methods to do this seamlessly, for example.</p>
<p>If you are concerned about physical attacks you should use an operating system with a secure verified boot implementation, such as Android, iOS, ChromeOS, or macOS. You should also make sure that your drive is encrypted, and that the operating system uses a TPM or Secure <a href="https://support.apple.com/guide/security/secure-enclave-sec59b0b31ff/1/web/1">Enclave</a> or <a href="https://developers.google.com/android/security/android-ready-se">Secure Element</a> for rate limiting attempts to enter the encryption passphrase. You should avoid sharing your computer with people you don&rsquo;t trust, because most desktop operating systems do not encrypt data separately per-user.</p>
<h2 id="bad-practices">Bad Practices</h2>
<p>As a beginner, you may often fall into some bad practices while making a threat model. These include:</p>
<ul>
<li>Solely focusing on advertising networks instead of service providers as a whole</li>
<li>Heavy reliance on privacy policies</li>
<li>Blindly shifting trust from one service provider to another</li>
<li>Heavy reliance on badness enumeration for privacy instead of systematically solving the problem</li>
<li>Blindly trusting open-source software</li>
</ul>
<p>As discussed, focusing solely on advertising networks and relying solely on privacy policies does not make up a sensible threat model. When switching away from a service provider, try to determine what the root problem is and see if your new provider has any technical solution to the problem. For example, you may not like Google Drive as it means giving Google access to all of your data. The underlying problem here is the lack of end to end encryption, which you can solve by using an encryption tool like Cryptomator or by switching to a provider who provides it out of the box like Proton Drive. Blindly switching from Google Drive to a provider who does not provide end to end encryption like the Murena Cloud does not make sense.</p>
<p>You should also keep in mind that <a href="/knowledge/badness-enumeration/">badness enumeration does not work, cannot work, has never worked, and will never work</a>. While things like ad blockers and antiviruses may help block the low hanging fruits, they can never fully protect you from the threat. On the other hand, they often increase your attack surface and are not worth the security sacrifice. At best, they are merely convenience tools and should not be thought of as part of a defense strategy.</p>
<p>Another thing to keep in mind is that open-source software is not automatically private or secure. Malicious code can be sneaked into a package by the developer of a project, contributors, library developers or the person who compiles the code. Beyond that, sometimes, a piece of open-source software may have worse security properties than its proprietary counterpart. An example of this would be traditional Linux desktops lacking verified boot, system integrity protection, or a full system access control for apps when compared to macOS. When doing threat modeling, it is vital that you evaluate the privacy and security properties of each piece of software being used, rather than just blindly trusting it because it is open-source.</p>
]]></content>
      </entry>
      <entry>
        <title>FLOSS Security</title>
        <link rel="alternate" href="https://deploy-preview-444--privsec-dev.netlify.app/posts/knowledge/floss-security/" />
        <id>https://deploy-preview-444--privsec-dev.netlify.app/posts/knowledge/floss-security/</id>
        <published>2022-02-02T23:16:00Z</published>
        <updated>2024-04-15T00:50:31+02:00</updated>
        <summary type="html">While source code is critical for user autonomy, it isn&amp;rsquo;t required to evaluate software security or understand run-time behavior.
One of the biggest parts of the Free and Open Source Software definitions is the freedom to study a program and modify it; in other words, access to editable source code. I agree that such access is essential; however, far too many people support source availability for the wrong reasons. One such reason is that source code is necessary to have any degree of transparency into how a piece of software operates, and is therefore necessary to determine if it is at all secure or trustworthy.</summary>
          <content type="html"><![CDATA[<p>While source code is critical for user autonomy, it isn&rsquo;t required to evaluate software security or understand run-time behavior.</p>
<p>One of the biggest parts of the Free and Open Source Software definitions is the freedom to study a program and modify it; in other words, access to editable source code. I agree that such access is essential; however, far too many people support source availability for the <em>wrong</em> reasons. One such reason is that source code is necessary to have any degree of transparency into how a piece of software operates, and is therefore necessary to determine if it is at all secure or trustworthy. Although security through obscurity is certainly not a robust measure, this claim has two issues:</p>
<ul>
<li>Source code describes what a program is designed to do; it is unnecessary and insufficient to determine if what it actually does aligns with its intended design.</li>
<li>Vulnerability discovery doesn&rsquo;t require source code.</li>
</ul>
<p>I&rsquo;d like to expand on these issues, focusing primarily on compiled binaries. Bear in mind that I do not think that source availability is <em>useless</em> from a security perspective (it certainly makes audits easier), and I <em>do</em> think that source availability is required for user freedom. I&rsquo;m arguing only that <strong>source unavailability doesn&rsquo;t imply insecurity</strong>, and <strong>source availability doesn&rsquo;t imply security</strong>. It&rsquo;s possible (and often preferable) to perform security analysis on binaries, without necessarily having source code. In fact, vulnerability discovery doesn&rsquo;t typically rely upon source code analysis.</p>
<p>I&rsquo;ll update this post occasionally as I learn more on the subject. If you like it, check back in a month or two to see if it has something new.</p>
<p><em>PS: this stance is not absolute; I concede to several <a href="#good-counter-arguments">good counter-arguments in a dedicated section</a>!</em></p>
<h2 id="how-security-fixes-work">How security fixes work</h2>
<p>I don&rsquo;t think anyone seriously claims that software&rsquo;s security instantly improves the second its source code is published. The argument I&rsquo;m responding to is that source code is necessary to understand what a program does and how (in)secure it is, and without it we can&rsquo;t know for sure.</p>
<p>Assuming a re-write that fundamentally changes a program&rsquo;s architecture is not an option<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, software security typically improves by fixing vulnerabilities via something resembling this process:</p>
<ol>
<li>Someone discovers a vulnerability</li>
<li>Developers are informed of the vulnerability</li>
<li>Developers reproduce the issue and understand what caused it</li>
<li>Developers patch the software to fix the vulnerability</li>
</ol>
<p>Source code is typically helpful (sometimes essential) to Step 3. If someone has completed Step 3, they will require source code to proceed to Step 4. Source code <em>isn&rsquo;t necessary for Steps 1 and 2</em>; these steps rely upon understanding how a program misbehaves. For that, we use <em>reverse engineering</em> and/or <em>fuzzing</em>.</p>
<h2 id="reverse-engineering">Reverse engineering</h2>
<p>Understanding <em>how a program is designed</em> is not the same as understanding <em>what a program does.</em> A reasonable level of one type of understanding does not imply the other.</p>
<p>Source code<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> is essential to describe a program&rsquo;s high-level, human-comprehensible design; it represents a contract that outlines how a developer <em>expects</em> a program to behave. A compiler or interpreter<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> must then translate it into machine instructions. But source code isn&rsquo;t always easy to map directly to machine instructions because it is part of a complex system:</p>
<ul>
<li>
<p>Compilers (sometimes even interpreters) can apply optimizations and hardening measures that are difficult to reason about. This is especially true for Just-In-Time compilers that leverage run-time information.</p>
</li>
<li>
<p>The operating system itself may be poorly understood by the developers, and run a program in a way that contradicts a developer&rsquo;s expectations.</p>
</li>
<li>
<p>Toolchains, interpreters, and operating systems can have bugs that impact program execution.</p>
</li>
<li>
<p>Different compilers and compiler flags can offer different security guarantees and mitigations.</p>
</li>
<li>
<p>Source code can be deceptive by featuring sneaky obfuscation techniques, sometimes unintentionally. Confusing naming patterns, re-definitions, and vulnerabilities masquerading as innocent bugs have all been well-documented: look up &ldquo;hypocrite commits&rdquo; or the <a href="https://en.wikipedia.org/wiki/Underhanded_C_Contest">Underhanded C Contest</a> for examples.</p>
</li>
<li>
<p>All of the above points apply to each dependency and the underlying operating system, which can impact a program&rsquo;s behavior.</p>
</li>
</ul>
<p>Furthermore, all programmers are flawed mortals who don&rsquo;t always fully understand source code. Everyone who&rsquo;s done a non-trivial amount of programming is familiar with the feeling of encountering a bug during run-time for which the cause is impossible to find&hellip;until they notice it staring them in the face on Line 12. Think of all the bugs that <em>aren&rsquo;t</em> so easily noticed.</p>
<p>Reading the source code, compiling, and passing tests isn&rsquo;t sufficient to show us a program&rsquo;s final behavior. The only way to know what a program does when you run it is to&hellip;run it.<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
<h3 id="special-builds">Special builds</h3>
<p>Almost all programmers are fully aware of their limited ability, which is why most already employ techniques to analyze run-time behavior that don&rsquo;t depend on source code. For example, developers of several compiled languages<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup> can build binaries with sanitizers to detect undefined behavior, races, uninitialized reads, etc. that human eyes may have missed when reading source code. While source code is necessary to <em>build</em> these binaries, it isn&rsquo;t necessary to run them and observe failures.</p>
<p>Distributing binaries with sanitizers and debug information to testers is a valid way to collect data about a program&rsquo;s potential security issues.</p>
<h3 id="dynamic-analysis">Dynamic analysis</h3>
<p>It&rsquo;s hard to figure out which syscalls and files a large program program needs by reading its source, especially when certain libraries (e.g. the libc implementation/version) can vary. A syscall tracer like <a href="https://strace.io/"><code>strace(1)</code></a><sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup> makes the process trivial.</p>
<p>A personal example: the understanding I gained from <code>strace</code> was necessary for me to write <a href="https://sr.ht/~seirdy/bwrap-scripts/">my bubblewrap scripts</a>. These scripts use <a href="https://github.com/containers/bubblewrap"><code>bubblewrap(1)</code></a> to sandbox programs with the minimum permissions possible. Analyzing every relevant program and library&rsquo;s source code would have taken me months, while <code>strace</code> gave me everything I needed to know in an afternoon: analyzing the <code>strace</code> output told me exactly which syscalls to allow and which files to grant access to, without even having to know what language the program was written in. I generated the initial version of the syscall allow-lists with the following command<sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">strace name-of-program program-args 2&gt;&amp;1 \
</span></span><span class="line"><span class="cl">	| rg &#39;^([a-z_]*)\(.*&#39; --replace &#39;$1&#39; \
</span></span><span class="line"><span class="cl">	| sort | uniq
</span></span></code></pre></div><p>This also extends to determining how programs utilize the network: packet sniffers like <a href="https://www.wireshark.org/">Wireshark</a> can determine when a program connects to the network, and where it connects.</p>
<p>These methods are not flawless. Syscall tracers are only designed to shed light on how a program interacts with the kernel. Kernel interactions tell us plenty (it&rsquo;s sometimes all we need), but they don&rsquo;t give the whole story. Furthermore, packet inspection can be made a bit painful by transit encryption<sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup>; tracing a program&rsquo;s execution alongside packet inspection can offer clarity, but this is not easy.</p>
<p>For more information, we turn to <a href="https://en.wikipedia.org/wiki/Core_dump"><strong>core dumps</strong></a>, also known as memory dumps. Core dumps share the state of a program during execution or upon crashing, giving us greater visibility into exactly what data a program is processing. Builds containing debugging symbols (e.g. <a href="https://dwarfstd.org/">DWARF</a>) have more detailed core dumps. Vendors that release daily snapshots of pre-release builds typically include some symbols to give testers more detail concerning the causes of crashes. Web browsers are a common example: Chromium dev snapshots, Chrome Canary, Firefox Nightly, WebKit Canary builds, etc. all include debug symbols. <a href="https://twitter.com/MisteFr/status/1168597562703716354?s=20">Until 2019</a>, <em>Minecraft: Bedrock Edition</em> included debug symbols which were used heavily by the modding community.<sup id="fnref:9"><a href="#fn:9" class="footnote-ref" role="doc-noteref">9</a></sup></p>
<h4 id="dynamic-analysis-example-zoom">Dynamic analysis example: Zoom</h4>
<p>In 2020, Zoom Video Communications came under scrutiny for marketing its &ldquo;Zoom&rdquo; software as a secure, end-to-end encrypted solution for video conferencing. Zoom&rsquo;s documentation claimed that it used &ldquo;AES-256&rdquo; encryption. Without source code, did we have to take the docs at their word?</p>
<p><a href="https://citizenlab.ca/">The Citizen Lab</a> didn&rsquo;t. On 2020-04-03, it published <a href="https://citizenlab.ca/2020/04/move-fast-roll-your-own-crypto-a-quick-look-at-the-confidentiality-of-zoom-meetings/">a report</a> revealing critical flaws in Zoom&rsquo;s encryption. It utilized Wireshark and <a href="https://mitmproxy.org/">mitmproxy</a> to analyze networking activity, and inspected core dumps to learn about its encryption implementation. The Citizen Lab&rsquo;s researchers found that Zoom actually used an incredibly flawed implementation of a weak version of AES-128 (ECB mode), and easily bypassed it.</p>
<p>Syscall tracing, packet sniffing, and core dumps are great, but they rely on manual execution which might not hit all the desired code paths. Fortunately, there are other forms of analysis available.</p>
<h3 id="binary-analysis">Binary analysis</h3>
<p>Tracing execution and inspecting memory dumps can be considered forms of reverse engineering, but they only offer a surface-level view of what&rsquo;s going on. Reverse engineering gets much more interesting when we analyze a binary artifact.</p>
<p>Static binary analysis is a powerful way to inspect a program&rsquo;s underlying design. Decompilation (especially when supplemented with debug symbols) can re-construct a binary&rsquo;s assembly or source code. Symbol names may look incomprehensible in stripped binaries, and comments will be missing. What&rsquo;s left is more than enough to decipher control flow to uncover how a program processes data. This process can be tedious, especially if a program uses certain forms of binary obfuscation.</p>
<p>The goal doesn&rsquo;t have to be a complete understanding of a program&rsquo;s design (incredibly difficult without source code); it&rsquo;s typically to answer a specific question, fill in a gap left by tracing/fuzzing, or find a well-known property. When developers publish documentation on the security architecture of their closed-source software, reverse engineering tools like decompilers are exactly what you need to verify their honesty (or lack thereof).</p>
<p>Decompilers are seldom used alone in this context. Instead, they&rsquo;re typically a component of reverse engineering frameworks that also sport memory analysis, debugging tools, scripting, and sometimes even IDEs. I use <a href="https://rizin.re/">the Rizin framework</a>, but <a href="https://ghidra-sre.org/">Ghidra</a> is also popular. Their documentation should help you get started if you&rsquo;re interested.</p>
<h3 id="example-malware-analysis">Example: malware analysis</h3>
<p>These reverse-engineering techniques&mdash;a combination of tracing, packet sniffing, binary analysis, and memory dumps&mdash;make up the workings of most modern malware analysis. See <a href="https://www.hybrid-analysis.com/sample/1ef3b7e9ba5f486afe53fcbd71f69c3f9a01813f35732222f64c0981a0906429/5e428f69c88e9e64c33afe64">this example of a fully-automated analysis of the Zoom Windows installer</a>. It enumerates plenty of information about Zoom without access to its source code: reading unique machine information, anti-VM and anti-reverse-engineering tricks, reading config files, various types of network access, scanning mounted volumes, and more.</p>
<p>To try this out yourself, use a sandbox designed for dynamic analysis. <a href="https://github.com/cuckoosandbox">Cuckoo</a> is a common and easy-to-use solution, while <a href="https://drakvuf.com/">DRAKVUF</a> is more advanced.</p>
<h3 id="extreme-example-the-truth-about-intel-me-and-amt">Extreme example: the truth about Intel ME and AMT</h3>
<p>The Intel Management Engine (ME) is a mandatory subsystem of all Intel processors (after 2008) with extremely privileged access to the host system. Active Management Technology (AMT) runs atop it on the subset of Intel processors with &ldquo;vPro&rdquo; branding. The latter can be disabled and is intended for organizations to remotely manage their inventory (installing software, monitoring, remote power-on/sleep/wake, etc).</p>
<p>The fact that Intel ME has such deep access to the host system and the fact that it&rsquo;s proprietary have both made it the subject of a high degree of scrutiny. Many people (most of whom have little experience in the area) connected these two facts together to allege that the ME is a backdoor, often by confusedly citing functionality of Intel AMT instead of ME. Is it really impossible to know for sure?</p>
<p>I picked Intel ME+AMT to serve as an extreme example: it shows both the power and limitations of the analysis approaches covered. ME isn&rsquo;t made of simple executables you can just run in an OS because it sits far below the OS, in what&rsquo;s sometimes called &ldquo;Ring -3&rdquo;.<sup id="fnref:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup> Analysis is limited to external monitoring (e.g. by monitoring network activity) and reverse-engineering unpacked partially-obfuscated firmware updates, with help from official documentation. This is slower and harder than analyzing a typical executable or library.</p>
<p>Answers are a bit complex and…more boring than what sensationalized headlines would say. <a href="https://twitter.com/igorskochinsky">Igor Skochinsky</a> (the developer of <a href="https://github.com/skochinsky/me-tools">me-tools</a>) and <a href="https://github.com/corna">Nicola Corna</a> (the developer of <a href="https://github.com/corna/me_cleaner">me_cleaner</a>) presented their analysis of ME in <a href="https://fahrplan.events.ccc.de/congress/2017/Fahrplan/system/event_attachments/attachments/000/003/391/original/Intel_ME_myths_and_reality.pdf">Intel Me: Myths and Reality</a>; Vassilios Ververis thoroughly analyzed AMT in <a href="https://kth.diva-portal.org/smash/get/diva2:508256/FULLTEXT01">Security Evaluation of Intel&rsquo;s Active Management Technology</a>. Interestingly, the former pair argues that auditing binary code is preferable to potentially misleading source code: binary analysis allows auditors to “cut the crap” and inspect what software is truly made of. However, this was balanced by a form of binary obfuscation that the pair encountered; I’ll describe it in a moment.</p>
<p>Simply monitoring network activity and systematically testing all claims made by the documentation allowed Ververis to uncover a host of security issues in Intel AMT. However, no undocumented features have (to my knowledge) been uncovered. The problematic findings revolved around flawed/insecure implementations of documented functionality. In other words: there&rsquo;s been no evidence of AMT being &ldquo;a backdoor&rdquo;, but its security flaws could have had a similar impact. Fortunately, AMT can be disabled. What about ME?</p>
<p>This is where some binary analysis comes in. Neither Skochinsky&rsquo;s <a href="https://recon.cx/2014/slides/Recon%202014%20Skochinsky.pdf">ME Secrets</a> presentation nor <!-- raw HTML omitted -->Intel Me: Myths and Reality<!-- raw HTML omitted --> seem to enumerate any contradictions with <a href="https://link.springer.com/book/10.1007/978-1-4302-6572-6">official Intel documentation</a>.</p>
<p>Unfortunately, some components are poorly understood due to being obfuscated using <a href="http://io.netgarage.org/me/">Huffman compression with unknown dictionaries</a>. Understanding the inner workings of the obfuscated components blurs the line between software reverse-engineering and figuring out how the chips are actually made, the latter of which is nigh-impossible if you don&rsquo;t have access to a chip lab full of cash. However, black-box analysis does tell us about the capabilities of these components: see page 21 of &ldquo;ME Secrets&rdquo;. Thanks to zdctg for clarifying this.</p>
<p>Skochinsky&rsquo;s and Corna&rsquo;s analysis was sufficient to clarify (but not completely contradict) sensationalism claiming that ME can remotely lock any PC (it was a former opt-in feature), can spy on anything the user does (they clarified that access is limited to unblocked parts of the host memory and the integrated GPU, but doesn&rsquo;t include e.g. the framebuffer), etc.</p>
<p>While claims such as &ldquo;ME is a black box that can do anything&rdquo; are misleading, ME is not without its share of vulnerabilities. My favorite look at its issues is a presentation by <a href="https://www.blackhat.com/eu-17/speakers/Mark-Ermolov.html">Mark Ermolov</a> and <a href="https://www.blackhat.com/eu-17/speakers/Maxim-Goryachy.html">Maxim Goryachy</a> at Black Hat Europe 2017: <a href="https://www.blackhat.com/docs/eu-17/materials/eu-17-Goryachy-How-To-Hack-A-Turned-Off-Computer-Or-Running-Unsigned-Code-In-Intel-Management-Engine-wp.pdf">How to Hack a Turned-Off Computer, or Running Unsigned Code in Intel Management Engine</a>.</p>
<p>In short: ME being proprietary doesn&rsquo;t mean that we can&rsquo;t find out how (in)secure it is. Binary analysis when paired with runtime inspection can give us a good understanding of what trade-offs we make by using it. While ME has a history of serious vulnerabilities, they&rsquo;re nowhere near what <a href="https://web.archive.org/web/20210302072839/themerkle.com/what-is-the-intel-management-engine-backdoor/">borderline conspiracy theories</a> claim.<sup id="fnref:11"><a href="#fn:11" class="footnote-ref" role="doc-noteref">11</a></sup></p>
<p>(Note: Intel is not alone here. Other chips typically have equivalents, e.g. AMD Secure Technology).</p>
<h2 id="fuzzing">Fuzzing</h2>
<p>Manual invocation of a program paired with a tracer like <code>strace</code> won&rsquo;t always exercise all code paths or find edge-cases. <a href="https://en.wikipedia.org/wiki/Fuzzing">Fuzzing helps bridge this gap</a>: it automates the process of causing a program to fail by generating random or malformed data to feed it. Researchers then study failures and failure-conditions to isolate a bug.</p>
<p>Fuzzing doesn&rsquo;t necessarily depend on access to source code, as it is a black-box technique. Fuzzers like <a href="https://lcamtuf.coredump.cx/afl/">American Fuzzy Loop (AFL)</a> normally use <a href="#special-builds">special fuzz-friendly builds</a>, but <a href="https://aflplus.plus/docs/binaryonly_fuzzing/">other fuzzing setups</a> can work with just about any binaries. In fact, some types of fuzz tests (e.g. <a href="https://github.com/KissPeter/APIFuzzer/">fuzzing a web API</a>) hardly need any implementation details.</p>
<p>Fuzzing frequently catches bugs that are only apparent by running a program, not by reading source code. Even so, the biggest beneficiaries of fuzzing are open source projects. <a href="https://github.com/curl/curl-fuzzer">cURL</a>, <a href="https://github.com/openssl/openssl/tree/master/fuzz">OpenSSL</a>, web browsers, text rendering libraries (HarfBuzz, FreeType) and toolchains (GCC, Clang, the official Go toolchain, etc.) are some notable examples.</p>
<blockquote>
<p>I&rsquo;ve said it before but let me say it again: fuzzing is really the top method to find problems in curl once we&rsquo;ve fixed all flaws that the static analyzers we use have pointed out. The primary fuzzing for curl is done by OSS-Fuzz, that tirelessly keeps hammering on the most recent curl code.</p>
</blockquote>
<ul>
<li><a href="https://daniel.haxx.se/">Daniel Stenberg</a> | <a href="https://daniel.haxx.se/blog/2020/09/23/a-google-grant-for-libcurl-work/">A Google grant for libcurl work</a></li>
</ul>
<p>If you want to get started with fuzzing, I recommend checking out <a href="https://github.com/google/AFL/blob/master/docs/QuickStartGuide.txt">the quick-start guide for American Fuzzy Loop</a>. Some languages like Go 1.18 also have fuzzing tools available right in the standard library.</p>
<h3 id="example-cve-2022-0185">Example: CVE-2022-0185</h3>
<p>A recent example of how fuzzing helps spot a vulnerability in an open-source project is <a href="https://www.openwall.com/lists/oss-security/2022/01/18/7">CVE-<!-- raw HTML omitted -->2022-0185</a>: a Linux 0-day found by the Crusaders of Rust a few weeks ago. It was discovered using the <a href="https://github.com/google/syzkaller">syzkaller</a> kernel fuzzer. The process was documented on Will&rsquo;s Root:</p>
<p><a href="https://www.willsroot.io/2022/01/cve-2022-0185.html">CVE-2022-0185 - Winning a $31337 Bounty after Pwning Ubuntu and Escaping Google&rsquo;s KCTF Containers</a> by <a href="https://willsroot.io">willsroot</a></p>
<p>I <em>highly</em> encourage giving it a read; it&rsquo;s the perfect example of fuzzing with sanitizers to find a vulnerability, reproducing the vulnerability (by writing a tiny C program), <em>then</em> diving into the source code to find and fix the cause, and finally reporting the issue (with a patch!). When source isn&rsquo;t available, the vendor would assume responsibility for the &ldquo;find and fix&rdquo; steps.</p>
<p>The fact that some of the most-used pieces of FLOSS in existence have been the biggest beneficiaries of source-agnostic approaches to vulnerability analysis should be quite revealing. The source code to these projects has received attention from millions of eyes, yet they <em>still</em> invest in fuzzing infrastructure and vulnerability-hunters prefer analyzing artifacts over inspecting the source.</p>
<h2 id="good-counter-arguments">Good counter-arguments</h2>
<p>I readily concede to several points in favor of source availability from a security perspective:</p>
<ul>
<li>
<p>Source code can make analysis <em>easier</em> by <em>supplementing</em> source-independent approaches. The lines between the steps I mentioned in the <a href="#how-security-fixes-work">four-step vulnerability-fixing process</a> are blurry.</p>
</li>
<li>
<p>Patching vulnerabilities is important. Source availability makes it possible for the community, package maintainers, or reporters of a vulnerability to patch software. Package maintainers often blur the line between &ldquo;packager&rdquo; and &ldquo;contributor&rdquo; by helping projects migrate away from abandoned/insecure dependencies. One example that comes to mind is the Python 2 to Python 3 transition for projects like Calibre.<sup id="fnref:12"><a href="#fn:12" class="footnote-ref" role="doc-noteref">12</a></sup> Being able to fix issues independent of upstream support is an important mitigation against <a href="https://seirdy.one/posts/2021/01/27/whatsapp-and-the-domestication-of-users/">user domestication</a>.</p>
</li>
<li>
<p>Some developers/vendors don&rsquo;t distribute binaries that make use of modern toolchain-level exploit mitigations (e.g. <!-- raw HTML omitted -->PIE<!-- raw HTML omitted -->, <!-- raw HTML omitted -->RELRO<!-- raw HTML omitted -->, stack canaries, automatic variable initialization, <a href="https://clang.llvm.org/docs/ControlFlowIntegrity.html"><!-- raw HTML omitted -->CFI<!-- raw HTML omitted --></a>, etc.<sup id="fnref:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup>). In these cases, building software yourself with these mitigations (or delegating it to a distro that enforces them) requires source code availability (or at least some sort of intermediate representation).</p>
</li>
<li>
<p>Closed-source software may or may not have builds available that include sanitizers and debug symbols.</p>
</li>
<li>
<p>Although fuzzing release binaries is possible, fuzzing is much easier to do when source code is available. Vendors of proprietary software seldom release special fuzz-friendly builds, and filtering out false-positives can be quite tedious without understanding high-level design.</p>
</li>
<li>
<p>It is certainly possible to notice a vulnerability in source code. Excluding low-hanging fruit typically caught by static code analysis and peer review, it&rsquo;s not the main way most vulnerabilities are found nowadays (thanks to <a href="https://www.broken-by-design.fr/">X_CLI</a> for <a href="https://lemmy.ml/post/167321/comment/117774">reminding me about what source analysis does accomplish</a>.</p>
</li>
<li>
<p>Software as a Service can be incredibly difficult to analyze, as we typically have little more than the ability to query a server. Servers don&rsquo;t send core dumps, server-side binaries, or trace logs for analysis. Furthermore, it&rsquo;s difficult to verify which software a server is running.<sup id="fnref:14"><a href="#fn:14" class="footnote-ref" role="doc-noteref">14</a></sup> For services that require trusting a server, access to the server-side software is important from both a security and a user-freedom perspective</p>
</li>
</ul>
<p>Most of this post is written with the assumption that binaries are inspectable and traceable. Binary obfuscation and some forms of content protection/<!-- raw HTML omitted -->DRM<!-- raw HTML omitted --> violate this assumption and actually do make analysis more difficult.</p>
<p>Beyond source code, transparency into the development helps assure users of compliance with good security practices. Viewing VCS history, patch reviews, linter configurations, etc. reveal the standards that code is being held up to, some of which can be related to bug-squashing and security.</p>
<p><a href="https://matrix.to/#/@hypokeimenon:tchncs.de">Patience</a> on Matrix also had a great response, which I agree with and adapt below:</p>
<p>Whether or not the source code is available for software does not change how insecure it is. However, there are good security-related incentives to publish source code.</p>
<ul>
<li>Doing so improves vulnerability patchability and future architectural improvement by lowering the barrier to contribution. The fixes that follow can be <em>shared and used by other projects</em> across the field, some of which can in turn be used by the vendor. This isn&rsquo;t a zero-sum game; a rising tide lifts all boats.</li>
<li>It&rsquo;s generally good practice to assume an attacker has full knowledge of a system instead of relying on security through obscurity. Releasing code provides strong assurance that this assumption is being made. It&rsquo;s a way for vendors to put their money where their mouth is.</li>
</ul>
<p>Both Patience and <a href="https://drewdevault.com/">Drew Vault</a> argue that given the above points, a project whose goal is maximum security would release code. Strictly speaking, I agree. Good intentions don&rsquo;t imply good results, but they can <em>supplement</em> good results to provide some trust in a project&rsquo;s future.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I&rsquo;ve gone over some examples of how analyzing a software&rsquo;s security properties need not depend on source code, and vulnerability discovery in both FLOSS and in proprietary software uses source-agnostic techniques. Dynamic and static black-box techniques are powerful tools that work well from user-space (Zoom) to kernel-space (Linux) to low-level components like Intel ME+AMT. Source code enables the vulnerability-fixing process but has limited utility for the evaluation/discovery process.</p>
<p>Don&rsquo;t assume software is safer than proprietary alternatives just because its source is visible; come to a conclusion after analyzing both. There are lots of great reasons to switch from macOS or Windows to Linux (it&rsquo;s been my main OS for years), but <a href="https://madaidans-insecurities.github.io/linux.html">security is low on that list</a>.</p>
<p>All other things being mostly equal, FLOSS is obviously <em>preferable</em> from a security perspective; I listed some reasons why in the counter-arguments section. Unfortunately, being helpful is not the same as being necessary. All I argue is that source unavailability does not imply insecurity, and source availability does not imply security. Analysis approaches that don&rsquo;t rely on source are typically the most powerful, and can be applied to both source-available and source-unavailable software. Plenty of proprietary software is more secure than FLOSS alternatives; few would argue that the sandboxing employed by Google Chrome or Microsoft Edge is more vulnerable than Pale Moon or most WebKitGTK-based browsers, for instance.</p>
<p>Releasing source code is just one thing vendors can do to improve audits; other options include releasing test builds with debug symbols/sanitizers, publishing docs describing their architecture, and/or just keeping software small and simple. We should evaluate software security through <em>study</em> rather than source model. Support the right things for the right reasons, and help others make informed choices with accurate information. There are enough good reasons to support software freedom; we don&rsquo;t need to rely on bad ones.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Writing an alternative or re-implementation doesn&rsquo;t require access to the original&rsquo;s source code, as is evidenced by a plethora of clean-room re-implementations of existing software written to circumvent the need to comply with license terms.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Ideally well-documented, non-obfuscated code.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Or a JIT compiler, or a <a href="https://en.wikipedia.org/wiki/Analytical_Engine">bunch of clockwork</a>, or&hellip;&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>For completeness, I should add that there is one source-based approach that can verify correctness: formal proofs. Functional programming languages that <a href="https://en.wikipedia.org/wiki/Dependent_type">support dependent types</a> can be provably correct at the source level. Assuming their self-hosted toolchains have similar guarantees, developers using these languages might have to worry less about bugs they couldn&rsquo;t find in the source code. This can alleviate concerns that their language runtimes can make it hard to reason about low-level behavior. Thanks to <a href="https://adrian.geek.nz/">Adrian Cochrane</a> for pointing this out.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>For example: C, C++, Objective-C, Go, Fortran, and others can utilize sanitizers from Clang and/or GCC.&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p>This is probably what people in <em>The Matrix</em> were using to see that iconic <a href="https://en.wikipedia.org/wiki/Matrix_digital_rain">digital rain</a>.&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p>This command only lists syscall names, but I did eventually follow the example of <a href="https://github.com/Whonix/sandbox-app-launcher">sandbox-app-launcher</a> by allowing certain syscalls (e.g. ioctl) only when invoked with certain parameters. Also, I used <a href="https://github.com/BurntSushi/ripgrep">ripgrep</a> because I&rsquo;m more familiar with <!-- raw HTML omitted -->PCRE<!-- raw HTML omitted -->-style capture groups.&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p>Decrypting these packets typically involves saving and using key logs, or using endpoints with <a href="https://blog.didierstevens.com/2020/12/14/decrypting-tls-streams-with-wireshark-part-1/">known pre-master secrets</a>.&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:9">
<p>I invite any modders who miss these debug symbols to check out the FLOSS <a href="https://www.minetest.net/">Minetest</a>, perhaps with the <a href="https://content.minetest.net/packages/Wuzzy/mineclone2/">MineClone2</a> game.&#160;<a href="#fnref:9" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:10">
<p>See page 127-130 of the Invisible Things Lab&rsquo;s <a href="https://invisiblethingslab.com/resources/misc09/Quest%20To%20The%20Core%20%28public%29.pdf">Quest to the Core slides</a>. Bear in mind that they often refer to AMT running atop ME.&#160;<a href="#fnref:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:11">
<p>As an aside: your security isn&rsquo;t necessarily improved by &ldquo;disabling&rdquo; it, since it still runs during the initial boot sequence and does provide some hardening measures of its own (e.g., a <!-- raw HTML omitted -->TPM<!-- raw HTML omitted -->).&#160;<a href="#fnref:11" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:12">
<p>In 2017, Calibre&rsquo;s author actually wanted to stay with Python 2 after its EOL date, and <a href="https://bugs.launchpad.net/calibre/+bug/1714107">maintain Python 2 himself</a>. Users and package maintainers were quite unhappy with this, as Python 2 would no longer be receiving security fixes after 2020. While official releases of Calibre use a bundled Python interpreter, distro packages typically use the system Python package; Calibre&rsquo;s popularity and insistence on using Python 2 made it a roadblock to getting rid of the Python 2 package in most distros. What eventually happened was that community members (especially <a href="https://github.com/eli-schwartz">Eli Schwartz</a> and <a href="https://flaviutamas.com/">Flaviu Tamas</a> submitted patches to migrate Calibre away from Python 2. Calibre migrated to Python 3 by <a href="https://calibre-ebook.com/new-in/fourteen">version 5.0</a>.&#160;<a href="#fnref:12" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:13">
<p>Linux distributions&rsquo; CFI+<!-- raw HTML omitted -->ASLR<!-- raw HTML omitted --> implementations rely executables compiled with CFI+PIE support, and ideally with stack-smashing protectors and no-execute bits. These implementations are flawed (see <a href="https://web.archive.org/web/20211021222659/http://cybersecurity.upv.es/attacks/offset2lib/offset2lib-paper.pdf">On the Effectiveness of Full-ASLR on 64-bit Linux</a> and <a href="https://grsecurity.net/PaX-presentation.pdf">Brad Spengler&rsquo;s presentation comparing these with PaX&rsquo;s own implementation</a>).&#160;<a href="#fnref:13" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:14">
<p>The <a href="https://signal.org/blog/private-contact-discovery/">best attempt I know of</a> leverages <a href="https://en.wikipedia.org/wiki/Trusted_execution_environment">Trusted Execution Environments</a>, but for limited functionality using an implementation that&rsquo;s <a href="https://en.wikipedia.org/wiki/Software_Guard_Extensions#Attacks">far from bulletproof</a>.&#160;<a href="#fnref:14" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content>
      </entry>

</feed>


