<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>web hacking on Stephen Swanson</title>
    
    
    
    <link>https://stephenswanson.xyz/tags/web-hacking/</link>
    <description>Recent content in web hacking on Stephen Swanson</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <managingEditor>stephen@stephenswanson.xyz (Stephen Swanson)</managingEditor>
    <webMaster>stephen@stephenswanson.xyz (Stephen Swanson)</webMaster>
    <copyright>Stephen Swanson - CC BY 3.0 US.</copyright>
    <lastBuildDate>Mon, 23 May 2022 00:00:00 -0700</lastBuildDate>
    
	<atom:link href="https://stephenswanson.xyz/tags/web-hacking/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>This One Math Trick Makes Banking Easy; Wallet Operators Hate It! - Genesis Wallet: HTB Cyber Apocalypse 2022</title>
      <link>https://stephenswanson.xyz/articles/htb-cyber-apocalypse-2022-genesis-wallet/</link>
      <pubDate>Mon, 23 May 2022 00:00:00 -0700</pubDate>
      <author>stephen@stephenswanson.xyz (Stephen Swanson)</author>
      <guid>https://stephenswanson.xyz/articles/htb-cyber-apocalypse-2022-genesis-wallet/</guid>
      <description>
        
          &lt;img src=&#34;https://stephenswanson.xyz/articles/htb-cyber-apocalypse-2022-genesis-wallet/cover.png&#34;/&gt;
          
        
        
        &lt;blockquote&gt;
&lt;p&gt;To weaken the Golden Fang army, we must cut off their funding of the Genesis coins. Ulysses managed to perform a phishing attack against one of the financial operators of the mercenary and retrieved the login credentials &amp;ldquo;icarus:FlyHighToTheSky&amp;rdquo; for the Genesis wallet. However, the account is protected with 2FA. Can you hack into this renowned intergalactic wallet and move their funds to your account?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sometimes, you know there&amp;rsquo;s a vulnerability in a piece of software that&amp;rsquo;s been patched, and you want to find the vulnerability so you can use it on an unpatched system. This CTF gave me a good opportunity to practice that. There was an unitended solution to the original genesis challenge. The operators patched the problem, but in a brand new challenge, leaving a vulnerable version up. I decided to see if I could reverse engineer the change and find the problem.&lt;/p&gt;
&lt;h2 id=&#34;the-challenge&#34;&gt;The Challenge&lt;/h2&gt;
&lt;p&gt;When we first browse to the page, we&amp;rsquo;re presented with a login/sign in prompt:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;4e0fcb82ed27c553021a061ccbe5f403.png&#34; alt=&#34;4e0fcb82ed27c553021a061ccbe5f403.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;After logging in with our new credentials, we&amp;rsquo;re required to keep track of a totp code:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;8b8b3ad97eb00b9fef6a4a3a6b39c816.png&#34; alt=&#34;8b8b3ad97eb00b9fef6a4a3a6b39c816.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;After saving it, and logging in with our new credentials and one time passcode, we&amp;rsquo;re presented with the main page.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;590495d0eaa9a4dd6600f920b36ec320.png&#34; alt=&#34;590495d0eaa9a4dd6600f920b36ec320.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re able to change our two factor code on the settings page, log out, view incoming and outgoing transactions, but the most important part, at least for us, is being able to send transactions:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f9d6dda1e61837b84b530b56be62b3f4.png&#34; alt=&#34;f9d6dda1e61837b84b530b56be62b3f4.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Based on this information, my guess at the solution was to send something malicious to the &amp;lsquo;icarus&amp;rsquo; user. In order to do that, we need two things: the icarus&#39; address, and some kind of payload.&lt;/p&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;The solution&lt;/h2&gt;
&lt;p&gt;This is the unintended solution, which I got during the competition. A different post will show the intended solution to the patched challenge: Genesis Wallet Redemption.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;a60d8d65393890ab46b6af35bb6fb5e2.png&#34; alt=&#34;a60d8d65393890ab46b6af35bb6fb5e2.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;After grabbing the zip files of the two challenges and putting them into a folder, as shown above, we can extract both of them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ unzip web_genesis_wallet
Archive:  web_genesis_wallet.zip
   creating: web_genesis_wallet
   ...
   
$ unzip web_genesis_wallet_redemption.zip 
Archive:  web_genesis_wallet_redemption.zip
   creating: web_genesis_wallet_redemption/
   ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can use the command &lt;code&gt;diff -r&lt;/code&gt;  to compare these two websites, and see what was changed in the patched version:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;1b92d3bdb70f78bb0287240c93f48080.png&#34; alt=&#34;1b92d3bdb70f78bb0287240c93f48080.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s a little suspicious. It looks like in the patched version, they added a check to prevent someone transfering negative amounts. So theoretically, if we knew icarus&#39; address, we could send them negative money, and drain their account that way.&lt;/p&gt;
&lt;p&gt;Probably the best place to look for the user&amp;rsquo;s address is in the registration flow. First, we look at &lt;code&gt;routes/index.js&lt;/code&gt;, at the &lt;code&gt;/api/register&lt;/code&gt; endpoint:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;nx&#34;&gt;router&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;post&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;/api/register&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;password&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;password&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
			&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
				&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;401&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Account already exists!&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;registerUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;username&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;password&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
					&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;  &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Account registered successfully&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
			&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
			&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Internal server error!&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)));&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;401&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We see that it calls the &lt;code&gt;db.registerUser&lt;/code&gt; function, and so we follow the trail there:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;registerUser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;pass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;reject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
		&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;address&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;crypto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;createHash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;md5&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;update&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;digest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;hex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
			&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;stmt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;prepare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;INSERT INTO users (username, password, address) VALUES ( ?, ?, ?)&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
			&lt;span class=&#34;nx&#34;&gt;resolve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;stmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;pass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;catch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
			&lt;span class=&#34;nx&#34;&gt;reject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
	&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From this, we see that the user&amp;rsquo;s address is nothing more than the md5 hash of their username! We can generate icarus&#39; address using this command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;icarus&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; md5sum
1ea8b3ac0640e44c27b3cb8a258a87f8  -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The -n is necessary to prevent echo from adding a &lt;code&gt;\n&lt;/code&gt; character to the end and spoiling the hash.&lt;/p&gt;
&lt;p&gt;With that wallet address and the vulnerability, we&amp;rsquo;re ready to execute the attack. We go to the Genesis Wallet dashboard, and use the send button to send the address &lt;code&gt;1ea8b3ac0640e44c27b3cb8a258a87f8&lt;/code&gt; &lt;code&gt;-1337GTC&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;7b001f14242b5cceb8b91c0d09e4e941.png&#34; alt=&#34;7b001f14242b5cceb8b91c0d09e4e941.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;The last step is to go to the transactions page and verify the transaction:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;3b5d3a6e089cac22aee8dd0b86a6c439.png&#34; alt=&#34;3b5d3a6e089cac22aee8dd0b86a6c439.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;After the transaction is processed, we just have to go back to the dashboard, and enjoy our newfound wealth, as well as a shiny new flag:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;b1f321f6f176754a4b1276485c3a4a05.png&#34; alt=&#34;b1f321f6f176754a4b1276485c3a4a05.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;If this was interesting at all, helped you with one of your challenges, or if you have any questions or corrections, please drop me a line!&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>Python PIL is Sus - Amidst Us: HTB Cyber Apocalypse 2022</title>
      <link>https://stephenswanson.xyz/articles/htb-cyber-apocalypse-2022-amidst-us/</link>
      <pubDate>Wed, 18 May 2022 00:00:00 -0700</pubDate>
      <author>stephen@stephenswanson.xyz (Stephen Swanson)</author>
      <guid>https://stephenswanson.xyz/articles/htb-cyber-apocalypse-2022-amidst-us/</guid>
      <description>
        
          &lt;img src=&#34;https://stephenswanson.xyz/articles/htb-cyber-apocalypse-2022-amidst-us/4443a8e2360636f3a99d97aec2a8a62a.png&#34;/&gt;
          
        
        
        &lt;blockquote&gt;
&lt;p&gt;The AmidstUs tribe is a notorious group of sleeper agents for hire. We have plausible reasons to believe they are working with Draeger, so we have to take action to uncover their identities. Ulysses and bonnie have infiltrated their HQ and came across this mysterious portal on one of the unlocked computers. Can you hack into it despite the low visibility and get them access?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was a fun challenge, mainly because the correct path was fairly obvious, although exploitation required a little googling. It was great practice for python exploitation.&lt;/p&gt;
&lt;h2 id=&#34;the-challenge&#34;&gt;The Challenge&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re given a web page with amonglings (?) on them, as well as a place to upload a file&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;9c92ee4755c77c68d5593a24abd09dab.png&#34; alt=&#34;9c92ee4755c77c68d5593a24abd09dab.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;We can upload an image, and the page returns the image with the alpha changed to a value that we can specify here:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;2abdcd8225379377f82919f427048239.png&#34; alt=&#34;2abdcd8225379377f82919f427048239.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re also given the complete source code, which shows that this is a python flask app.&lt;/p&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;The Solution&lt;/h2&gt;
&lt;p&gt;From examining the page, we can see that we have one pathway through the code; via the &lt;code&gt;/api/alphafy&lt;/code&gt; endpoint. In a flask app, you can typically find all the routes in a file named &lt;code&gt;routes.py&lt;/code&gt; or something like that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@api&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;route&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;/alphafy&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;methods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;alphafy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_json&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;image&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;abort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This route just calls calls a function called &lt;code&gt;make_alpha&lt;/code&gt; , which we can trace back to the &lt;code&gt;utils.py&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;make_alpha&lt;/code&gt; function is too long to include in it&amp;rsquo;s entirety, but here are a few snippets that are relevant:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;make_alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;background&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;dec_img&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;base64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b64decode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;encode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BytesIO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dec_img&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;RGBA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;img_bands&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;band&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;F&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;band&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()]&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ImageMath&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
            &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;float(
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;				max(
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;				max(
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;					max(
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;					difference1(red_band, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;),
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;					&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# just for syntax highlighting&lt;/span&gt;
					&lt;span class=&#34;c1&#34;&gt;# ...&lt;/span&gt;
					&lt;span class=&#34;c1&#34;&gt;# ...&lt;/span&gt;
					&lt;span class=&#34;c1&#34;&gt;# ...&lt;/span&gt;
			        &lt;span class=&#34;n&#34;&gt;new_image&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;buffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PNG&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;s2&#34;&gt;&amp;#34;image&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;data:image/png;base64,&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base64&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b64encode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;buffer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getvalue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;decode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Examining this function, it looks like the call of &lt;code&gt;ImageMath.eval&lt;/code&gt;  might be interesting. When looking for vulnerabilites, just the word eval in any context is a huge red flag.&lt;/p&gt;
&lt;p&gt;After some Googling, we figure out that something like CVE-2022-22817 might be interesting. Since we have a preliminary thumbs up, we can reach into our standard python bag of tricks and pull out a payload like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;nb&#34;&gt;__import__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;os&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;system&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;cp /flag.txt /app/application/static&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since it seems like the color parameters are evaluated, we can try exploiting the parameters using Burp.&lt;/p&gt;
&lt;p&gt;First, we&amp;rsquo;ll send the api request to the Burp repeater:
&lt;img src=&#34;1049bd722aa2bee6abedcf7ad885d7fc.png&#34; alt=&#34;1049bd722aa2bee6abedcf7ad885d7fc.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then, we&amp;rsquo;ll scroll to the bottom of the request, add our payload, and send it off:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;5472e9a4d14e7389abcb6c631b70c484.png&#34; alt=&#34;5472e9a4d14e7389abcb6c631b70c484.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll see that we get a 400 response, indicating some kind of server error, but let&amp;rsquo;s check and see if we actually copied the flag to the &lt;code&gt;/static&lt;/code&gt; directory:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;dff9c4da6160cd37fada5fb000bc1f98.png&#34; alt=&#34;dff9c4da6160cd37fada5fb000bc1f98.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Boom! We have a working PoC. Time to use it on the actual challenge server!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;697a1366d985e9940b436e02043a4610.png&#34; alt=&#34;697a1366d985e9940b436e02043a4610.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;This time, I&amp;rsquo;m not using the repeater, just the interceptor.&lt;/p&gt;
&lt;p&gt;After adding the exploit, we&amp;rsquo;ll pass it to the challenge server, and check if our exploit worked.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f570cb5ae23e062bf416c4b3051659ac.png&#34; alt=&#34;f570cb5ae23e062bf416c4b3051659ac.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;And we get the flag, solving the challenge and giving us access to the internal networks of the mysterious amonglings!&lt;/p&gt;
&lt;p&gt;If this was interesting at all, helped you with one of your challenges, or if you have any questions or corrections, please drop me a line!&lt;/p&gt;

        
        </description>
    </item>
    
    <item>
      <title>How To Cheat At Wordle</title>
      <link>https://stephenswanson.xyz/articles/how-to-cheat-at-wordle/</link>
      <pubDate>Thu, 24 Mar 2022 00:00:00 -0700</pubDate>
      <author>stephen@stephenswanson.xyz (Stephen Swanson)</author>
      <guid>https://stephenswanson.xyz/articles/how-to-cheat-at-wordle/</guid>
      <description>
        
          &lt;img src=&#34;https://stephenswanson.xyz/articles/how-to-cheat-at-wordle/cover.webp&#34;/&gt;
          
        
        
        &lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I know a fair few people who are playing the &lt;a href=&#34;https://www.nytimes.com/games/wordle/index.html&#34;&gt;New York Time&amp;rsquo;s Wordle&lt;/a&gt;. I&amp;rsquo;m not very good at word games, so I started poking around to see if I could find the answer in my own way, and write a browser extension to do it for me.&lt;/p&gt;


&lt;div class=&#34;notices warning&#34; &gt;&lt;p&gt;Following the guide contained herein is guaranteed to put strain on your friendships with real Wordle players. Only continue if you&amp;rsquo;re willing to brave the consequences.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&#34;the-manual-way&#34;&gt;The Manual Way&lt;/h3&gt;
&lt;p&gt;It turns out that unlike some other Wordle-inspired games, the NYT Wordle just keeps the solution in the browser&amp;rsquo;s local storage, so the process for cheating looks something like this:&lt;/p&gt;


&lt;div class=&#34;notices note&#34; &gt;&lt;p&gt;I&amp;rsquo;m using Firefox here. You may have to modify the steps here if you&amp;rsquo;re using a different browser.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;First, go into the Firefox tool bar and select &amp;ldquo;More Tools&amp;rdquo;:&lt;/p&gt;

  &lt;img src=&#34;open-more-tools.webp&#34;  alt=&#34;Opening more tools in Firefox&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;  /&gt;


&lt;p&gt;Next, open the Firefox web developer tools:&lt;/p&gt;

  &lt;img src=&#34;open-dev-tools.webp&#34;  alt=&#34;Opening the Firefox web developer tools&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;  /&gt;


&lt;p&gt;Then, click &amp;ldquo;Storage&amp;rdquo;, then click &amp;ldquo;Local Storage&amp;rdquo;, then click &amp;ldquo;&lt;a href=&#34;https://nytimes.com&#34;&gt;https://nytimes.com&lt;/a&gt;&amp;rdquo;.&lt;/p&gt;

  &lt;img src=&#34;browse-local-storage.webp&#34;  alt=&#34;Finding the New York Times local storage entry&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;  /&gt;


&lt;p&gt;The solution will be in the long string on the right:&lt;/p&gt;

  &lt;img src=&#34;found-solution.webp&#34;  alt=&#34;Finding the solution to the Wordle&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;  /&gt;


&lt;h3 id=&#34;the-fun-way&#34;&gt;The Fun Way&lt;/h3&gt;
&lt;p&gt;After figuring out the above, I decided to write a little browser extension to automatically pull the solution from local storage for me. The extension is called Robotle, and it&amp;rsquo;s on my &lt;a href=&#34;https://gitlab.com/ArchWizard101/robotle&#34;&gt;Gitlab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s Robotle in action:

  &lt;img src=&#34;robotle.webp&#34;  alt=&#34;Robotle solving the wordle&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;  /&gt;

&lt;/p&gt;
&lt;p&gt;Robotle currently only works on the NYT wordle, and only supports Firefox. Maybe someday if the mood strikes me, I&amp;rsquo;ll extend him and make a more universal Wordle cheating tool.&lt;/p&gt;

        
        </description>
    </item>
    
  </channel>
</rss>