<feed xmlns="http://www.w3.org/2005/Atom"><title>Linux Audit</title><link href="https://linux-audit.com/atom.xml" rel="self" type="application/atom+xml"/><link href="https://linux-audit.com/"/><id>https://linux-audit.com/</id><updated>2026-05-15T07:38:44+00:00</updated><author><name>Michael Boelen</name><email>michael.boelen@cisofy.com</email></author><rights>Copyright 2026, Michael Boelen</rights><entry><title>Latest changes</title><link href="https://linux-audit.com/website/latest-changes/"/><id>https://linux-audit.com/website/latest-changes/</id><author><name>Michael Boelen</name></author><published>2023-05-13T00:07:52+02:00</published><updated>2026-05-15T07:38:44+00:00</updated><content type="html">&lt;p>This page contains the most recent changes to the blog.&lt;/p>
</content></entry><entry><title>Kernel hardening: Disable and blacklist Linux modules</title><link href="https://linux-audit.com/kernel/kernel-hardening-disable-and-blacklist-linux-modules/"/><id>https://linux-audit.com/kernel/kernel-hardening-disable-and-blacklist-linux-modules/</id><author><name>Michael Boelen</name></author><published>2015-05-16T14:52:39+00:00</published><updated>2026-05-15T07:37:22+00:00</updated><content type="html"><![CDATA[<p>The Linux kernel is modular, which makes it more flexible than monolithic kernels. New functionality can be easily added to a run kernel, by loading the related module. While that is great, it can also be misused. You can think of loading malicious modules (e.g. rootkits), or unauthorized access to the server and copy data via a USB port. In our previous article about <a href="/kernel/increase-kernel-integrity-with-disabled-linux-kernel-modules-loading/">kernel modules</a>, we looked at how to prevent loading any module. In this case, we specifically disallow the ones we don&rsquo;t want.</p>
<h2 id="blacklisting-modules">Blacklisting modules</h2>
<p>Blacklisting modules is one way to disallow them. This defines which modules should no longer be loaded. However, it will only limit the loading of modules during the boot process. You can still load a module manually after booting.</p>
<p>Blacklisting a module is simple. Create a file in the <span class="hl-box hl-2">/etc/modprobe.d</span> directory and give it a proper name (e.g. blacklist-module.conf).</p>
<h3 id="blacklisting-firewire">Blacklisting firewire</h3>
<p>Let&rsquo;s say we want to blacklist firewire. We first have to determine what modules are available. By using find, we can quickly determine the related kernel drivers:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line hl"><span class="cl"># find /lib/modules/`uname -r` -name *firewire*
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/firewire
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/firewire/firewire-ohci.ko.gz
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/firewire/firewire-core.ko.gz
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/firewire/firewire-sbp2.ko.gz
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/firewire/firewire-net.ko.gz
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/media/firewire
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/drivers/staging/fwserial/firewire-serial.ko.gz
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/sound/firewire
</span></span><span class="line"><span class="cl">/lib/modules/4.0.1-1-ARCH/kernel/sound/firewire/snd-firewire-lib.ko.gz
</span></span></code></pre></div><p>Now we know there are multiple modules, most part of the drivers and one in the sound section. If we want to disable all these modules, we could simply blacklist them all. Or block the generic category.</p>
<h3 id="gathering-module-information">Gathering module information</h3>
<p>By using <kbd class="hl-box hl-c"title="Shows information about kernel modules">modinfo</kbd>, we can gather the details about a particular module. In this case, we have a look at the <em>snd-firewire-lib</em> module and see what it does:</p>
































<figure>
    <picture>
      <source srcset="images/linux-audit-modinfo-depends-module.webp" type="image/webp">
<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /kernel/kernel-hardening-disable-and-blacklist-linux-modules/images/linux-audit-modinfo-depends-module_hu_6bfd2e5b4ca3d846.png 500w
  
  
  
  '
   src="/kernel/kernel-hardening-disable-and-blacklist-linux-modules/images/linux-audit-modinfo-depends-module.png"
 alt="Screenshot of modinfo which shows a dependency" loading="lazy">
    </picture>
    
    <figcaption>
      <p><i class="caption">The modinfo commands shows on which a module depends</i></p>
    </figcaption>
    
</figure>

<p>We can see it depends on firewire-core. Let&rsquo;s have a look at the firewire-core module itself:</p>
































<figure>
    <picture>
      <source srcset="images/linux-audit-modinfo-kernel-module-details.webp" type="image/webp">
<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /kernel/kernel-hardening-disable-and-blacklist-linux-modules/images/linux-audit-modinfo-kernel-module-details_hu_7d6abfbc48b4a328.png 500w
  
  
  
  '
   src="/kernel/kernel-hardening-disable-and-blacklist-linux-modules/images/linux-audit-modinfo-kernel-module-details.png"
 alt="Screenshot of modinfo of firewire core module" loading="lazy">
    </picture>
    
    <figcaption>
      <p><i class="caption">Details of firewire core module</i></p>
    </figcaption>
    
</figure>

<p>The details of the firewire-core module show that is responsible for firewire itself. It is the core unit itself and doing the transaction logic within the IEEE1394 protocol specifications. We can see it is depending on the CRC-ITU-T standard.</p>
<p>By blacklisting the firewire-core, we effectively disable any module depending on it. In this case, we don&rsquo;t blacklist the crc-itu-t module, to prevent other modules from properly functioning.</p>
<p>The related snippet to blacklist would be:</p>
<p><strong>/etc/modprobe.d/blacklist-firewire.conf</strong></p>
<blockquote>
<p>blacklist firewire-core</p>
</blockquote>
<h3 id="see-blacklisted-modules">See blacklisted modules</h3>
<p>To see what modules are currently blacklisted, we can use the modprobe command:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line hl"><span class="cl"># modprobe --showconfig | grep blacklist
</span></span><span class="line"><span class="cl">blacklist firewire_core
</span></span></code></pre></div><p>This will show all modules which are blacklisted.</p>
<h2 id="disable-modules">Disable modules</h2>
<p>The next level of blacklisting modules is to actually disable them. This way they won&rsquo;t be loaded unintentionally.</p>
<p>To disable a module, we have to redirect a module via the install option. Modprobe will try to load the related file. By defining a module as /bin/true, it won&rsquo;t be loaded.</p>
































<figure>
    <picture>
      <source srcset="images/linux-audit-modprobe-could-not-insert.webp" type="image/webp">
<img 
  sizes="(min-width: 35em) 1200px, 100vw"
  srcset='
  
    /kernel/kernel-hardening-disable-and-blacklist-linux-modules/images/linux-audit-modprobe-could-not-insert_hu_4a1a8dcbb03f8c79.png 500w
  
  
  
  '
   src="/kernel/kernel-hardening-disable-and-blacklist-linux-modules/images/linux-audit-modprobe-could-not-insert.png"
 alt="Screenshot of modprobe failing" loading="lazy">
    </picture>
    
    <figcaption>
      <p><i class="caption">Using the install option we can avoid loading modules</i></p>
    </figcaption>
    
</figure>

<p>To see what modules are currently disabled via install, we can use modprobe as well:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line hl"><span class="cl"># modprobe --showconfig | grep &#34;^install&#34; | grep &#34;/bin&#34;
</span></span><span class="line"><span class="cl">install firewire_core /bin/true
</span></span><span class="line"><span class="cl">install firewire_ohci /bin/true
</span></span></code></pre></div><p><strong>Note</strong>: the root user can still override settings, by using the <em>--ignore-install</em> parameter. In that case, the module can still be loaded.</p>
<h2 id="conclusion">Conclusion</h2>
<p>By using the right combination of blacklist, install and alias, we can disallow the loading of Linux kernel modules. They form the first level of defense against unintentional and unauthorized module loading. By using the kernel setting <strong>kernel.modules_disabled</strong> and set its value to 1, we can make sure things are really tightened. Even the root user can not load any modules anymore.</p>
<h2 id="useful-commands">Useful commands</h2>
<p>When working with kernel modules, here are some of the most common commands:</p>
<ul>
<li><strong>Blacklisted and disabled modules</strong>
<ul>
<li>modprobe -showconfig | egrep &ldquo;^(blacklist|install)&rdquo;</li>
</ul>
</li>
<li><strong>Find modules</strong>
<ul>
<li>find /lib/modules/`uname -r` -print</li>
</ul>
</li>
<li><strong>Show loaded modules</strong>
<ul>
<li>lsmod</li>
</ul>
</li>
<li><strong>Load module</strong>
<ul>
<li>modprobe module</li>
</ul>
</li>
<li><strong>Unload module</strong>
<ul>
<li>modprobe -r module</li>
</ul>
</li>
<li><strong>Module details</strong>
<ul>
<li>modinfo module</li>
</ul>
</li>
</ul>
<p><em>Questions or other tips? Let it know!</em></p>
]]></content></entry><entry><title>Nginx hardening profile</title><link href="https://linux-audit.com/systemd/hardening-profiles/nginx/"/><id>https://linux-audit.com/systemd/hardening-profiles/nginx/</id><author><name>Michael Boelen</name></author><published>2024-06-25T19:26:50+00:00</published><updated>2026-04-30T08:57:38+00:00</updated><content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>This is a hardening profile to help securing nginx by using systemd unit configuration. It&rsquo;s goal is to restrict what nginx can do and make it harder for any possible vulnerability to be misused.</p>
<p>The rationale for the selected settings is based on the analysis as part of the article <a href="/web/nginx-hardening-with-systemd/">Hardening nginx with systemd security features</a>.</p>
<p>Relevant FAQ: <a href="/systemd/faq/how-to-use-systemctl-edit/">How to use systemctl edit to change a service?</a></p>

<h2 id="notes-and-fine-tuning">Notes and fine-tuning</h2>
<p>As nginx can be tailored to multiple needs, most likely some fine-tuning is needed. Depending on external components such as PHP, temporary files may need to be made accessible. When possible, define an alternative directory and keep PrivateTmp enabled.</p>
<blockquote>
<p>If you are using an older hardening profile, please upgrade at least to 0.5 or higher.</p>
</blockquote>
<h3 id="debian">Debian</h3>
<p>Debian systems may need an extension to ExecPaths and allow also /sbin/start-stop-daemon</p>
<h3 id="transparent-proxy">Transparent proxy</h3>
<p>When using proxy functionality (proxy_bind $remote_addr transparent), adjustments may need to be made to allow this. Otherwise nginx can&rsquo;t fork the worker processes.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">SecureBits=no-setuid-fixup-locked noroot-locked
</span></span><span class="line"><span class="cl">CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_CHOWN CAP_SETGID CAP_SETUID CAP_NET_RAW
</span></span></code></pre></div><blockquote>
<p>Rationale: nginx uses prctl(PR_SET_KEEPCAPS, 1) before setuid(). If keep-caps-locked is set in SecureBits, an EPERM issue will occur with a fatal exit 2 code for the worker processes.</p>
</blockquote>
<p>Got a more tight version that works? Let it know.</p>
<h2 id="changes">Changes</h2>
<ul>
<li>Adjust SecureBits (0.5)</li>
<li>Add PrivateTmp=yes</li>
<li>Changed LockPersonality from &rsquo;true&rsquo; to &lsquo;yes&rsquo;</li>
<li>Additional comments</li>
<li>Add capability: CAP_SETPCAP due to usage of SecureBits</li>
<li>Add SecureBits</li>
<li>Allow real-time scheduling</li>
</ul>
<h2 id="special-thanks">Special thanks</h2>
<p>To Jean-Baptiste for reporting an issue with SecureBits that may allow access to files while normally not permitted with file permissions.</p>
]]></content></entry><entry><title>journalctl cheat sheet</title><link href="https://linux-audit.com/cheat-sheets/journalctl/"/><id>https://linux-audit.com/cheat-sheets/journalctl/</id><author><name>Michael Boelen</name></author><published>2024-04-24T12:41:39+00:00</published><updated>2025-11-19T06:04:28+00:00</updated><content type="html"><![CDATA[<h2 id="common-journalctl-options">Common journalctl options</h2>
<table>
  <thead>
      <tr>
          <th>Long option</th>
          <th>Short option</th>
          <th>What the option does</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>--catalog</td>
          <td>-x</td>
          <td>Show log lines with additional help or suggestions where available</td>
      </tr>
      <tr>
          <td>--disk-usage</td>
          <td></td>
          <td>Show size of the archived and active journals</td>
      </tr>
      <tr>
          <td>--follow</td>
          <td>-f</td>
          <td>Track changes, like tail -f</td>
      </tr>
      <tr>
          <td>--lines=</td>
          <td>-n</td>
          <td>Show X number of lines (most recent)</td>
      </tr>
      <tr>
          <td>--output=</td>
          <td>-o</td>
          <td>Define what output format should be used for journal entries</td>
      </tr>
      <tr>
          <td>--pager-end</td>
          <td>-e</td>
          <td>Go to the end of the pager output, so the last entries are visibible</td>
      </tr>
      <tr>
          <td>--reverse</td>
          <td>-r</td>
          <td>Reverse output, newest on top</td>
      </tr>
      <tr>
          <td>--since=</td>
          <td>-S</td>
          <td>Limit the data to a specific period (begin)</td>
      </tr>
      <tr>
          <td>--unit</td>
          <td>-u</td>
          <td>Specify the unit when querying the logs or taking an action</td>
      </tr>
      <tr>
          <td>--until=</td>
          <td>-U</td>
          <td>Limit the data to a specific period (end)</td>
      </tr>
      <tr>
          <td>--vacuum-files</td>
          <td></td>
          <td>Trim journal logs by number</td>
      </tr>
      <tr>
          <td>--vacuum-size</td>
          <td></td>
          <td>Clear log entries from journal logs by specifying total size</td>
      </tr>
      <tr>
          <td>--vacuum-time</td>
          <td></td>
          <td>Clear log entries from journal logs by specifying time (age)</td>
      </tr>
      <tr>
          <td>--verify</td>
          <td></td>
          <td>Integrity check of the journals</td>
      </tr>
  </tbody>
</table>
<h3 id="showing-basic-details-of-the-journals">Showing basic details of the journals</h3>
<p>The size of the journals can displayed with <span class="hl-box hl-c-o">--disk-usage</span>, which may be useful when the file system is getting full.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line hl"><span class="cl"># journalctl --disk-usage
</span></span><span class="line"><span class="cl">Archived and active journals take up 160.0M in the file system.
</span></span></code></pre></div><p>To verify the integrity of the journals, use the <span class="hl-box hl-c-o">--verify</span> option.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line hl"><span class="cl"># journalctl --verify
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/system@ca889eb2eae24e41b37a50d33bad131c-0000000000000001-00060ed90326924f.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/user-1000@aeb5e2f412954ecfaa870c245338cb93-00000000000036b8-000611a51acdc7d0.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/user-1000@aeb5e2f412954ecfaa870c245338cb93-00000000000004e2-00060ed9041f690a.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/user-1000.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/system@ca889eb2eae24e41b37a50d33bad131c-0000000000014c26-000613a20f360102.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/system.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/user-1000@aeb5e2f412954ecfaa870c245338cb93-0000000000014e03-000613d7a3bb17e3.journal
</span></span><span class="line"><span class="cl">PASS: /var/log/journal/d8bd6473290d43a9942eaba0a506a454/system@ca889eb2eae24e41b37a50d33bad131c-0000000000003334-0006113d51794916.journal
</span></span></code></pre></div><h2 id="querying-the-journals">Querying the journals</h2>
<p>There are many ways to query the journals. One of them is simply running <code>journalctl</code> and start scrolling. But there are better ways!</p>
<h3 id="query-by-time-or-period">Query by time or period</h3>
<p>Show messages of today with the <span class="hl-box hl-c-o">--since=</span> option and define the period.</p>
<p><code>journalctl --since=&quot;today&quot;</code></p>
<p>To shorten the period, we can tell it to show only very recent entries of fifteen minutes ago or newer.</p>
<p><code>journalctl --since=&quot;15 minutes ago&quot;</code></p>
<p>We can also provide a range, with the combination of <em>since</em> and <em>until</em>.</p>
<p><code>journalctl --since=&quot;2024-02-01&quot; --until=&quot;2024-04-01&quot;</code></p>
<p>For troubleshooting it may help to increase the period, but include a unit name to strip out much of the unneeded entries.</p>
<p><code>journalctl --unit ssh.service --since=&quot;1 week ago&quot;</code></p>
<h3 id="query-by-priority-or-facility">Query by priority or facility</h3>
<p>Journalctl allows to query by priority. Here are the available levels:</p>
<table>
  <thead>
      <tr>
          <th>Priority level</th>
          <th>Name</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0</td>
          <td>emerg</td>
      </tr>
      <tr>
          <td>1</td>
          <td>alert</td>
      </tr>
      <tr>
          <td>2</td>
          <td>crit</td>
      </tr>
      <tr>
          <td>3</td>
          <td>err</td>
      </tr>
      <tr>
          <td>4</td>
          <td>warning</td>
      </tr>
      <tr>
          <td>5</td>
          <td>notice</td>
      </tr>
      <tr>
          <td>6</td>
          <td>debug</td>
      </tr>
      <tr>
          <td>7</td>
          <td>info</td>
      </tr>
  </tbody>
</table>
<p>Use the short notation, but now include the unit name in the output, and limit messages to a priority (including the ones with lower number, meaning a higher priority).</p>
<p><code>journalctl -S &quot;today&quot; --output=with-unit --priority=err</code></p>
<p>Only show some levels (notice, debug, and info)</p>
<p><code>journalctl -p 5..7</code></p>
<p>When querying by facility, which are common with syslog, define the right value. To know the available facilities, use the &lsquo;help&rsquo;.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-plaintext" data-lang="plaintext"><span class="line hl"><span class="cl"># journalctl --facility=help
</span></span><span class="line"><span class="cl">Available facilities:
</span></span><span class="line"><span class="cl">kern
</span></span><span class="line"><span class="cl">user
</span></span><span class="line"><span class="cl">mail
</span></span><span class="line"><span class="cl">daemon
</span></span><span class="line"><span class="cl">auth
</span></span><span class="line"><span class="cl">syslog
</span></span><span class="line"><span class="cl">lpr
</span></span><span class="line"><span class="cl">news
</span></span><span class="line"><span class="cl">uucp
</span></span><span class="line"><span class="cl">cron
</span></span><span class="line"><span class="cl">authpriv
</span></span><span class="line"><span class="cl">ftp
</span></span><span class="line"><span class="cl">12
</span></span><span class="line"><span class="cl">13
</span></span><span class="line"><span class="cl">14
</span></span><span class="line"><span class="cl">15
</span></span><span class="line"><span class="cl">local0
</span></span><span class="line"><span class="cl">local1
</span></span><span class="line"><span class="cl">local2
</span></span><span class="line"><span class="cl">local3
</span></span><span class="line"><span class="cl">local4
</span></span><span class="line"><span class="cl">local5
</span></span><span class="line"><span class="cl">local6
</span></span><span class="line"><span class="cl">local7
</span></span></code></pre></div><h3 id="query-by-string">Query by string</h3>
<p>Similar to the <strong>grep</strong> tool, there are a few options available to search in the journals. It shares the same name, but is an option instead.</p>
<p><code>journalctl --grep &quot;[bB]lock&quot;</code></p>
<blockquote>
<p>Regular expressions are allowed, so be aware of case-sensitive filtering.</p>
</blockquote>
<p>Want to search and not worry about lowercase and uppercase?</p>
<p><code>journalctl --case-sensitive=false --grep &quot;block&quot;</code></p>
<h3 id="query-only-by-priority-error">Query only by priority ERROR</h3>
<p>Show only the entries flagged with priority ERROR.</p>
<p><code>journalctl -p err</code></p>
<p>Or since last boot:</p>
<p><code>journalctl -b -p err</code></p>
<h2 id="limit-output-and-follow">Limit output and follow</h2>
<p>Journalctl allows to limit the output to a specific number of lines. To show the last 10 lines, which is equal to <strong>--lines=10</strong>, we can use <strong>-n</strong>.</p>
<p><code>journalctl -n</code></p>
<p>We can also combine it with a unit, and show only 5 lines.</p>
<p><code>journalctl -u ssh.service -n 5</code></p>
<p>Keep track of new additions, we can use the <span class="hl-box hl-c-o"title="Shortened option: -f">--follow</span> option, similar to <code>tail -f</code>.</p>
<p><code>journalctl --follow</code></p>
<h2 id="cleaning-up-the-journals">Cleaning up the journals</h2>
<p>When the journal gets too big, decrease its size by performing a <em>vacuum</em> action.</p>
<p><code>journalctl --vacuum-size=256M</code></p>
<p>It is also possible to set a time period instead, like 4 weeks.</p>
<p><code>journalctl --vacuum-time=4w</code></p>
<p>Another possibility is defining the number of logs.</p>
<p><code>journalctl --vacuum-files=5</code></p>
<h2 id="other-useful-options">Other useful options?</h2>
<p>Did I miss something that really should be included in this cheat sheet? Let it <a href="/contact/">know</a>!</p>
]]></content></entry><entry><title>systemd-analyze</title><link href="https://linux-audit.com/system-administration/commands/systemd-analyze/"/><id>https://linux-audit.com/system-administration/commands/systemd-analyze/</id><author><name>Michael Boelen</name></author><published>2024-06-27T19:07:12+00:00</published><updated>2025-11-14T12:36:24+00:00</updated></entry></feed>