<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="3.9.3">Jekyll</generator><link href="https://danzinger.wien/feed.xml" rel="self" type="application/atom+xml" /><link href="https://danzinger.wien/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2023-09-04T11:34:04+02:00</updated><id>https://danzinger.wien/feed.xml</id><title type="html">Philipp Danzinger</title><subtitle>Hey there, I'm Philipp. I am an undergraduate computer science student at TU Wien (inofficially known as the Technical University of Vienna). I am interested in a lot of things, including parallelism and optimisation, security, and (quantum) complexity theory. Sometimes I manually solve control problems for large dynamical systems (i.e. playing factorio).</subtitle><author><name>Philipp Danzinger</name><email>your-email@email.com</email></author><entry><title type="html">Exploiting KeePassRPC</title><link href="https://danzinger.wien/exploiting-keepassrpc/" rel="alternate" type="text/html" title="Exploiting KeePassRPC" /><published>2020-08-01T11:00:00+02:00</published><updated>2020-08-01T11:00:00+02:00</updated><id>https://danzinger.wien/exploiting-keepassrpc</id><content type="html" xml:base="https://danzinger.wien/exploiting-keepassrpc/">&lt;p&gt;While taking a university course on security, I discovered two critical related vulnerabilities in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePassRPC&lt;/code&gt;, an addon for the popular password manager &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePass&lt;/code&gt;. Both vulnerabilities allow a malicious web site to read and leak (unlocked) KeePass databases, while being very hard or impossible to detect, provided the KeePassRPC addon is installed.
Shortly after I reported them, the vulnerabilities were patched and &lt;a href=&quot;https://forum.kee.pm/t/a-critical-security-update-for-keepassrpc-is-available/3040&quot;&gt;publicly disclosed&lt;/a&gt; by the developer.&lt;/p&gt;

&lt;p&gt;With this blog post I aim to provide a bit of context and background about the discovery, as well as some technical details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, a short summary for users:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Am I affected?&lt;/strong&gt; You are affected if you are using the password manager &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePass&lt;/code&gt; and have installed the plugin &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePassRPC&lt;/code&gt; (prior to version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.12.0&lt;/code&gt; released on the 29th of July 2020). The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePassRPC&lt;/code&gt; plugin is used to interface with the Firefox/Chrome extension &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kee&lt;/code&gt; as well as the Thunderbird extension &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeeBird&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;In case this applies to you, you are advised to &lt;a href=&quot;https://forum.kee.pm/t/upgrading-keepassrpc/22&quot;&gt;update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePassRPC&lt;/code&gt;&lt;/a&gt; immediately.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Have my passwords been compromised?&lt;/strong&gt; If you are or were using a vulnerable version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeePassRPC&lt;/code&gt;, this is possible. Exploiting the vulnerabilities is possible while leaving little or no trace. On the other hand, the vulnerabilities were not publicly known prior to the release of the patch, and at the time of writing this, I am not personally aware of any real-world exploit using them. Based on this, one may consider it unlikely that individual users were compromised. In the end, you have to weigh the risks yourself.&lt;/li&gt;
  &lt;li&gt;For more details, see &lt;a href=&quot;https://forum.kee.pm/t/a-critical-security-update-for-keepassrpc-is-available/3040&quot;&gt;the official announcement&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without further ado, let’s jump into the details.&lt;/p&gt;

&lt;h2 id=&quot;i-had-one-job&quot;&gt;I had one job…&lt;/h2&gt;

&lt;p&gt;This tale starts with the finale of another one. Internet Security, one of the &lt;del&gt;hardest&lt;/del&gt; most rewarding computer science lectures at TU Wien, was about to end. A big part of the lecture consisted of solving practice problems in offensive security (which is code for hacking).&lt;/p&gt;

&lt;p&gt;One part of the final challenge was a simple implementation task: the lecturers had set up an automated environment with KeePass, KeePassRPC, and a web browser. The assignment was to adapt the official Kee extension to leak passwords once a connection had been established (or to create a new browser extension mimicking Kee).&lt;/p&gt;

&lt;p&gt;KeePassRPC works by creating a web socket server, which Kee can connect to. To secure the connection, a protocol called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SRP-6a&lt;/code&gt; is employed. This involves a popup window by KeePassRPC containing a password, which the user has to enter into the browser. This proves to KeePassRPC that the connection is authorized by the user.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/exploiting-keepassrpc/password_window.png&quot; style=&quot;width:30em&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In our assignment, a (virtual) user would automatically enter this password. Our only job was to change the extension so that it steals some passwords afterward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;…but…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn’t know this at first. The assignment had just been published and the grader wasn’t quite ready yet.&lt;/p&gt;

&lt;p&gt;So, after essentially solving the challenge (and being unable to check) I thought “wouldn’t it be interesting if I could do it without a password?”.&lt;/p&gt;

&lt;p&gt;It turned out that bypassing the password was very much possible. Only later did I find out (to my surprise and shock) that this could be abused remotely since web browsers don’t prohibit web sites from opening a web socket connection to localhost.&lt;/p&gt;

&lt;p&gt;Once all the dust from the lecture had settled, I consulted with the lecturers, Michael Pucher and Georg Merzdovnik, to develop proof-of-concept exploits and responsibly disclose the vulnerabilities.&lt;/p&gt;

&lt;h2 id=&quot;kee-keepassrpc-and-srp-6a&quot;&gt;Kee, KeePassRPC and SRP-6a&lt;/h2&gt;

&lt;p&gt;KeePassRPC and the Kee browser addon use (a slight variation of) the SRP-6a protocol to establish an encrypted connection. For the purposes of this post, SRP-6a can be thought of as an extension of the well-known Diffie-Hellman key exchange.&lt;/p&gt;

&lt;p&gt;Diffie-Hellman is a protocol that allows two parties to establish a shared secret key even in the presence of an eavesdropping attacker. To that end, they each pick a random secret number (say, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; respectively) and perform a modular power calculation (i.e. a power modulo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; is a fixed large number) to arrive at public numbers (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;), which they exchange. By means of mathematical magic, each party then uses its own secret number and the other person’s public number to arrive at the same shared key, called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;SRP-6a can be thought of as adding an authentication layer to Diffie-Hellman. First off, the two parties receive asymmetric roles of &lt;em&gt;user&lt;/em&gt; (‘client’) and &lt;em&gt;host&lt;/em&gt; (‘server’). New calculations and parameters are introduced to ensure that a connection can only be established if both parties are in possession of some password and if they agree on said password.&lt;/p&gt;

&lt;p&gt;More details can be found in &lt;a href=&quot;http://srp.stanford.edu/design.html&quot;&gt;the official SRP-6(a) documentation&lt;/a&gt; and &lt;a href=&quot;https://forum.kee.pm/t/keepassrpc-technical-detail/2364&quot;&gt;this post about the SRP-6a implementation in KeePassRPC&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;vulnerability-1-a0-edge-case&quot;&gt;Vulnerability 1: A=0 edge case&lt;/h2&gt;

&lt;p&gt;In SRP-6a the &lt;em&gt;user&lt;/em&gt; has little freedom. In fact, apart from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username&lt;/code&gt; (which is not used by KeePassRPC) the only parameter the &lt;em&gt;user&lt;/em&gt; can freely control is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;.
According to the protocol, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; gets calculated as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A = g^a&lt;/code&gt; where g is a conventional constant number, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; is a secret number picked by the &lt;em&gt;user&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Of course, an attacker need not follow the protocol to the letter and can choose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; freely. One choice turns out to be particularly interesting. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A=0&lt;/code&gt;, the computation of the session key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt; becomes particularly simple. When we (somewhat counterintuitively) start with the calculation usually performed by the host, we obtain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S = ((Av)^u)^b = (0^u)^b = 0&lt;/code&gt;.
Yup, the session key just becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, regardless of the password.&lt;/p&gt;

&lt;p&gt;This is not an issue with SRP-6a itself, as the specification [1] makes the following demand: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;The host will abort if it detects that A == 0 (mod N)&lt;/code&gt;.
Unfortunately, this check was not correctly implemented in KeePassRPC, allowing an attacker to connect instantly without the password.&lt;/p&gt;

&lt;p&gt;The following clip shows the exploit in action. If you pay close attention, you can see the password popup from KeePassRPC becoming visible for a short time before quickly vanishing again.&lt;/p&gt;

&lt;p&gt;&lt;img data-gifffer=&quot;/assets/img/exploiting-keepassrpc/poc1.gif&quot; style=&quot;width:40em&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;vulnerability-2-weak-secret-random-numbers&quot;&gt;Vulnerability 2: weak secret random numbers&lt;/h2&gt;

&lt;p&gt;After figuring out the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A=0&lt;/code&gt; exploit, I decided to revisit another peculiarity I had noticed previously. Namely, a few variables, including the secret &lt;em&gt;host&lt;/em&gt; parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, were being generated with a cryptographically weak random number generator.&lt;/p&gt;

&lt;div class=&quot;language-cs highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Language: C#&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// SRP.cs before fix (https://github.com/kee-org/keepassrpc/blob/67ba4de94bbd81368a37e911436cb94907f7173c/KeePassRPC/SRP.cs)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Comments are mine&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SRP&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// [...]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_b&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BigInteger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;genRandomBits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;//                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;_B&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_k&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;modPow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_B&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_N&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;genRandomBits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Now&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
          &lt;span class=&quot;c1&quot;&gt;//                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;_B&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_k&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_g&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;modPow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;_Bstr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// [...]&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To be exact, the random bits for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; (or ‘&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_b&lt;/code&gt;’) were taken from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Random&lt;/code&gt; instance seeded with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(int)DateTime.Now.Ticks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/api/system.datetime.ticks?view=netcore-3.1&quot;&gt;the official C# documentation&lt;/a&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ticks&lt;/code&gt; attribute of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; object contains the number of 100-nanosecond intervals (&lt;em&gt;okay…&lt;/em&gt;) that have elapsed since 0001-01-01 midnight (&lt;em&gt;seriously?&lt;/em&gt;). Also, if used with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime.Now&lt;/code&gt;, this means 0001-01-01 midnight in local time (&lt;em&gt;I am out of sarcastic remarks&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The point is, the server’s secret is based on local time, and it is ticking at a rate of 10_000 intervals per millisecond. If guessed correctly, this server secret &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; can be used to calculate the session key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;K&lt;/code&gt;. Referencing the &lt;a href=&quot;https://forum.kee.pm/t/keepassrpc-technical-detail/2364&quot;&gt;KeePassRPC technical documentation&lt;/a&gt;, this works by first reversing step 2 to determine &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B = kv+g^b =&amp;gt; v = (B - g^b)/k&lt;/code&gt;. Then, an attacker can compute the session key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S&lt;/code&gt; as the host would in step 7: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;S = (Av^u)^b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Guessing this value may seem like a daunting task, but there are a few factors at play that make it possible.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Firstly, KeePassRPC allows for infinite retries. With the processing time for KeePassRPC and local web socket latencies, a few hundred tries per second are possible.&lt;/li&gt;
  &lt;li&gt;Secondly, KeePassRPC also generates a ‘seed’ parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; shortly before creating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; created in the exact same way as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; and is known to the &lt;em&gt;user&lt;/em&gt;. Therefore, an attacker can arrive at a reasonable estimate for the tick used for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; by ‘locally’ finding the tick for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; first. This eliminates many web socket round trips and hash calculations associated with the protocol.&lt;/li&gt;
  &lt;li&gt;Since the timing when generating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; is usually around &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1-3&lt;/code&gt; milliseconds apart, this leaves a few ten-thousand tries for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, my exploit for this vulnerability usually took around 1 minute on a modern desktop PC. The time likely scales strongly with (single-core) CPU speed. In fact, the relationship seems to be quadratic, because slower hardware increases the number of ticks to try as well as the time required to try each one.&lt;/p&gt;

&lt;p&gt;On a final note: with the first vulnerability present, this one is far less relevant for practical purposes. The main point was to show that this aspect of the implementation was vulnerable as well and to make a few interesting observations along the way.&lt;/p&gt;

&lt;h2 id=&quot;disclosure-and-patch&quot;&gt;Disclosure and Patch&lt;/h2&gt;

&lt;p&gt;I disclosed the vulnerability to the vendor in private on July 28th, 2020. The report was acknowledged within 12 hours. Within 24 hours of my initial report, the vendor issued a patch for KeePassRPC (with version 1.12.0 and later 1.12.1 to fix a compatibility problem) and publicly disclosed the vulnerabilities.&lt;/p&gt;

&lt;p&gt;From my understanding, the patch fixes the first vulnerability by throwing an error if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A=0&lt;/code&gt;. The second one is fixed by using a cryptographic number generator instead of a generator seeded by the system time.&lt;/p&gt;

&lt;p&gt;Furthermore, an additional security layer is introduced that should prevent web sites from connecting to KeePassRPC in the first place. This is done by validating the origin of incoming connections against a whitelist of different origins used for browser extensions (for instance &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chrome-extension://&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;timeline&quot;&gt;Timeline&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;2020-07-28 22:00 UTC&lt;/strong&gt; - I &lt;strong&gt;disclose&lt;/strong&gt; the vulnerabilities to the vendor&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;2020-07-29 10:00 UTC&lt;/strong&gt; - Vendor &lt;strong&gt;acknowledges&lt;/strong&gt; the vulnerabilities and lays out a plan to fix and publicly disclose them&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;2020-07-29 17:00 UTC&lt;/strong&gt; - KeePassRPC 1.12.0 is released to &lt;strong&gt;fix&lt;/strong&gt; the vulnerabilities&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;2020-07-29 21:00 UTC&lt;/strong&gt; - Vulnerabilities are &lt;strong&gt;publicly disclosed&lt;/strong&gt; by the vendor&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;2020-08-01 22:00 UTC&lt;/strong&gt; - &lt;strong&gt;This blog post&lt;/strong&gt; is released&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;2020-08-02 11:00 UTC&lt;/strong&gt; - Blog post updated to add details about the disclosure and patch&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Philipp Danzinger</name><email>your-email@email.com</email></author><category term="keepass" /><category term="keepassrpc" /><category term="vulnerability" /><summary type="html">While taking a university course on security, I discovered two critical related vulnerabilities in KeePassRPC, an addon for the popular password manager KeePass. Both vulnerabilities allow a malicious web site to read and leak (unlocked) KeePass databases, while being very hard or impossible to detect, provided the KeePassRPC addon is installed. Shortly after I reported them, the vulnerabilities were patched and publicly disclosed by the developer.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://danzinger.wien/assets/img/exploiting-keepassrpc/preview.jpg" /><media:content medium="image" url="https://danzinger.wien/assets/img/exploiting-keepassrpc/preview.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>