<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Capabilities on My personal blog</title>
        <link>https://www.matteobianchi.eu/tags/capabilities/</link>
        <description>Recent content in Capabilities on My personal blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Tue, 28 Apr 2026 09:00:00 +0200</lastBuildDate><atom:link href="https://www.matteobianchi.eu/tags/capabilities/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Capabilities: oltre il root tutto-o-niente</title>
        <link>https://www.matteobianchi.eu/p/capabilities-linux/</link>
        <pubDate>Tue, 28 Apr 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/capabilities-linux/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/capabilities-linux/cover.png" alt="Featured image of post Capabilities: oltre il root tutto-o-niente" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Nel modello classico c&amp;rsquo;erano solo due stati: root (può tutto) o non-root (quasi niente). Questo creava
un problema: un programma che aveva bisogno di &lt;em&gt;un solo&lt;/em&gt; potere di root — per esempio aprire la porta
80, riservata a root — doveva girare &lt;em&gt;interamente&lt;/em&gt; da root, con tutti i suoi poteri. Le &lt;strong&gt;capabilities&lt;/strong&gt;
spezzano l&amp;rsquo;onnipotenza di root in ~40 permessi distinti, così si può concedere &lt;em&gt;esattamente&lt;/em&gt; quello che
serve. È il &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/principio-minimo-privilegio/&#34; &gt;privilegio minimo&lt;/a&gt; applicato
ai poteri del kernel.&lt;/p&gt;
&lt;h2 id=&#34;alcune-capabilities-chiave&#34;&gt;Alcune capabilities chiave
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAP_NET_BIND_SERVICE  → aprire porte sotto la 1024 (es. 80, 443) senza essere root
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAP_NET_ADMIN         → configurare la rete (interfacce, firewall)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAP_SYS_ADMIN         → &amp;#34;il nuovo root&amp;#34;: enorme e pericolosa, da evitare come la peste
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAP_DAC_OVERRIDE      → ignorare i permessi dei file (quasi root sui file)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAP_CHOWN             → cambiare proprietario dei file
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAP_SYS_PTRACE        → ispezionare/alterare altri processi (debug, ma anche attacco)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;CAP_SYS_ADMIN&lt;/code&gt; è tristemente nota come &amp;ldquo;il nuovo root&amp;rdquo;: concede talmente tanto che darla equivale quasi
a dare root. Diffidane.&lt;/p&gt;
&lt;h2 id=&#34;leggere-e-assegnare-capabilities-sui-file&#34;&gt;Leggere e assegnare capabilities sui file
&lt;/h2&gt;&lt;p&gt;Si possono attaccare a un eseguibile (&lt;strong&gt;file capabilities&lt;/strong&gt;): il programma le ottiene all&amp;rsquo;esecuzione,
senza essere SUID-root. È l&amp;rsquo;alternativa moderna e più sicura al &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/permessi-speciali-suid-sgid/&#34; &gt;SUID&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;getcap -r /usr/bin 2&amp;gt;/dev/null         &lt;span class=&#34;c1&#34;&gt;# elenca i binari con capabilities assegnate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# es: /usr/bin/ping = cap_net_raw+ep   ← ping non è più SUID-root, ha solo questa capability&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# dare a un&amp;#39;app il permesso di aprire la porta 80, senza renderla root né SUID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;setcap &lt;span class=&#34;s1&#34;&gt;&amp;#39;cap_net_bind_service=+ep&amp;#39;&lt;/span&gt; /usr/local/bin/myapp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;getcap /usr/local/bin/myapp            &lt;span class=&#34;c1&#34;&gt;# verifica&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;setcap -r /usr/local/bin/myapp         &lt;span class=&#34;c1&#34;&gt;# rimuovere tutte le capabilities&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Il &lt;code&gt;+ep&lt;/code&gt; significa &lt;em&gt;effective&lt;/em&gt; + &lt;em&gt;permitted&lt;/em&gt;: la capability è attiva all&amp;rsquo;avvio. Perché questo è meglio
del SUID? Perché &lt;code&gt;myapp&lt;/code&gt; ottiene &lt;em&gt;solo&lt;/em&gt; il potere di aprire porte basse, non l&amp;rsquo;intero root: se viene
compromesso, l&amp;rsquo;attaccante non eredita l&amp;rsquo;onnipotenza.&lt;/p&gt;
&lt;h2 id=&#34;azzerare-le-capabilities-nei-servizi&#34;&gt;Azzerare le capabilities nei servizi
&lt;/h2&gt;&lt;p&gt;Nel &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/systemd-hardening-servizi/&#34; &gt;sandboxing systemd&lt;/a&gt; abbiamo visto
&lt;code&gt;CapabilityBoundingSet=&lt;/code&gt;. Qui si chiude il cerchio: si parte da zero e si concede solo lo stretto
necessario.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# nella unit del servizio
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CapabilityBoundingSet=CAP_NET_BIND_SERVICE   # il servizio può SOLO aprire porte basse
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AmbientCapabilities=CAP_NET_BIND_SERVICE     # e le riceve all&amp;#39;avvio, senza essere root
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# tutto il resto dei poteri di root è precluso, anche se gira come root
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Così un web server può legarsi alla 443 pur avendo azzerato ogni altro potere: compromesso, non può
caricare moduli kernel, non può ignorare i permessi dei file, non può amministrare la rete.&lt;/p&gt;
&lt;h2 id=&#34;verificare-le-capabilities-di-un-processo&#34;&gt;Verificare le capabilities di un processo
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;grep Cap /proc/&amp;lt;pid&amp;gt;/status            &lt;span class=&#34;c1&#34;&gt;# bitmask delle capabilities del processo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;getpcaps &amp;lt;pid&amp;gt;                         &lt;span class=&#34;c1&#34;&gt;# versione leggibile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;capsh --decode&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0000000000003000&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;# decodifica una bitmask in nomi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Le capabilities trasformano il root tutto-o-niente in un insieme di permessi concedibili uno a uno:
un binario ottiene solo &lt;code&gt;CAP_NET_BIND_SERVICE&lt;/code&gt; invece di tutto root, un servizio azzera il bounding set
e riceve solo ciò che gli serve. È privilegio minimo a livello di kernel. Ma capabilities e permessi
restano &lt;em&gt;discrezionali&lt;/em&gt;; per una politica che nemmeno root o il proprietario possano aggirare serve il
controllo d&amp;rsquo;accesso &lt;strong&gt;obbligatorio&lt;/strong&gt;: &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/selinux/&#34; &gt;SELinux&lt;/a&gt;, prossimo capitolo.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
