<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="https://davidsherenowitsa.party/feed.xml" rel="self" type="application/atom+xml" /><link href="https://davidsherenowitsa.party/" rel="alternate" type="text/html" /><updated>2021-07-19T03:03:56+00:00</updated><id>https://davidsherenowitsa.party/feed.xml</id><title type="html">David Cook’s Blog</title><subtitle>David Cook's blog</subtitle><entry><title type="html">Examining Rockwell Automation’s Firmware Signatures</title><link href="https://davidsherenowitsa.party/2018/09/27/examining-rockwell-automation-s-firmware-signatures.html" rel="alternate" type="text/html" title="Examining Rockwell Automation’s Firmware Signatures" /><published>2018-09-27T21:58:00+00:00</published><updated>2018-09-27T21:58:00+00:00</updated><id>https://davidsherenowitsa.party/2018/09/27/examining-rockwell-automation-s-firmware-signatures</id><content type="html" xml:base="https://davidsherenowitsa.party/2018/09/27/examining-rockwell-automation-s-firmware-signatures.html">&lt;h1 id=&quot;background&quot;&gt;Background&lt;/h1&gt;

&lt;p&gt;Industrial automation products have long been behind the curve when it comes to computer security. Default passwords, backdoor passwords, unpatched vulnerabilities, and network protocols with no authentication have been the norm for years. Rockwell Automation, one of the more established vendors in the market, took a significant step forward in 2015 by adopting signed firmwares.&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;https://controltech.cz/sk/k-stiahnutiu/category/17-summer-days-2015-sk?download=204:powerflex-update-2015&quot;&gt;a Rockwell Automation slide deck&lt;/a&gt;, firmware signatures were first introduced in their PowerFlex 750 series of variable frequency drives. The motivation for this change wasn’t computer security concerns, but rather compliance with nuclear non-proliferation treaties. According to the presentation, the Department of Commerce updated export regulations on variable frequency drives with output frequencies of 600Hz or greater. (ten or twelve times the frequency of the electrical grid) Rockwell Automation addressed this by capping the output frequency in a software update, so that the drives weren’t subject to harsher export restrictions. This change was paired with a new firmware signature mechanism, which would enforce that only firmware images authored by the manufacturer could be flashed onto devices. Following this feature’s development for the PowerFlex 750 line, firmware signatures were rolled out to most other product lines to improve their security.&lt;/p&gt;

&lt;h1 id=&quot;signed-firmware&quot;&gt;Signed Firmware&lt;/h1&gt;

&lt;p&gt;Each firmware package consists of a configuration file (with extension &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.nvs&lt;/code&gt;) and one or more binary files. In a signed firmware package, half of the binary files that get flashed to the device are DER-encoded X.509 certificates, with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.der&lt;/code&gt; file extension. In a typical public key infrastructure, one would expect that an X.509 certificate would be used to identify a principal that makes signatures, but in this system, the certificate file acts as the firmware signature itself, with the help of some unusual vendor-specific extensions, described below.&lt;/p&gt;

&lt;h1 id=&quot;extensions&quot;&gt;Extensions&lt;/h1&gt;

&lt;p&gt;Each certificate file contains seven extensions, with OIDs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95.3.1&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95.3.7&lt;/code&gt;. The prefix of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1&lt;/code&gt; is assigned to private enterprises, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95&lt;/code&gt; in particular is assigned to Allen-Bradley, which is a division of Rockwell Automation. The extension with OID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95.3.1&lt;/code&gt; is particularly interesting, because it contains a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT STRING&lt;/code&gt; of the SHA-1 hash of the corresponding firmware image.&lt;/p&gt;

&lt;p&gt;Extensions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95.3.2&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95.3.6&lt;/code&gt; hold &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INTEGER&lt;/code&gt;s which might be related to firmware versions, product identifiers, or other metadata. Extension &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.3.6.1.4.1.95.3.7&lt;/code&gt; holds a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT STRING&lt;/code&gt; of unknown purpose.&lt;/p&gt;

&lt;h1 id=&quot;subject-and-issuer&quot;&gt;Subject and Issuer&lt;/h1&gt;

&lt;p&gt;The issuer name of each certificate is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O=Rockwell Automation&lt;/code&gt;. The subject name of each certificate has an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;organizationName&lt;/code&gt; field of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rockwell Automation&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;organizationalUnitName&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commonName&lt;/code&gt; fields that vary by product.&lt;/p&gt;

&lt;h1 id=&quot;certificate-signature&quot;&gt;Certificate Signature&lt;/h1&gt;

&lt;p&gt;Although the distinguished names of the subject and the issuer in each certificate are different, the public keys of the subject and the issuer are identical. From a chain building perspective, these are leaf certificates, but from a cryptographic perspective, these certificates are self-signed. This mismatch suggests that the certificates aren’t being used in a traditional PKI, and the bootloader isn’t building a chain of certificates back to a root certificate when it verifies firmware signatures.&lt;/p&gt;

&lt;h1 id=&quot;tools-for-certificate-signatures&quot;&gt;Tools for Certificate Signatures&lt;/h1&gt;

&lt;p&gt;The subject’s public key is encoded directly in the certificate body, but the issuer’s public key does not appear anywhere in an X.509 certificate, as it’s assumed to be known beforehand. However, the signature over the to-be-signed portion of the certificate is made with the issuer’s public key, so we can guess that the issuer’s public key is the same as the subject’s public key, try to verify the signature, and check if our guess was correct or not. I wrote a Python script to parse certificates and perform this verification and &lt;a href=&quot;https://gist.github.com/divergentdave/7cd98ee16919a1a159ded8bc3160c8da&quot;&gt;posted it as a gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If we hadn’t guessed that the certificates were self signed, we could have used a more generic approach to recover the issuer’s public key from any two certificates it signed. If we make a guess for the public exponent, raise each signature to the power of the public exponent, and subtract each padded plaintext message from the result, then the resulting differences will be multiples of the public modulus. Next, we compute the greatest common divisor of the two differences, and then divide out any small factors from the greatest common divisor to get a candidate public modulus. Finally, we check if the signatures are valid using this public key to determine if our public modulus guess was correct. I wrote another Python script to perform this calculation and &lt;a href=&quot;https://gist.github.com/divergentdave/40ac9c7224b382166c905e76595bcf73&quot;&gt;posted it as a gist too&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;algorithms&quot;&gt;Algorithms&lt;/h1&gt;

&lt;p&gt;Unfortunately, the firmware signature certificate files use SHA-1 and 1024-bit RSA keys. Neither of these choices would pass muster in the Web PKI today, nor would either have been a best practice back in 2015. Nation-state attackers might take advantage of novel attacks to forge firmware signatures, like how the US and Israel used an attack on MD5 signatures to forge Windows Update certificates. I would recommend migrating to SHA-256 instead of SHA-1, and either 2048-bit RSA or ECDSA. Of course, firmwares built after such a migration would have to reject signatures by the 1024-bit RSA key and signatures that use SHA-1 for this to be effective.&lt;/p&gt;

&lt;h1 id=&quot;serial-number&quot;&gt;Serial Number&lt;/h1&gt;

&lt;p&gt;The certificates appear to gave high-entropy serial numbers, which is good for security. About half of the certificates have a negative serial number, which isn’t allowed by the relevant RFCs. As a result, some tools may not work with half of these files.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Based on these observations, it seems that Rockwell Automation’s firmware signatures are the product of custom, proprietary tools. By including the hash of a firmware image in a certificate extension, they have repurposed X.509 certificates as a kind of detached signature with extra signed metadata. As far as I can tell, this signature scheme should be secure, but the outdated algorithms are concerning, and the reliance on self-signed certificates (with no way to provide a cross-signed certificate chain) will make key rotation difficult.&lt;/p&gt;</content><author><name>David Cook</name></author><summary type="html">Background</summary></entry><entry><title type="html">Solving Logic Puzzles with Z3</title><link href="https://davidsherenowitsa.party/2018/09/19/solving-logic-puzzles-with-z3.html" rel="alternate" type="text/html" title="Solving Logic Puzzles with Z3" /><published>2018-09-19T00:15:00+00:00</published><updated>2018-09-19T00:15:00+00:00</updated><id>https://davidsherenowitsa.party/2018/09/19/solving-logic-puzzles-with-z3</id><content type="html" xml:base="https://davidsherenowitsa.party/2018/09/19/solving-logic-puzzles-with-z3.html">&lt;p&gt;I’ve been attending &lt;a href=&quot;http://www.puzzledpint.com/&quot;&gt;Puzzled Pint&lt;/a&gt; events for the past year or so with a group of friends. These events are akin to pub trivia, except with puzzles, and they’re great fun. Two months ago, one of the puzzles was &lt;a href=&quot;http://www.puzzledpint.com/files/4615/2955/2400/04-Casino.pdf&quot;&gt;a classic logic grid puzzle set in a game of Texas Hold ‘Em&lt;/a&gt;. The organizers rated this puzzle as the most difficult that month; it took some effort, but we did solve it without hints.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://davidsherenowitsa.party/assets/logic_puzzle_screenshot.png&quot; alt=&quot;Poker logic puzzle from Puzzled Pint June 2018&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At the time, I had mused about wishing for a SAT/SMT solver to do the puzzle for me. “SAT” here refers to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Boolean_satisfiability_problem&quot;&gt;Boolean satisfiability problem&lt;/a&gt;, which is one of the classic hard problems in computer science. In turn, “SMT” is &lt;a href=&quot;https://en.wikipedia.org/wiki/Satisfiability_modulo_theories&quot;&gt;Satisfiability modulo theories&lt;/a&gt;, a more versatile generalization of the Boolean satisfiability problem. SAT solvers and SMT solvers both apply deduction, heuristics, and brute force to a formula to either solve it, prove that it has no solutions, or give up on it. Due to the particular way that both the SAT problem and SMT problem are hard, there’s no general way to efficiently solve every formula, but modern solvers can get answers on a lot of practical problems. But what of problems with no practical application?&lt;/p&gt;

&lt;p&gt;Later in the week, after Puzzled Pint, I sat down and re-solved the poker logic puzzle using &lt;a href=&quot;https://github.com/Z3Prover/z3&quot;&gt;Z3&lt;/a&gt;, an open source and freely available SMT solver by Microsoft. I’ve enjoyed playing around with Z3, and it’s the sort of hammer that can make everything look like a nail. Z3 uses an internal language that looks a lot like a LISP, which I’m given to understand is typical in the field. I used Z3’s Python library, which makes it easy to build Z3 expressions using function calls and normal mathematical operators.&lt;/p&gt;

&lt;p&gt;Due to terminology differences between fields, Z3 uses the term “constant” instead of “variable” to refer to symbols like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; in the formula &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4 * x + 3 * y = 27&lt;/code&gt;. Also, Z3 uses the term “sort” to describe what kind of value each constant can hold. To model the problem statement, I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IntSort&lt;/code&gt; to track the order in which the players folded, and I defined new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EnumSort&lt;/code&gt;s for non-numerical values like names. To tie the different values together, I defined functions that mapped player names to the values of their other properties. With this scaffolding in place, I translated each puzzle clue into constraint formulas, adding a new constant each time a clue mentioned an unknown player. I then ran the solver, printed out the results, added one more constraint to rule out that particular solution, and ran the solver again to confirm that the solution was unique.&lt;/p&gt;

&lt;p&gt;I have &lt;a href=&quot;https://gist.github.com/divergentdave/13a2a557c26146fc3e3b15a398f8428b&quot;&gt;posted the logic puzzle solver script in a gist&lt;/a&gt;, along with scripts for two more similar puzzles from other sources. Each script finds the answer in well under a second. To run these scripts, you’ll need Python 3 and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z3-python&lt;/code&gt; package installed. The same ideas should work on any logic puzzle, as long as the constraint formulas capture the precise meaning of each clue. Enjoy!&lt;/p&gt;</content><author><name>David Cook</name></author><summary type="html">I’ve been attending Puzzled Pint events for the past year or so with a group of friends. These events are akin to pub trivia, except with puzzles, and they’re great fun. Two months ago, one of the puzzles was a classic logic grid puzzle set in a game of Texas Hold ‘Em. The organizers rated this puzzle as the most difficult that month; it took some effort, but we did solve it without hints.</summary></entry></feed>