<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>SQroot.eu</title>
    <description>A personal engineering blog</description>
    <link>https://sqroot.eu/</link>
    <atom:link href="https://sqroot.eu/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Mon, 28 Dec 2020 21:50:21 +0200</pubDate>
    <lastBuildDate>Mon, 28 Dec 2020 21:50:21 +0200</lastBuildDate>
    <generator>Jekyll v4.2.0</generator>
    
      <item>
        <title>Puzzle box Christmas gift</title>
        <description>&lt;p&gt;Here’s a gift box I built for this Christmas. A wooden box, locked with a combination lock. To get the code of the lock (and the gift inside),
one has to get the box open… somehow… without knowing the lock combination.&lt;/p&gt;

&lt;h2 id=&quot;why-do-this&quot;&gt;Why do this&lt;/h2&gt;

&lt;p&gt;I wanted to make obtaining the gift just a bit challenging - this would make the reward more satisfying. Idea of a locked box w/ combination
lock fit well, as making a puzzle to disclose a password is doable enough. Oddly, I couldn’t find a small lockable box from local nor
online stores, so I built one.&lt;/p&gt;

&lt;h2 id=&quot;the-build&quot;&gt;The build&lt;/h2&gt;

&lt;p&gt;I’m no woodworker, and did this in the living room, with limited tooling available. The build is rough.
I discovered plenty of small tips how to make my next box cleaner, but that’s for another time.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/1.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/1.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/2.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/2.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/2.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/2.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/2.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/3.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/3.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/3.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/3.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/3.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/4.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/4.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/4.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/4.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/4.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/5.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/5.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/5.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/5.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/5.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) I started by cutting a length of 90cm x 2cm x 100cm pine board into ~15cm pieces, fitting the pieces together into a box, then sanding the edges.
Box lid was made of a bit larger and thicker pine. A heavier lid was needed in order to fit the loops for the lock without splitting the wood, but was a mistake in retrospect,
as this took the center of gravity for the box too high - it would tip over when empty and open.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/6.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/6.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/6.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/7.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/7.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/7.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/7.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/7.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) I pained the inside with an oil-based glossy dark brown wood oil, and the outside with water-based dark brown wood pigment. The pieces are glued together
with wood glue.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/8.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/8.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/8.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/8.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/8.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/9.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/9.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/9.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/9.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/9.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) I wanted to engrave a name into the lid of the box. First attempt of this did not look nice - the text was very small, and I used a regular drill to
engrave the wood. The drill was too big for the too-small letters. Result was sloppy-looking (if artistic), uneven edges, with some of the “freestanding” bits in letters like R (the middle outcrop) breaking off.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/10.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/10.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/10.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/10.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/10.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/11.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/11.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/11.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/11.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/11.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/12.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/12.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/12.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/12.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/12.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/13.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/13.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/13.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/13.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/13.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) I got a better drill meant for sideways engraving from the hardware store, and used bigger letters with more straight edges (no freestanding bits) - result looked much better.
I filled the engraved letterings with white filler meant for fixing indents in wood, then let it dry and sanded the top. The result - nicely freestanding, filled out lettering.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/14.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/14.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/14.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/14.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/14.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/15.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/15.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/15.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/15.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/15.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) I attached small brass hinges to the backside of the box.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/16.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/16.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/16.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/16.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/16.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) Finishing touches - fully oiled and attaching front-facing loops for the lock. Sadly, I had to forgo adding a box-lid inlay piece, as this would have messed up the center of balance even further.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/24.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/24.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/24.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/24.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/24.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/25.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/25.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/25.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/25.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/25.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/26.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/26.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/26.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/26.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/26.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) The box is complete. There are plenty of areas where I knew I could do better (paint drips, uneven sanding, balance and weight…), but as this was my very first box and the point
wasn’t to get it perfect, I let it be. Regardless, the final result looks rather nice.&lt;/p&gt;

&lt;h2 id=&quot;guess-the-code&quot;&gt;Guess the code&lt;/h2&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/21.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/21.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/21.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/21.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/22.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/22.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/22.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/23.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/23.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/23.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) The box would go under the Christmas tree locked with a combination lock.
In the box would also be a sheet with Maths tasks as well as a &lt;a href=&quot;https://www.rahvaraamat.ee/p/matemaatika-valemeid/29049/et?isbn=9789985025901&quot;&gt;formula book&lt;/a&gt;.
In order to open the box, you’d need to solve the math.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/17.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/17.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/17.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/17.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/17.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/18.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/18.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/18.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/18.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/18.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/27.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/27.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/27.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/27.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/27.png&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/gift-box/19.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/gift-box/19.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/gift-box/19.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/gift-box/19.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/gift-box/19.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;(above) I took the Maths problems from Estonian national Maths exam for high-schoolers, from last year
(see: &lt;a href=&quot;https://www.innove.ee/eksamid-ja-testid/riigieksamid/riigieksamite-materjalid/&quot;&gt;Math exam problems and answers for 2019 year&lt;/a&gt;).
I picked problems that were relatively easy to solve, and also tested them on friends - the goal was to offer a slightly complex challenge, but not to frustrate people.&lt;/p&gt;

&lt;p&gt;Solving all three problems would give you the three-digit combination of the lock; and you’d be able to open the box.&lt;/p&gt;

&lt;h2 id=&quot;ways-to-open-the-box&quot;&gt;Ways to open the box&lt;/h2&gt;

&lt;p&gt;Having learned from &lt;a href=&quot;/2017/girlfriend-puzzle&quot;&gt;Girlfriend Puzzle&lt;/a&gt;, I wanted to make it possible to open the box in multiple different ways.
Again - to avoid frustration. The point wasn’t so much to solve the Maths puzzles, but to think outside the box (pun intended) and &lt;em&gt;hack it&lt;/em&gt;
&lt;em&gt;(yes - I’m deviously trying to get the hacker mindset into gf)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These were the different ways how to get into the box:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Solve all three Maths problems and get the combination&lt;/li&gt;
  &lt;li&gt;There are 3 problems on the assignment sheet, each one giving X points (listed).
Realize the numbers of points for the three tasks are actually individual numbers in the lock combination. Permute and open the lock.&lt;/li&gt;
  &lt;li&gt;Top and footer of the assignment sheet has, in faint letters the text: “Some SECRETS are only visible by candlelight”.
Realize this means invisible ink - I wrote the combination to the paper with lemon juice. Heating the paper would yield the answer.&lt;/li&gt;
  &lt;li&gt;Unscrew back hinges (I left hinges on the outside on purpose)&lt;/li&gt;
  &lt;li&gt;Unscrew front lock loops (requires Torx screw head - on purpose)&lt;/li&gt;
  &lt;li&gt;Use online tools (Wolfram Alpha) to solve the Maths problems&lt;/li&gt;
  &lt;li&gt;Google the text of the assignments, discover it’s from national exams - with answer sheet included&lt;/li&gt;
  &lt;li&gt;Ask friends and family to help with solving Maths (distributed computing)&lt;/li&gt;
  &lt;li&gt;Outright guess the combination (it’s a significant, guessable number - a &lt;em&gt;terrible&lt;/em&gt; password)&lt;/li&gt;
  &lt;li&gt;Physically break the box&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-it-played-out&quot;&gt;How it played out&lt;/h2&gt;

&lt;p&gt;The box was opened via a combination of brute-forcing and solving Maths - friends and family helped to solve most of the Maths problems, getting the answer “900”.
As there were only 99 possible other combinations, they were brute-forced without solving the last Maths problem, and the box was opened.&lt;/p&gt;

&lt;p&gt;Overall, the present-puzzle was a success, and - I think - the gift was appreciated.&lt;/p&gt;

&lt;p&gt;Ho-ho-ho =)&lt;/p&gt;

</description>
        <pubDate>Wed, 23 Dec 2020 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2020/puzzle-box-christmas-gift</link>
        <guid isPermaLink="true">https://sqroot.eu/2020/puzzle-box-christmas-gift</guid>
        
        
        <category>Projects</category>
        
      </item>
    
      <item>
        <title>eCoop open redirect and XSS on login page</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://ecoop.ee&quot;&gt;eCoop&lt;/a&gt;, an Estonian food retailer, had two vulnerabilities on their login page. Both were responsibly disclosed and fixed by the vendor.&lt;/p&gt;

&lt;p&gt;When unauthenticated users visit the online e-store and try to access a feature intended for authenticated users, they are shown a login page.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/ecoop/login-page.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/ecoop/login-page.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/ecoop/login-page.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/ecoop/login-page.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/ecoop/login-page.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The URL of the login page (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=%2Fet%2Fostunimekirjad%2F&lt;/code&gt;) has a query parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt;,
which is intended for user convenience - you get redirected to the subpage you were trying to access after login.&lt;/p&gt;

&lt;p&gt;However, the frontend code in charge of using this parameter didn’t validate the value, and it was possible to misuse it for two abuse cases.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?next=&lt;/code&gt; query parameter is an urlencoded value of an URI path in the same frontend application (React router path),
with expected values like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%2Fet%2Fostunimekirjad%2F&lt;/code&gt; (decoded: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/et/ostunimekirjad/&lt;/code&gt;).&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/ecoop/router.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/ecoop/router.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The application tries to redirect to this path after the “Login” button is pressed.&lt;/p&gt;

&lt;h1 id=&quot;open-redirect&quot;&gt;Open redirect&lt;/h1&gt;

&lt;p&gt;It was possible to feed a full URI value to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; parameter, hence redirecting the visitor out from the original eCoop website
after they attempted a login. The frontend code did not validate that the passed value would be a subpage of the current site.&lt;/p&gt;

&lt;p&gt;PoC: Phishing e-mail from “Coop” with a link to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=%2F%2Fekoop.ee&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//ekoop.ee&lt;/code&gt; with two slashes - external (currently unclaimed) domain).
Users would try to login on a legitimate site, but get redirected to a phishing site after the first login attempt.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/ecoop/open-redirect.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/ecoop/open-redirect.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/ecoop/open-redirect.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/ecoop/open-redirect.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/ecoop/open-redirect.png&quot; /&gt;
&lt;/picture&gt;

&lt;h1 id=&quot;reflected-xss&quot;&gt;Reflected XSS&lt;/h1&gt;

&lt;p&gt;It was also possible to abuse the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; query parameter to execute JavaScript in the context of the site. This could be done, because it was possible
to specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;javascript&lt;/code&gt; as the link protocol.&lt;/p&gt;

&lt;p&gt;PoC: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=javascript%3Aalert(1)&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;javascript:alert(1)&lt;/code&gt;). A maliciously crafted link could be sent to a user, with the payload encoded
in the URL. The payload would execute once the victim pressed “log in”, and run arbitrary JavaScript in the context of the eCoop site.&lt;/p&gt;

&lt;p&gt;eCoop session cookie is marked as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;httpOnly&lt;/code&gt;, but the site has no Content Security Policy in place to protect against it. The payload could include additional scripts,
modify the content of the site, read out user-entered username/password, or phish for more information - all the while using the percieved legitimacy of the trusted domain/brand.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/ecoop/xss.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/ecoop/xss.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/ecoop/xss.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/ecoop/xss.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/ecoop/xss.png&quot; /&gt;
&lt;/picture&gt;

&lt;h1 id=&quot;the-fix&quot;&gt;The fix&lt;/h1&gt;

&lt;p&gt;eCoop fixed the issue 16 months after initial disclosure. The fix involved adding a frontend validator for the value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; parameter, checking it against
a whitelist of all internally set React Routes.&lt;/p&gt;

&lt;div class=&quot;language-javascript 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;// ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&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;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;componentWillMount&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;query&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;validateRedirectPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
                &lt;span class=&quot;na&quot;&gt;socialLoginErrors&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attachError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;activeLanguage&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;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;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;validateRedirectPath&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;whitelistedRedirectPaths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;r&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;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;u&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Invalid redirect path!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&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;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_getWhitelistedRedirectPaths&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;t&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;childRoutes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&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;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The fix appears effective, as both PoC-s now fail.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/ecoop/fix1.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/ecoop/fix1.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/ecoop/fix1.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/ecoop/fix1.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/ecoop/fix1.png&quot; /&gt;
&lt;/picture&gt;

&lt;h1 id=&quot;appendix-timeline&quot;&gt;Appendix: Timeline&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;2019-04-04 Initial discovery&lt;/li&gt;
  &lt;li&gt;2019-04-04 No security / IT contact (or responsible disclosure/&lt;a href=&quot;https://securitytxt.org/&quot;&gt;security.txt&lt;/a&gt;) found for eCoop, wrote to customer support for an IT contact&lt;/li&gt;
  &lt;li&gt;2019-04-05 Received contact e-mail of E-Services Development Manager&lt;/li&gt;
  &lt;li&gt;2019-04-07 &lt;a href=&quot;https://en.wikipedia.org/wiki/Responsible_disclosure&quot;&gt;Responsible disclosure&lt;/a&gt; to Coop about both problems, with full PoC \ explanation&lt;/li&gt;
  &lt;li&gt;2019-04-08 Acknowledgment of receipt from Coop’s E-Services Development Manager; PoC forwarded to development team&lt;/li&gt;
  &lt;li&gt;2019-11-25 Escalation: disclosure to CERT-EE (CC Coop); as nothing had happened yet - bug still live. No response form either party&lt;/li&gt;
  &lt;li&gt;2020-03-12 Escalation: contact Coop ISO directly for an update (CC original report contents)&lt;/li&gt;
  &lt;li&gt;2020-03-12 ISO replies: acknowledgment that issue was known internally since initial report; remediation plan had been made (switch to a new technical e-store platform), but implementation delayed&lt;/li&gt;
  &lt;li&gt;2020-08-04 ISO notifies that the issue has been fixed in the current production system&lt;/li&gt;
  &lt;li&gt;2020-08-05 Verified fix (a whitelist validator had been added; protects against both PoC-s), can see no obvious bypass - issue fixed&lt;/li&gt;
  &lt;li&gt;2020-08-05 Public disclosure&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;appendix-disclosure-e-mail&quot;&gt;Appendix: Disclosure e-mail&lt;/h1&gt;

&lt;p&gt;Tere&lt;/p&gt;

&lt;p&gt;Kirjutan Teile kui e-arendusjuhile heas usus, et &lt;a href=&quot;https://en.wikipedia.org/wiki/Responsible_disclosure&quot;&gt;responsible disclosure&lt;/a&gt; raames teada anda Coop e-poest leitud XSS + open redirect turvaveast.
Teadaolevalt ei ole neid veel halvasti ära kasutatud, ning see teavitus võimaldab Teil vead parandada, muutes Coop keskkonna klientidele (sh minule) turvalisemaks.&lt;/p&gt;

&lt;p&gt;(Kirjutan otse Teile, kuna ei suutnud ecoop.ee kodulehelt leida turvaküsimusteks otsekontakti, ning ecoop.ee ei kasuta &lt;a href=&quot;https://securitytxt.org/&quot;&gt;security.txt&lt;/a&gt; standardit).&lt;/p&gt;

&lt;p&gt;Leitud haavatavused on järgnevad.&lt;/p&gt;

&lt;h2 id=&quot;open-redirect-1&quot;&gt;Open redirect&lt;/h2&gt;

&lt;p&gt;Rakenduse aktsepteerib sisselogimisel URL parameetrit “next”. Näiteks, kui sisselogimata külastaja vajutab peamenüü lingile “Ostunimekirjad”, suunatakse ta edasi “Sisene eCoopi” lehele, kusjuures lehe URL on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=%2Fet%2Fostunimekirjad%2F&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Aadressi vaadates märgati, et &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; parameeter sisaldab URI segmenti ja on ilmselt haavatav &lt;a href=&quot;https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md&quot;&gt;open redirect&lt;/a&gt; turvaveale: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; parameetri väärtus on muudetav ning võib näidata suvalisele URL-ile - mispeale rakendus ka peale sisselogimist sinna suunab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PoC:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=%2F%2Fneti.ee&lt;/code&gt; (peale sisselogimist suunatakse ümber neti.ee veebilehele)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Probleem:&lt;/strong&gt; rakendus ei valideeri &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; parameetri väärtust ning suunab ka välistele domeenidele.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Väärkasutus (näide #1):&lt;/strong&gt; Kliendile saadetakse link stiilis &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=%2F%2Fekoop.ee%2Fet%2Flogisisse&lt;/code&gt;; näiteks phishing-uudiskirjaga. Kirjas olev link on õigele domeenile, ning klient usaldab seda. Peale sisselogimist suunab süsteem aga edasi phishing veebilehele, mis asub hoopis teisel domeenil, ning väidab, et sisselogimine ebaõnnestus, palun sisestada parool uuesti. Klient ei märka domeeni muutust, ning annab kolmandale osapoolele oma parooli.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kaitse:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md#preventing-unvalidated-redirects-and-forwards&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kriitilisus:&lt;/strong&gt; Madal&lt;/p&gt;

&lt;h2 id=&quot;reflected-xss-via-get-uri&quot;&gt;Reflected XSS via GET URI&lt;/h2&gt;

&lt;p&gt;Kasutades sama &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; URL parameetrit sisselogimislehel, on võimalik ecoop keskkonnas käivitada JavaScript koodi. See on nn “Reflected XSS” haavatavus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Probleem:&lt;/strong&gt; Rakendus käivitab next parameetri väärtust kui JavaScript koodi, kasutaja browseri kontekstis - XSS&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PoC:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://ecoop.ee/et/logisisse/?next=javascript:window.location.href%3D%27%2F%2Flocalhost%2F%27%2Bdocument.getElementById(%27tfid-84-1%27).value&lt;/code&gt; (peale sisselogimist suunatakse ümber teisele domeenile localhost, kusjuures kliendi parool on tekstina URL-is)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Väärkasutus (näide #1):&lt;/strong&gt; Kliendile saadetakse phishing kirjaga link Coop e-poodi. Kirjas olev link on õigele domeenile, ning klient usaldab seda. Link viib sisselogimislehele. Kui klient vajutab “Logi sisse”, käivitub &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; parameetris olev JavaScript kood, mis võtab kliendi poolt täidetud parooli väljast (enne ümbersuunnamist!) parooli väärtuse, ning saadab selle kolmandale osapoolele, kompromiteerides nõnda kliendi sisselogimisandmed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kaitse:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kriitilisus:&lt;/strong&gt; Keskmine&lt;/p&gt;

&lt;p&gt;Palun vastust, kinnitamaks raporti kättesaamist ning võimalusel ka indikatiivset aega, millal mainitud vead parandatakse (tüüpiliselt parandatakse turvavead maksimaalselt 90 päeva jooksul).&lt;/p&gt;
</description>
        <pubDate>Tue, 04 Aug 2020 00:00:00 +0300</pubDate>
        <link>https://sqroot.eu/2020/ecoop-xss-on-login-page</link>
        <guid isPermaLink="true">https://sqroot.eu/2020/ecoop-xss-on-login-page</guid>
        
        
        <category>Security</category>
        
      </item>
    
      <item>
        <title>Buspad kiosk breakout</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.luxexpress.eu/en/&quot;&gt;Lux Express&lt;/a&gt; is a transportation company that operates bus lines in the Baltic region.
In their fleet of more modern buses, they offer each passenger
an in-seat Android multimedia tablet, running in kiosk (restricted) mode. The tablet runs a full-screen custom application,
that has menu items for common entertainment options like a web browser, movies and music.&lt;/p&gt;

&lt;p&gt;Due to misconfiguration of the tablet, it’s possible to exit this kiosk mode and get full user-level control of the tablet.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/1.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/1.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The welcome screen of the pad is the in-kiosk activity menu: watch movies, browse the web. The kiosk is running in full-screen,
with no apparent exit button (there is an exit “app” hidden away in the games section, but it requires a password).&lt;/p&gt;

&lt;p&gt;The design goal here seems (rightfully) that random travellers should only be allowed to use the tablet in kosk mode, to entertain,
but not reconfigure the tablet or install any apps.&lt;/p&gt;

&lt;h2 id=&quot;buspad-kiosk-breakout---steps&quot;&gt;Buspad kiosk breakout - steps&lt;/h2&gt;

&lt;p&gt;Here’s how to break out of the full-screen kiosk app and access Android settings. This is not hacking per se, as everything required
is exposed/allowed/enabled by the tablet in it’s current configuration. As of 2020-03-22, the tablets should still be vulnerable.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/2.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/2.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/2.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/2.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/2.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Select “internet” from the kiosk welcome screen. Navigate to any web page.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/3.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/3.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/3.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/3.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/3.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Select a word or a phrase on the web page. In Android, selecting text is done by long-pressing on a word. Choose “SHARE” from top-right.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wikipedia warns us that we are using an old and unsupported browser that will stop working soon. I wonder if this is a nudge to prod operators into finally updating it.&lt;/em&gt;&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/4.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/4.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/4.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/4.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/4.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Android sharing menu opens. In your phone, you’d have a bunch of apps like Twitter or Notes there as a sharing target. We are interested in the Google (launcher) app.
Select it as share target.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/5.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/5.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/5.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/5.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/5.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The kiosk app moves to the background and we’re now in the context of the Google app. There’s a meta-search-launcher bar on top, where you can search and launch other apps on the
tablet - including apps not listed in the restricted kiosk view. We’re now effectively out of the kiosk.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/6.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/6.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/6.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/6.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/6.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Launch ApkInstaller app. This seems to be a custom thing designed for sideloading new apps to the device, as by default, it isn’t running the Google Play app installer.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/7.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/7.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/7.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/7.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/7.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;We’re offered the choice to manage existing apps, or to add a new app.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/7.1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/7.1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/7.1.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/7.1.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/7.1.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Select to install a new app; and USB memory as the install source.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/8.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/8.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/8.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/8.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/8.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Insert a USB drive into the front-facing USB port of the device. USB should contain .apk file to install.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/9.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/9.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/9.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/9.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/9.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;From the ApkInstaller, find your .apk file from the USB and choose to install it.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/10.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/10.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/10.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/10.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/10.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Android default apk policy applies - sideloading apps is not allowed.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/11.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/11.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/11.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/11.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/11.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Use pad “back” buttons to exit back to the in-kiosk web browser. Launch Google app again; and from there, launch the Settings app.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/12.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/12.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/12.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/12.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/12.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Go to Security and disable “Verify apps” setting.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/13.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/13.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/13.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/13.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/13.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Try to install .apk file again; this time it succeeds.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/14.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/14.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/14.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/14.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/14.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Installed app (Terminal Emulator) is visible from apps list.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/15.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/15.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/15.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/15.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/15.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Launch the newly installed app (web -&amp;gt; share -&amp;gt; Google -&amp;gt; search). You’re now out of the kiosk and launched an app of your
choice - be it file explorer, terminal or anything else.&lt;/p&gt;

&lt;h2 id=&quot;analysis&quot;&gt;Analysis&lt;/h2&gt;

&lt;p&gt;Properly kiosking of things is hard; people have been breaking out of kioskes &lt;a href=&quot;https://securityriskadvisors.com/blog/sitekiosk-breakout/&quot;&gt;for a&lt;/a&gt;
&lt;a href=&quot;https://blog.kiosksimple.com/2014/11/26/a-guide-to-hacking-kiosk-applications/&quot;&gt;long&lt;/a&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=kRFNYws1FF0&quot;&gt;time&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this instance, kiosk breakout was possible, because:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Android default text context-action was enabled (selecting / sharing text)&lt;/li&gt;
  &lt;li&gt;A launcher app (Google) was present and installed on the device and available as a share target&lt;/li&gt;
  &lt;li&gt;Device had ApkInstaller present and launchable&lt;/li&gt;
  &lt;li&gt;Front-facing USB port had data lines enabled; and Android user had permission to use it as mass-media device&lt;/li&gt;
  &lt;li&gt;New app installation was possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Advise for fixing this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Upgrade Android versions, if possible. If hardware doesn’t support newer Android, consider upgrading the hardware also. It will cost, but
these devices were installed (based on the Android version present) in 2012. Enterprises typically have an amortization time of 4…5 years for these types of devices&lt;/li&gt;
  &lt;li&gt;Demand more quality from the pad’s software-development partner. The pad has numerous quality (UI/UX) issues,
but also quite rich attack surface and security misconfigurations&lt;/li&gt;
  &lt;li&gt;Contract software partner to provide periodic (~2 times a year) software updates to the pads. This means Android version updates + version updates
(security patches) to all the software running on it (the tablet has Flash 11.1 installed, released in… 2012)&lt;/li&gt;
  &lt;li&gt;Have monitoring and alerts for the pads. If some pad launches system settings app or installs new apps - unusual, unexpected behavior - someone
should know; and look into it. I’m fairly certain no human-noticed logs or alerts were triggered from the above activity&lt;/li&gt;
  &lt;li&gt;Disable front-facing USB port for data access. At least deny the tablet user to access it. Percentage of users who would find a valid use-case for it is extremely low,
but vulnerability it opens - not so low&lt;/li&gt;
  &lt;li&gt;Remove APKInstaller from device, if possible&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;other-observations&quot;&gt;Other observations&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Android version is Jelly Bean (released in Feb 2013) - this as reached end of life long ago&lt;/li&gt;
  &lt;li&gt;The tablet and software installed there is quite old (2012) - I don’t think it has received any meaningful updates since then&lt;/li&gt;
  &lt;li&gt;It’s possible to export installed .apk-s out of the device&lt;/li&gt;
  &lt;li&gt;The custom kiosk app is poorly written. In many, many, many ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/settings.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/settings.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/settings.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/settings.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/settings.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2020/buspad/versions.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2020/buspad/versions.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2020/buspad/versions.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2020/buspad/versions.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2020/buspad/versions.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;h2 id=&quot;possible-misuses&quot;&gt;Possible misuses&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Install keyloger (log everything being typed by next travellers). Imagine if a traveller decides to log in to their Facebook or an internet bank…&lt;/li&gt;
  &lt;li&gt;Install mic / camera recorder apps (listen in on conversations) &lt;em&gt;(not sure if camera and mic are physically installed to the tablets)&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Install generic malware (botnet node; (very slow) cryptocurrency miner)&lt;/li&gt;
  &lt;li&gt;Track the location of the bus&lt;/li&gt;
  &lt;li&gt;Take screenshots of the tablet (if someone has logged into any account…)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;advise-to-travelers&quot;&gt;Advise to travelers&lt;/h2&gt;

&lt;p&gt;The purpose of this public disclosure is to warn travelers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Do not trust the tablet - you didn’t provision it; you now know it isn’t properly locked; and you don’t know what previous travelers have done with it&lt;/li&gt;
  &lt;li&gt;Absolutely &lt;strong&gt;do not&lt;/strong&gt; enter any sensitive data to the tablet. No logging in to Facebook; no logging in to your internet bank&lt;/li&gt;
  &lt;li&gt;Use the tab only for entertainment - read news, watch movies&lt;/li&gt;
  &lt;li&gt;Do not have sensitive conversations in the bus&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
  &lt;li&gt;2019-12 Initial discovery&lt;/li&gt;
  &lt;li&gt;2019-12-14 Responsibly disclosed to &lt;a href=&quot;https://cert.ee&quot;&gt;CERT-EE&lt;/a&gt; and Lux Express - no response from Lux Express, autoreply from CERT&lt;/li&gt;
  &lt;li&gt;2020-03-15 2nd disclosure to Lux Express (alternative e-mail - general info contact - no response)&lt;/li&gt;
  &lt;li&gt;2020-03-22 Public disclosure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=vmWXtDtKD9k&quot;&gt;https://www.youtube.com/watch?v=vmWXtDtKD9k&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://riia.luxexpress.eu/en/onboard-media-content&quot;&gt;https://riia.luxexpress.eu/en/onboard-media-content&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://igra.luxexpress.eu/et/uued-bussid-liinil-tallinn-stpetersburg&quot;&gt;https://igra.luxexpress.eu/et/uued-bussid-liinil-tallinn-stpetersburg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 22 Mar 2020 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2020/buspad-kiosk-bypass</link>
        <guid isPermaLink="true">https://sqroot.eu/2020/buspad-kiosk-bypass</guid>
        
        
        <category>Security</category>
        
      </item>
    
      <item>
        <title>Secure Christmas</title>
        <description>&lt;p&gt;I received solstice greetings via snail-mail from fellow security engineers in &lt;a href=&quot;https://bigbank.eu&quot;&gt;Bigbank&lt;/a&gt;, guys I used to work with.
Only, when ethical hackers send messages, they send them… securely.&lt;/p&gt;

&lt;p&gt;The outer envelope was marked as registered mail. Inside:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Security stickers, because, obviously&lt;/li&gt;
  &lt;li&gt;A merry fir tree card
    &lt;ul&gt;
      &lt;li&gt;…but you had to enable macros to get it to show&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Security envelope, properly sealed with a security seal
    &lt;ul&gt;
      &lt;li&gt;Inside, an USB drive&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/package.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/package.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/secure-christmas/package.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/secure-christmas/package.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/package.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;h2 id=&quot;usb-teardown&quot;&gt;USB teardown&lt;/h2&gt;

&lt;p&gt;The USB drive was named “&lt;a href=&quot;https://en.wikipedia.org/wiki/Nimda&quot;&gt;nimda&lt;/a&gt;” (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__&amp;lt;&amp;lt;admin&lt;/code&gt; - RTL override?) and contained &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;insecurity.png&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~/tmp » &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lh&lt;/span&gt;
total 867M
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 ando ando 867M dets  17 12:34 insecurity.png

~/tmp » &lt;span class=&quot;nb&quot;&gt;stat &lt;/span&gt;insecurity.png 
  File: insecurity.png
  Size: 908809605 	Blocks: 1775032    IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 1447295     Links: 1
Access: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0644/-rw-r--r--&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;  Uid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; 1000/    ando&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;   Gid: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; 1000/    ando&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Access: 2018-12-20 18:28:02.900991000 +0200
Modify: 2018-12-17 12:34:24.000000000 +0200
Change: 2018-12-20 18:28:02.202816787 +0200
 Birth: -

~/tmp » file insecurity.png 
insecurity.png: PNG image data, 300 x 300, 8-bit colormap, non-interlaced
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, it is (actually) a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;300x300px&lt;/code&gt; .PNG image. The obvious question though - WTF is up with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;867M&lt;/code&gt; file size?
Interestingly, Nautilus had no problems displaying the thumbnail.&lt;/p&gt;

&lt;picture&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/png-thumb.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;It’s my avatar.&lt;/p&gt;

&lt;p&gt;Maybe the guys used &lt;a href=&quot;https://www.w3.org/TR/PNG/#11textinfo&quot;&gt;PNG metadata&lt;/a&gt; to hide a hidden message or artificially
enlarge the file size? &lt;a href=&quot;/content/2018/secure-christmas/metadata.txt&quot;&gt;Let’s inspect&lt;/a&gt; with&lt;/p&gt;

&lt;div class=&quot;language-bash 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;nv&quot;&gt;$ &lt;/span&gt;identify &lt;span class=&quot;nt&quot;&gt;-verbose&lt;/span&gt; insecurity.png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Seems like not. What about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hexdump&lt;/code&gt;, this should give an indication of what’s actually there…&lt;/p&gt;

&lt;div class=&quot;language-bash 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;nv&quot;&gt;$ &lt;/span&gt;hexdump &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; insecurity.png &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 90000 | less
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/png-hex1.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/png-hex1.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/secure-christmas/png-hex1.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/secure-christmas/png-hex1.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/png-hex1.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The file starts with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.png&lt;/code&gt; image, as expected. This is why Nautilus was able to render the thumbnail.
However, scrolling down, we see that at one point not far into the file, the file ends with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IEND&lt;/code&gt; marker, which &lt;a href=&quot;https://www.w3.org/TR/PNG/#11IEND&quot;&gt;according to .PNG specification&lt;/a&gt;,
“marks the end of the PNG datastream”.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/png-hex2.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/png-hex2.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/png-hex2.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;What follows makes it clear why the file was so large.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/png-hex3.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/png-hex3.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/png-hex3.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The guys have hidden the latest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.iso&lt;/code&gt; of Kali Linux into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.PNG&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Have you ever thought how to hide your hacking distros? An image* will do.&lt;/p&gt;

&lt;h2 id=&quot;card-teardown&quot;&gt;Card teardown&lt;/h2&gt;

&lt;p&gt;The printed-out card they sent had two sides: one Word document, directing the user to
enable content, the other wishing merry Christmas.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/macros.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/macros.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/secure-christmas/macros.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/secure-christmas/macros.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/macros.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/card.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/card.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Most people don’t know this, but whenever you print something with a color printer, the printer
&lt;a href=&quot;https://en.wikipedia.org/wiki/Machine_Identification_Code&quot;&gt;embeds tiny tracking&lt;/a&gt;
&lt;a href=&quot;http://seeingyellow.com/&quot;&gt;fingerprints in the paper&lt;/a&gt;, in yellow color.
You won’t be able to see it with a naked eye, but in case it’s ever needed,
this marker will be able to identify from which printer a particular paper came from.
This is how they were able to &lt;a href=&quot;https://mashable.com/2017/06/06/printer-dots-nsa-leak&quot;&gt;identify a whistleblower in NSA&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see if the markers (or any other hidden messages) are present in the card.&lt;/p&gt;

&lt;p&gt;We’ll start by taking a high-resolution scan (best quality possible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;600dpi&lt;/code&gt;) of the paper.&lt;/p&gt;

&lt;p&gt;The resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.PDF&lt;/code&gt; can be opened in Gimp.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/gimp.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/gimp.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/gimp.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Using the color Channels dialog, we’ll hide the Red and Green color channels, leaving only the blue.
And zoom in.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/secure-christmas/gimp2.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/secure-christmas/gimp2.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/secure-christmas/gimp2.png&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/secure-christmas/gimp2.png&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/gimp2.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Looking closely, we can see tiny black dots with the same pattern, distributed across the page.
Zooming in on one of them gives us the unique fingerprint of the printer in questions.&lt;/p&gt;

&lt;picture&gt;
    
    &lt;img src=&quot;/content/2018/secure-christmas/printer-fingerprint.png&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;So, if you ever receive printouts with the same fingerprint, you know it came from their printer.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;All-in-all, an excellent hackish solstice wish. Thanks, guys!&lt;/p&gt;

&lt;p&gt;Bigbank Information Security Team (ISEC) is a blue team of hackers, who tries to keep the bank safe from
exploitation and data breaches.&lt;/p&gt;
</description>
        <pubDate>Thu, 20 Dec 2018 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2018/secure-christmas</link>
        <guid isPermaLink="true">https://sqroot.eu/2018/secure-christmas</guid>
        
        
        <category>Security</category>
        
      </item>
    
      <item>
        <title>1u OpenHAB enclosure</title>
        <description>&lt;p&gt;I have been running &lt;a href=&quot;https://mysensors.org&quot;&gt;MySensors&lt;/a&gt; and &lt;a href=&quot;https://www.openhab.org&quot;&gt;OpenHAB&lt;/a&gt; for a while now. The system is set up on a Raspberry Pi 3, running &lt;a href=&quot;https://github.com/openhab/openhabian&quot;&gt;OpenHABian&lt;/a&gt;.
I have built and deployed some basic MySensors nodes in my apartment, measuring things like room temperature and humidity. I have
some “smart” IoT devices to control with OpenHAB.&lt;/p&gt;

&lt;p&gt;My home automation project begin as a prototype, but by now it’s become clear that the system is useful and I want to expand it.
This means that the “I’ll just throw a RPi onto a rack shelf” approach needs upgrading. I have a proper rack, why can’t the RPi be properly racked?&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/shelf-pi.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/shelf-pi.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/shelf-pi.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/shelf-pi.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/shelf-pi.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;I had an empty Soekris 1u net6501 enclosure, which fit the bill.&lt;/p&gt;

&lt;h2 id=&quot;business-plan&quot;&gt;Business Plan&lt;/h2&gt;

&lt;p&gt;Drill new holes into the Soekris enclosure, mount the Pi-s into it; rackmount the entire thing. No more free-floating Pi-s on a shelf. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#labporn&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Bonus points: replace the stock &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NRF24L01+&lt;/code&gt; radio with the more powerful &lt;a href=&quot;https://hackaday.com/2016/05/31/fixing-the-terrible-range-of-your-cheap-nrf24l01-palna-module/&quot;&gt;long-range version&lt;/a&gt; (external antenna); and support MySensors
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERROR&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RX&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TX&lt;/code&gt; &lt;a href=&quot;https://www.mysensors.org/build/advanced_gateway&quot;&gt;LED-s&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-build&quot;&gt;The Build&lt;/h2&gt;

&lt;p&gt;I started by measuring and drawing the layout in Inkscape. By printing the panel design on paper, I could get hole guidelines for drilling.&lt;/p&gt;

&lt;p&gt;I planned to mount 3 LED-s to the 1u front panel for MySensors, + a toggle switch for stopping / starting home automation services on the Pi.
The toggle switch would allow Eveli to turn off all home automation services, should something error out and become UnbearablyAnnoying.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/drilling.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/drilling.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/drilling.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/drilling.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/drilling.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Light sandpaper took care of removing the original Soekris paint and text. Three layers of spray-paint later I had a nice-looking black front panel.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/paintjob.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/paintjob.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/paintjob.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/paintjob.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/paintjob.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;I used through-hole &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3mm&lt;/code&gt; LED sockets and a small toggle switch.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/mount.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/mount.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/mount.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/mount.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/mount.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;I drilled eight &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.5mm&lt;/code&gt; holes for mounting two Raspberry Pi-s (the 2nd Pi just rents the space in the enclosure) and Eveli proceeded
to screw them in place.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/girl-mounting.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/girl-mounting.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/girl-mounting.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/girl-mounting.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/girl-mounting.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/mounted-pis.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/mounted-pis.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/mounted-pis.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/mounted-pis.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/mounted-pis.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;I also added two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;40mm&lt;/code&gt; fans to the sides of the enclosure for keeping things cool. The fans presented a problem, as they run on standard
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12V&lt;/code&gt;, however I have no such power source available from the Pi-s. This problem will be solved in the future, &lt;em&gt;somehow&lt;/em&gt;.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/fans.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/fans.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/fans.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/fans.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/fans.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The back of the enclosure (the addon card slot) also got it’s hole for the antenna mount of the radio.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/antenna.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/antenna.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/antenna.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/antenna.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/antenna.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Electronics on the front panel needed connecting to the PI. I created a very small PCB module for adding the required &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;300Ω&lt;/code&gt; resistors to the LED-s
and connected them to RPi GPIO pins.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/frontpanel-electronics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/frontpanel-electronics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/frontpanel-electronics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/frontpanel-electronics.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/frontpanel-electronics.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;Documentation is important - in three months time, I won’t remember what connects to where. I created a quick diagram of the electronics in
&lt;a href=&quot;http://fritzing.org/home/&quot;&gt;Fritzing&lt;/a&gt; and printed it onto the inside of the enclosure.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/schematics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/schematics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/schematics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/schematics.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/schematics.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/mounted-schematics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/mounted-schematics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/mounted-schematics.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/mounted-schematics.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/mounted-schematics.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;The resulting enclosure looked like this.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/inside-look.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/inside-look.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/inside-look.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/inside-look.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/inside-look.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;p&gt;I installed the 1u enclosure to my homelab rack.&lt;/p&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/rackmount.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/rackmount.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/rackmount.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/rackmount.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/rackmount.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;picture&gt;
    
        &lt;source media=&quot;(min-width: 576px)&quot; srcset=&quot;/content/resized/576/2018/rpi-enclosure/rackmount-closeup.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 768px)&quot; srcset=&quot;/content/resized/768/2018/rpi-enclosure/rackmount-closeup.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 992px)&quot; srcset=&quot;/content/resized/992/2018/rpi-enclosure/rackmount-closeup.jpg&quot; /&gt;
    
        &lt;source media=&quot;(min-width: 1200px)&quot; srcset=&quot;/content/resized/1200/2018/rpi-enclosure/rackmount-closeup.jpg&quot; /&gt;
    
    &lt;img src=&quot;/content/2018/rpi-enclosure/rackmount-closeup.jpg&quot; /&gt;
&lt;/picture&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;

&lt;p&gt;Initial testing showed that everything worked OK - the long-range radio presented no problems and MySensors flashed the appropriate LED-s
when radio activity occurred.&lt;/p&gt;

&lt;p&gt;The back-end of the enclosure doesn’t look as good as it could - I fed the Ethernet and power cables directly into the PI-s, so it isn’t modular.&lt;/p&gt;

&lt;p&gt;Future plans involve writing firmware to make the toggle switch work as well as populating the original Soekris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3mm&lt;/code&gt; LED sockets with LED-s: they
will start showing service status on the OpenHAB (MySensors, OpenHAB, MySQL…).&lt;/p&gt;

&lt;h2 id=&quot;project-files&quot;&gt;Project Files&lt;/h2&gt;

&lt;p&gt;Project files are available from &lt;a href=&quot;https://github.com/anroots/rpi-enclosure&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Thu, 30 Aug 2018 00:00:00 +0300</pubDate>
        <link>https://sqroot.eu/2018/1u-openhab-enclosure</link>
        <guid isPermaLink="true">https://sqroot.eu/2018/1u-openhab-enclosure</guid>
        
        
        <category>Hardware</category>
        
      </item>
    
      <item>
        <title>My Soul is Mine</title>
        <description>&lt;p&gt;I was stopped today by a man who wanted to know if I believe in a soul.&lt;/p&gt;

&lt;p&gt;“Why not”, the man said, “you are alive, surely you have a soul!”&lt;/p&gt;

&lt;p&gt;Perhaps I do - or do not; I lack data. What I know is that my soul is my own, and ain’t nobodys business to tell me what to do with it.&lt;/p&gt;

&lt;p&gt;“Thou must believe in a higher power, a god!”, is a man, telling me what to do with it.&lt;/p&gt;

&lt;p&gt;Live life for today. Live life for the now, not for decades in the future, for what might or might not exist, after. Enjoy what you have right now, and what you have not. Warmth. Food. An ilness. A kindness, a kiss. Friends.&lt;/p&gt;

&lt;p&gt;Friends. Live for friends, for people who are special. Hold &lt;em&gt;them&lt;/em&gt; in your heart, instead of a god. Do not talk to me about retribution, should I refuse to give my heart to him. A heaven, where admittance is only granted to those who worship, is a kingdom of fear, not free will. Would I want to be there?&lt;/p&gt;

&lt;p&gt;Above all, live for yourself.&lt;/p&gt;

&lt;p&gt;Do not stop me, for I am a man who knows himself and can make his own choices.&lt;/p&gt;
</description>
        <pubDate>Tue, 22 May 2018 00:00:00 +0300</pubDate>
        <link>https://sqroot.eu/2018/my-soul-is-mine</link>
        <guid isPermaLink="true">https://sqroot.eu/2018/my-soul-is-mine</guid>
        
        
        <category>Opinions</category>
        
      </item>
    
      <item>
        <title>Outage Reports From Personal Homelab</title>
        <description>&lt;p&gt;All times are in local (UTC+2) timezone.&lt;/p&gt;

&lt;p&gt;Consumers, with their ISP-provided all-in-one router/firewall/switch/access point have it easy: plug it in, and hardly anything ever breaks.
I run a personal homelab from my apartment - a 42U rack with a firewall, switched networking, application servers, UPS - all the good stuff.
I get more power, but also more moving parts, which means my home IT setup has more resemblance to a corporate environment,
with associated problems: more breakage and more support.&lt;/p&gt;

&lt;p&gt;Here are some examples on how things can go wrong.&lt;/p&gt;

&lt;h2 id=&quot;secondary-wan-unusable-due-to-breached-bandwidth-cap&quot;&gt;Secondary WAN Unusable Due To Breached Bandwidth Cap&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Start&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2018-02-18 02:00:40&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;End&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2018-03-01 00:00:00&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Scheduled backups were allowed to run over a fail-over WAN connection, which filled up its data cap and rendered it unusable&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Discovered By&lt;/strong&gt;: Monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the night, at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12:36&lt;/code&gt;, the primary WAN dropped due to excessive packet loss. The WAN connection had been experiencing various degrees of packet loss most of the late evening (11pm…1am, reasons unknown).&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Primary WAN down&quot; integrity=&quot;sha512-+worJ29cTSbTpnvxybe/c+QlAd8EsVR90rV/1sJOTuClQPiAuNAa5MK9CZn1qqN+5EGfa1XdraJsXk741UZNCg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/starman-down-fb0a2b276f5c4d26d3a67bf1c9b7bf73e42501df04b1547dd2b57fd6c24e4ee0a540f880b8d01ae4c2bd0999f5aaa37ee4419f6b55ddada26c5e4ef8d5464d0a.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Shortly after that, a scheduled backup job from a Synology NAS ran. The backup archive was about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;107 GB&lt;/code&gt; and was destined to upload to Amazon S3.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Synology backup config&quot; integrity=&quot;sha512-1BcI7PK/Jk0zdFVwQxJ2IXz1PE/q1p8vjhqtC7FmV2E/P1YVioU7pLk/wWHY3Q5GBNYQp471X8qQ4Q0yPRagfg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/backup-config-d41708ecf2bf264d33745570431276217cf53c4fead69f2f8e1aad0bb16657613f3f56158a853ba4b93fc161d8dd0e4604d610a78ef55fca90e10d323d16a07e.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When the primary WAN (Starman) goes down, a fail-over 4G WAN (Tele2) connection automatically takes over. Even though the primary WAN recovered a while later (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;01:02&lt;/code&gt;), the backup had already started and used the secondary WAN connection, which is bandwidth-capped to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30GB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Primary WAN recovers&quot; integrity=&quot;sha512-zfMcqzscsO71G31Vr3ySjaObwYh3v8xBEPWA1uPXwVpCD9FYbRg3MYxBEjZnM0Bz2012AmKS8MkyYh904AmG6A==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/starman-recovery-cdf31cab3b1cb0eef51b7d55af7c928da39bc18877bfcc4110f580d6e3d7c15a420fd1586d1837318c41123667334073db4d76026292f0c932621f74e00986e8.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It is unclear why the backup did not switch back to the primary WAN connection, once it recovered. Leading theory: a persistent TCP connection to
S3 had already been established over the backup WAN and the firewall / Synology did not want to break the TCP state, so it kept using it.&lt;/p&gt;

&lt;p&gt;Result - the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30GB&lt;/code&gt; data cap was eaten up very quickly, the backup failed and the secondary WAN was now effectively offline until the next month,
when the cap reset.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Traffic graph of secondary WAN&quot; integrity=&quot;sha512-8Wqp6BHFX4DAkHnOTcv/pSZQ6S6iasWhfQJmz/fS4s8q9sfEk6BKCC8HrjFwg1LtxuyN2ZPn7kKAQhPKB2Xc7A==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/traffic-graph-f16aa9e811c55f80c09079ce4dcbffa52650e92ea26ac5a17d0266cff7d2e2cf2af6c7c493a04a082f07ae31708352edc6ec8dd993e7ee42804213ca0765dcec.png&quot; /&gt;
&lt;img alt=&quot;Data cap full&quot; integrity=&quot;sha512-uUwvXv7dfl+5KCGFbhA3in0VQVTPqQLJThCN5xJVtKcO+o5UGnsReISS5mg+i1dq8RIEyxEpzKKQPThh4EitRg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/data-cap-b94c2f5efedd7e5fb92821856e10378a7d154154cfa902c94e108de71255b4a70efa8e541a7b11788492e6683e8b576af11204cb1129cca2903d3861e048ad46.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;An additional alert was thrown about the failure of the secondary WAN by Prometheus monitoring as soon as the cap was breached
and the ISP blocked service.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;HAProxy back-end down alert&quot; integrity=&quot;sha512-wKWW6mbWAc6x+iO6/3bsTJRB/joxdV9b6GHjbjs2jVKqp56gFo0wphU2sc5IBYbYusUoq6YbUDt5t6PBeIqhdQ==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/haproxy-alert-c0a596ea66d601ceb1fa23baff76ec4c9441fe3a31755f5be861e36e3b368d52aaa79ea0168d30a61536b1ce480586d8bac528aba61b503b79b7a3c1788aa175.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The alert reported that a cloud-based HAProxy load-balancer was no longer able to reach my firewall
via the secondary WAN connection. This meant that when the primary WAN goes down again, all of my self-hosted webpages will become
unavailable, too.&lt;/p&gt;

&lt;h3 id=&quot;mitigation&quot;&gt;Mitigation&lt;/h3&gt;

&lt;p&gt;The NAS itself is not gateway-aware: it can not detect (without hackery) if the primary or secondary WAN is active and if it should
proceed with the backups.&lt;/p&gt;

&lt;p&gt;A sensible solution is to apply mitigation from the firewall: only route NAS traffic to WAN through the primary WAN interface (previously: WAN fail-over interface).&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;NAS firewall rule&quot; integrity=&quot;sha512-SWM7MVjNnRPEEm1Al8haYgkBiy5UffvXA7nzMMmgt4tuCWthytYn5hqE16Tss37PqyK25kN6qSyjLqm4yWJszg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/nas-firewall-rule-49633b3158cd9d13c4126d4097c85a6209018b2e547dfbd703b9f330c9a0b78b6e096b61cad627e61a84d7a4ecb37ecfab22b6e6437aa92ca32ea9b8c9626cce.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The NAS will not reach the Interwebs when the primary WAN is down (a downside), but it will also not eat up data-capped secondary WAN bandwidth again (a win).&lt;/p&gt;

&lt;p&gt;The purpose of the secondary WAN is to keep public webpages accessible during a short primary WAN outage - backups can wait.&lt;/p&gt;

&lt;h2 id=&quot;internet-unusable-due-to-dns-failure&quot;&gt;Internet Unusable Due To DNS Failure&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Start&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~2018-02-17 22:00&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;End&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~2018-02-17 22:20&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: &lt;a href=&quot;https://quad9.net&quot;&gt;Quad9&lt;/a&gt; DNS resolver outage or a network outage to nearest Quad9 server&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Discovered By&lt;/strong&gt;: SO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Incoming customer complaint: “The Internet is not working”. Investigation revealed that the problematic laptop was in WiFi, had IP
and was able to ping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8.8.8.8&lt;/code&gt;. However, ping to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;neti.ee&lt;/code&gt; failed. Further investigation revealed a DNS outage from that laptop
and from another client device as well. Suspecting a wider DNS outage, investigation moved over to the firewall.&lt;/p&gt;

&lt;p&gt;The main firewall was set up to use primary and secondary &lt;a href=&quot;https://quad9.net&quot;&gt;Quad9&lt;/a&gt; DNS servers - it’s a DNS service that is both
fast and also blocks malicious sites at the DNS level, “for free”. Adding a tertiary DNS (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8.8.8.8&lt;/code&gt;) to the firewall’s pool of
configured DNS servers hotfixed the issue and the customer was happily using the Internet again.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;DNS servers&quot; integrity=&quot;sha512-hTIg3H6VTiH0VNztX3d/Tw54SGlOhvM6GSQILHEjQ84IYIJaJXUthsVtCl1SJRuS/eaT9AQnQVguF48A4gsyhw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/dns-servers-853220dc7e954e21f454dced5f777f4f0e7848694e86f33a1924082c712343ce0860825a25752d86c56d0a5d52251b92fde693f4042741582e178f00e20b3287.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Some minutes later, the Quad9 DNS service was working again and the hotfix could be removed.&lt;/p&gt;

&lt;p&gt;Root cause unclear: either an outage at the nearest Quad9 distribution servers or a network failure between me and Quad9.
No similar outage has happened to date and Quad9 does not have a service status page (that I could find).&lt;/p&gt;

&lt;h2 id=&quot;momentary-power-spike-from-mains-power&quot;&gt;Momentary Power Spike from Mains Power&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Start&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2018-04-17 11:18:03&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;End&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2018-04-17 11:18:10&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Unexpected power spike on mains power, over Tallinn city centre, reason unknown&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Discovered By&lt;/strong&gt;: User + Monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was working in the office, when, suddenly, the green emergency exit sign on the ceiling flashed to ~300% regular brightness, then back again. Seconds later, I received an alert on my phone that my homelab had gone to battery power - the UPS had taken over. Five seconds later, the UPS was back on mains power.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Kibana logs, showing UPS switching into battery mode&quot; integrity=&quot;sha512-FLagrkzm/OnXaLQhZKxyXMbspLxDjD05zBFtfHXzgGjVC0RpqGpzAf8MJCOR+I5YiVCJpmsdm8v28mPg65l7OA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/ups-battery-14b6a0ae4ce6fce9d768b42164ac725cc6eca4bc438c3d39cc116d7c75f38068d50b4469a86a7301ff0c242391f88e58895089a66b1d9bcbf6f263e0eb997b38.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Theory: an unexpected power spike occured in central Tallinn, my office and home were affected. The spike lasted a second or two.&lt;/p&gt;

&lt;p&gt;The homelab was protected by the UPS.&lt;/p&gt;

&lt;h2 id=&quot;remote-filebeat-log-shipments-failing-due-to-changed-remote-ip-s&quot;&gt;Remote Filebeat log shipments failing due to changed remote IP-s&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Start&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2019-06-08 19:11:13&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;End&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2019-06-09 16:20:00&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Detected at&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2019-06-09 10:05:00&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Changed remote node IP, which wasn’t in a whitelist&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Discovered By&lt;/strong&gt;: User, who needed logs and went looking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am running a &lt;a href=&quot;https://www.digitalocean.com/products/kubernetes/&quot;&gt;managed Kubernetes cluster&lt;/a&gt; on DigitalOcean. I run a DaemonSet of Filebeat containers on the nodes, which ship pod and node logs to my on-prem ELK for storage and search. The on-prem firewall has whitelisted the IP-s of DigitalOcean nodes, that are allowed to ship logs to me.&lt;/p&gt;

&lt;p&gt;As part of the managed service, DigitalOcean performs automatic Kubernetes cluster updates. As details about Intel’s MDS vulnerability emerged recently, DigitalOcean &lt;a href=&quot;https://blog.digitalocean.com/may-2019-intel-vulnerability/&quot;&gt;needed to patch&lt;/a&gt; their infrastructure. This meant a redeploy of Kubernetes nodes.&lt;/p&gt;

&lt;p&gt;Every time the nodes are redeployed, they are replaced with new droplets, having new IP-s. As you might guess, this breaks IP whitelisting - and I didn’t have any detection or automatic remediation in place.&lt;/p&gt;

&lt;p&gt;So, when I went looking for pod logs from ELK to debug a unrelated problem, I found no logs at all - my Kubernetes node IP-s had changed and incoming log shipments were rejected by my firewall.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Firewall blocking logs&quot; integrity=&quot;sha512-uYm9ZRXmFRibsJ5awxxgqnPJPepAo3uFwuDZNOhbsJAGzWA0m5ZMBxAoZPMjhIJj4W/3xYRON9cObZgx3xwH6A==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/blocked-log-shipments-b989bd6515e615189bb09e5ac31c60aa73c93dea40a37b85c2e0d934e85bb09006cd60349b964c07102864f323848263e16ff7c5844e37d70e6d9831df1c07e8.png&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;remediation&quot;&gt;Remediation&lt;/h3&gt;

&lt;p&gt;The solution was easy enough - update the whitelist with new IP-s.&lt;/p&gt;

&lt;h3 id=&quot;monitoring-improvements&quot;&gt;Monitoring improvements&lt;/h3&gt;

&lt;p&gt;As this was bound to happen again, I decided to deploy monitoring and alerting to detect this.
&lt;a href=&quot;https://elastalert.readthedocs.io&quot;&gt;Elastalert&lt;/a&gt; fit this use-case (alerting from firewall logs) nicely,
and I’d been meaning to deploy it anyway.&lt;/p&gt;

&lt;p&gt;I deployed it to my Openshift 3 cluster and added the first rule, which will monitor firewall logs for log shipment blocks.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Elastalert rule&quot; integrity=&quot;sha512-3+VvE4GexZ2odQr8HUQHOxT544Lc0R+sEqqhvWtZAWY7aRDSM8JQzqWKpVeKc8WUm+7hIa/fYkRcwUVgcYHedA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/elastalert-rule-dfe56f13819ec59da8750afc1d44073b14f9e382dcd11fac12aaa1bd6b5901663b6910d233c250cea58aa5578a73c5949beee121afdf62445cc145607181de74.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Elastalert alert&quot; integrity=&quot;sha512-bcfJwNDgMCuSntKzL24WvDdLNGLSNuDuWnP3TKOQF/0MhtK2OCj2UuLXKTI8LeMIgNCYrOcqyCIk+ot3b2QeqA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/outages/elastalert-fleep-6dc7c9c0d0e0302b929ed2b32f6e16bc374b3462d236e0ee5a73f74ca39017fd0c86d2b63828f652e2d729323c2de30880d098ace72ac82224fa8b776f641ea8.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A better solution would be to hook into DigitalOcean API-s and automatically update the whitelist.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;(This post will be updated when more interesting incidents occur)&lt;/p&gt;
</description>
        <pubDate>Sun, 18 Feb 2018 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2018/outage-reports-from-personal-homelab</link>
        <guid isPermaLink="true">https://sqroot.eu/2018/outage-reports-from-personal-homelab</guid>
        
        
        <category>Learning</category>
        
      </item>
    
      <item>
        <title>&quot;Shut It!&quot; - An Arduino Door Alarm</title>
        <description>&lt;p&gt;The outer door to the office had a problem: sometimes, it wouldn’t lock properly. It’s one of those doors that
has a mechanical automatic closure system, but the system was worn down and would sometimes not close and properly lock the door.
The result, a security risk: a distracted employee could leave the office and forget the door unlocked.&lt;/p&gt;

&lt;p&gt;To mitigate this issue, I decided to build a small, simple DIY door alarm, that would alert employees when the office door
had been left open for a prolonged period of time. This was the perfect practical project as an introduction to digital
electronics and Arduino for &lt;a href=&quot;http://eppolekors.com&quot;&gt;@epplkrs&lt;/a&gt;, a graphical designer who
&lt;a href=&quot;https://github.com/anroots/electronics-labs&quot;&gt;wanted to learn about Arduino&lt;/a&gt;. She did most of the
prototyping, soldering and product design and built her first real Arduino product.&lt;/p&gt;

&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;/h2&gt;

&lt;p&gt;Build a small door sensor that would start beeping when the door is open for too long.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Small form-factor (can be attached to a wall)&lt;/li&gt;
  &lt;li&gt;Monitors the state of the door (open / locked)&lt;/li&gt;
  &lt;li&gt;If the door has been open for longer than 30 seconds, start beeping annoyingly until someone comes and shuts the door&lt;/li&gt;
  &lt;li&gt;Runs on batteries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considering the requirements, we settled on the following design:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Arduino as “the brain” - Atmega328 on a breadboard&lt;/li&gt;
  &lt;li&gt;Runs on 3 AA batteries (4.5V)&lt;/li&gt;
  &lt;li&gt;Project installed in a small paper box (taped to the wall), with an extending sensor wire&lt;/li&gt;
  &lt;li&gt;Sensor (reed switch with a magnet) attaches to the door to monitor door state&lt;/li&gt;
  &lt;li&gt;When the door is open, the reed switch activates and powers ON the Arduino&lt;/li&gt;
  &lt;li&gt;A status LED on the front panel indicates that the door is open&lt;/li&gt;
  &lt;li&gt;If the door is not closed within 30 seconds, an internal Piezo buzzer will start beeping&lt;/li&gt;
  &lt;li&gt;When the door is closed, the cycle repeats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt=&quot;Project schematic&quot; integrity=&quot;sha512-toF2OjSRbuapOsWq7JD3M/SIivYc/zwi2ZjexXs3f9Ksttj7f7BtxDFJH8zzDrXq4YlEbW0g3HopurXxuG69QA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/schematic-b681763a34916ee6a93ac5aaec90f733f4888af61cff3c22d998dec57b377fd2acb6d8fb7fb06dc431491fccf30eb5eae189446d6d20dc7a29bab5f1b86ebd40.png&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;build-process&quot;&gt;Build Process&lt;/h2&gt;

&lt;p&gt;We started with a breadboard prototype: Arduino hooked up to a sensor, a LED and a buzzer.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Breadboard&quot; integrity=&quot;sha512-IdmAwQSqutKmIBWWzJye8Esx+ZRZy0zGQqMuTNB+bsCI/owNSrV7nX0bQsTr3+h0knF3KNP0jR/a5e1R8KNVRw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/breadboard-21d980c104aabad2a6201596cc9c9ef04b31f99459cb4cc642a32e4cd07e6ec088fe8c0d4ab57b9d7d1b42c4ebdfe87492717728d3f48d1fdae5ed51f0a35547.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This enabled us to write and test the Arduino firmware.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Arduino code&quot; integrity=&quot;sha512-1nn8wG4QX/Lw119ZkwmyI228144YvOZ0CST77TOKvZWr122CUiF7kB45C0N+z+vr+RW1N5iaoxUUcaMldfA02A==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/programming-d679fcc06e105ff2f0d75f599309b2236dbcd78e18bce6740924fbed338abd95abd76d8252217b901e390b437ecfebebf915b537989aa3151471a32575f034d8.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With the code properly reading sensors and activating the buzzer, came the time for physical assembly: 
The project needed to come off the breadboard and into a permanent, fixed PCB.&lt;/p&gt;

&lt;p&gt;The Atmega328 chip was attached to an empty PCB, with all the required I/O
devices and connectors soldered onto it.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Soldering&quot; integrity=&quot;sha512-wvwvVIn70LjOk3C8AgSvSl8fKz5BrFX4RGcwXxylHtQmVcFR8Y4IUYjZpMLkeyWFfvmb69eZYxJceFYN6TG9Aw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/solder1-c2fc2f5489fbd0b8ce9370bc0204af4a5f1f2b3e41ac55f84467305f1ca51ed42655c151f18e085188d9a4c2e47b25857ef99bebd79963125c78560de931bd03.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Soldering&quot; integrity=&quot;sha512-RAYdYU5ecbLpRQEHNTdDO4XF60EdIguzOM0K93f/uSriGJ1p5wmrwF+oog8zOqVofW+spyNw/PYUMCOE2HkLdw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/solder2-44061d614e5e71b2e94501073537433b85c5eb411d220bb338cd0af777ffb92ae2189d69e709abc05fa8a20f333aa5687d6faca72370fcf614302384d8790b77.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Soldering done&quot; integrity=&quot;sha512-TQbM/AzncW+IWPF3LApQVoaaByUmUr+9MeeQhasl5/JCIe0X5CqgqGoB1xFjRvw8g73KM4f/ZYGXV736p+qMEg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/pcb-done-4d06ccfc0ce7716f8858f1772c0a5056869a07252652bfbd31e79085ab25e7f24221ed17e42aa0a86a01d7116346fc3c83bdca3387ff65819757bdfaa7ea8c12.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Completed box&quot; integrity=&quot;sha512-xamkBz9PYgtKp5Hed+pLv6+3pw0bbj9sCNMRbT8faP9A+elyfEo9RBXIAws58fU5/JVECy9i5ckKge9Kv+W+3A==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/completed-box-in-c5a9a4073f4f620b4aa791de77ea4bbfafb7a70d1b6e3f6c08d3116d3f1f68ff40f9e9727c4a3d4415c8030b39f1f539fc95440b2f62e5c90a81ef4abfe5bedc.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We used an Apple Mouse box as the project enclosure. As a result, the completed project was
elegantly White.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Completed box&quot; integrity=&quot;sha512-woH19l5irV5A5l9Re67rktBWBL2ArNRf/7e5dqOuu3nV1RhjRysVwIXtMnLQU8k6pCBCy/EkYp/2DR+lqrBsww==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/finished-front-c281f5f65e62ad5e40e65f517baeeb92d05604bd80acd45fffb7b976a3aebb79d5d51863472b15c085ed3272d053c93aa42042cbf124629ff60d1fa5aab06cc3.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Double-sided tape to the back of the box keeps the project on a wall.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Completed box&quot; integrity=&quot;sha512-G6abYLnknrtn1CTWUVDHazjVIYjT0LqouVCMcGhpRQ7zNR9jt1/b+zsqSTH5JWQp27VeYZtPrWuLo9yiuRbN+w==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/finished-back-1ba69b60b9e49ebb67d424d65150c76b38d52188d3d0baa8b9508c706869450ef3351f63b75fdbfb3b2a4931f9256429dbb55e619b4fad6b8ba3dca2b916cdfb.jpg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;We installed the project to the problematic door; and it works: when the door is
opened, the project powers ON, waits for 30 seconds and will then start BEEPING, alerting the
office: the door was left open again.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Installing&quot; integrity=&quot;sha512-qcmm2iL0lwgB61jP3GpkvmWG5VaQicuq0ypTbqxDtMYRoaiclhW6bHxDUtrarp0oaQtYxGejC4139TuUM/Knfg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2018/shut-it/installing-a9c9a6da22f4970801eb58cfdc6a64be6586e5569089cbaad32a536eac43b4c611a1a89c9615ba6c7c4352dadaae9d28690b58c467a30b8d77f53b9433f2a77e.jpg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;source&quot;&gt;Source&lt;/h2&gt;

&lt;p&gt;Project schematics and source code &lt;a href=&quot;https://github.com/anroots/shut-it&quot;&gt;are available from Github&lt;/a&gt; under the MIT license.&lt;/p&gt;
</description>
        <pubDate>Tue, 13 Feb 2018 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2018/shut-it-an-arduino-door-alarm</link>
        <guid isPermaLink="true">https://sqroot.eu/2018/shut-it-an-arduino-door-alarm</guid>
        
        
        <category>Hardware</category>
        
      </item>
    
      <item>
        <title>Repurposing an Old Phone: Personal HUD Screen</title>
        <description>&lt;p&gt;I was running with my buddy Priit, when I accidentally dropped my trusty Nexus 5 phone and cracked its screen.
The screen had fractures, but was still perfectly legible; and the hardware still functioned.
So, instead of throwing it away, I gave it a new life on my wall, as a personal “HUD” screen, showing relevant info
such as weather, time and bus schedules.&lt;/p&gt;

&lt;h2 id=&quot;revision-1&quot;&gt;Revision #1&lt;/h2&gt;

&lt;p&gt;The first revision was just a hacked-together &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.html&lt;/code&gt; page with some inline Javascript string concatenation.
It fetched relevant data from publicly available API-s and displayed it out. The page took as little work as possible,
to get the prototype usefulness validated.&lt;/p&gt;

&lt;p&gt;As I was already running a in-home Openshift3 cluster, deploying it into a Nginx stateless web container
was a non-issue and after two nights of hacking I had a functional prototype.&lt;/p&gt;

&lt;h3 id=&quot;features&quot;&gt;Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Display current time using &lt;a href=&quot;https://momentjs.com&quot;&gt;moment.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Show current weather and the forecast for the next three hours using data from &lt;a href=&quot;https://openweathermap.org/api&quot;&gt;OpenWeatherMap&lt;/a&gt; API&lt;/li&gt;
  &lt;li&gt;Show the departure times (using real-time GPS predictions) of busses from my nearest stop using the undocumented and quite horrible CSV “API” from &lt;a href=&quot;https://soiduplaan.tallinn.ee&quot;&gt;Tallinn city&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Always-on screen on dark background&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt=&quot;Revision 1&quot; integrity=&quot;sha512-S5V1h9ET2bB8kCNEo0ZBEbxp+3QaTWAV9Sxhq4lHEpyX7DV35Hawtrpsvp6Qh2F56gFcMQec4icHCQhK6DHYMg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/screen/rev1-4b957587d113d9b07c902344a3464111bc69fb741a4d6015f52c61ab8947129c97ec3577e476b0b6ba6cbe9e90876179ea015c31079ce2270709084ae831d832.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The solution was quick to implement and worked; providing useful information when I was heading out.
However, as quick PoC-s often do, it had its problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The codebase was a mess - literally hacked together into a couple of files. It needed refactoring and “beautification” before I dared show it to anyone&lt;/li&gt;
  &lt;li&gt;All config was hardcoded&lt;/li&gt;
  &lt;li&gt;It was not very modular nor expandable (with new features)&lt;/li&gt;
  &lt;li&gt;After a couple of months, I learned what &lt;a href=&quot;https://en.wikipedia.org/wiki/Screen_burn-in&quot;&gt;screen burn-in&lt;/a&gt; means&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt=&quot;Screen burn&quot; integrity=&quot;sha512-plH+PbLY9snawGnIvxGXD6bsX72TJQq9FHbqFTRA/3Q5XJqEGX4eEn9GBMO5AGzNL777gcqIv9WexbhG37+5AQ==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/screen/screen-burn-a651fe3db2d8f6c9dac069c8bf11970fa6ec5fbd93250abd1476ea153440ff74395c9a84197e1e127f4604c3b9006ccd2fbefb81ca88bfd59ec5b846dfbfb901.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Screen burn-in: the outlines of previous content are visibly “burned in”.&lt;/p&gt;

&lt;h2 id=&quot;revision-2&quot;&gt;Revision #2&lt;/h2&gt;

&lt;p&gt;I was satisfied that the concept worked and provided value; time to refactor.&lt;/p&gt;

&lt;p&gt;I ordered a cheap-ish, but still good quality (excellent, large screen!) tablet from China -&lt;a href=&quot;https://www.gearbest.com/tablet-pcs/pp_690462.html&quot;&gt;Teclast T10&lt;/a&gt;. This gave me larger screen real-estate and also a better quality (and not broken) touch-screen.&lt;/p&gt;

&lt;p&gt;I rewrote the code from zero and split the project into two parts: &lt;a href=&quot;https://github.com/sqroot-eu/screen-frontend&quot;&gt;screen-frontend&lt;/a&gt; (&lt;a href=&quot;https://vuejs.org&quot;&gt;Vue.js&lt;/a&gt;) and &lt;a href=&quot;https://github.com/sqroot-eu/screen-backend&quot;&gt;screen-backend&lt;/a&gt; (Python / Flask). This allowed me to do it in a API-first manner and also keep everything nice and apart.&lt;/p&gt;

&lt;p&gt;Getting to know Vue and Webpack without prior major JavaScript experience was a challenge, especially the asset build process (I insist in using CoffeeScript and Sass over their ‘plainer’ cousins), but finally, I succeeded.&lt;/p&gt;

&lt;p&gt;I removed most of the hardcoded values (weather station to use, bus stop ID-s) from the code, which makes it more portable and - in theory - allows others to benefit from the project, although this is not a goal in itself.&lt;/p&gt;

&lt;p&gt;I switched to weather data provider to the &lt;a href=&quot;http://ilmateenistus.ee&quot;&gt;national weather service&lt;/a&gt;,
because they have local data (although in XML…) and audio reports.&lt;/p&gt;

&lt;p&gt;Why would &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://www.ilmateenistus.ee/ilma_andmed/xml/hoiatus.php&lt;/code&gt; API respond with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP 404&lt;/code&gt; for valid queries is beyond me.
Whoever developed that endpoint owes me 30 minutes of lost time.&lt;/p&gt;

&lt;p&gt;I solved the screen burn-in problem by keeping the screen OFF most of the time. The tablet turns the screen ON automatically
for five minutes when the front-facing camera detects motion. This saves the screen, some power and also keeps the ambient
light low at night. This can be done with the &lt;a href=&quot;https://www.fully-kiosk.com/&quot;&gt;Fully kiosk browser&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;features-1&quot;&gt;Features&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Show current time&lt;/li&gt;
  &lt;li&gt;Show current weather + forecast for the next couple of days&lt;/li&gt;
  &lt;li&gt;Play weather forecast in audio form (audio provided by the national weather service)&lt;/li&gt;
  &lt;li&gt;Highlight and display weather alerts for my area, if there are any&lt;/li&gt;
  &lt;li&gt;Show bus schedule in real-time&lt;/li&gt;
  &lt;li&gt;Track investments&lt;/li&gt;
  &lt;li&gt;Turn screen ON only if motion is detected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img alt=&quot;Revision 2&quot; integrity=&quot;sha512-+WxLv7YDcJWL2uABz/dvYlf3DyhHMrXup+2sM47CQmUaw4pyqpUZXUUdbWcYw0AUUeUraCtHOmQ2VjdZYIvbyg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/screen/rev2-f96c4bbfb60370958bdae001cff76f6257f70f284732b5eea7edac338ec242651ac38a72aa95195d451d6d6718c3401451e52b682b473a6436563759608bdbca.jpg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;future&quot;&gt;Future?&lt;/h2&gt;

&lt;p&gt;Tentative future plans include refactoring the codebase some more (don’t look at my variable names…)
and adding more features, for example a tab that shows readings from home IoT sensors.&lt;/p&gt;

&lt;p&gt;As the tablet is running its original Chinese firmware, I don’t consider it a “trusted” device: it could
be doing &lt;a href=&quot;https://www.cyberscoop.com/android-malware-china-huawei-zte-kryptowire-blu-products&quot;&gt;much more than only detect motion&lt;/a&gt;
with its camera. Hence, I will either try to flash
stock Android to it (tried once, failed, any links to tutorials for this specific model are appreciated)
or more likely, use my PFSense &amp;amp; IoT WiFi to block its access to the outside Internet.&lt;/p&gt;

&lt;h2 id=&quot;skill-level-ups&quot;&gt;Skill Level-Ups&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;First contact with Vue.js, Webpack and with Javascript frontend frameworks in general&lt;/li&gt;
  &lt;li&gt;Python / Flask experience&lt;/li&gt;
  &lt;li&gt;Open source credz (both the &lt;a href=&quot;https://github.com/sqroot-eu/screen-backend&quot;&gt;backend&lt;/a&gt; and &lt;a href=&quot;https://github.com/sqroot-eu/screen-frontend&quot;&gt;frontend&lt;/a&gt; are in GitHub)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project can be seen and used from &lt;a href=&quot;https://screen.sqroot.eu&quot;&gt;screen.sqroot.eu&lt;/a&gt; and the backend API is at &lt;a href=&quot;https://api.screen.sqroot.eu&quot;&gt;api.screen.sqroot.eu&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 06 Dec 2017 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2017/screen</link>
        <guid isPermaLink="true">https://sqroot.eu/2017/screen</guid>
        
        
        <category>Projects</category>
        
      </item>
    
      <item>
        <title>Snarky Doorbell</title>
        <description>&lt;p&gt;Snarky Doorbell is a custom-built smart IoT office doorbell.&lt;/p&gt;

&lt;p&gt;Instead of the usual monotonic “ding-dong”, it has personality: when the doorbell is rung, it responds
with a snarky voice comment in the style of “Ooo, this must be the pizza we ordered!” or
“The developer who gets up and opens the door is immune from the next team meeting invite!”
or “Another victim arrives….muahahahaha!”.&lt;/p&gt;

&lt;picture&gt;&lt;img alt=&quot;Snarky doorbell&quot; integrity=&quot;sha512-X/O1fbsGqiZqkNHNM4mVbo4HxZXnGd+o5Q0ZlKZcH2XwHTeW18ek+uRyLyNU55vRaxGkj3to/BBPGgj/NGtmyw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/mugshot-5ff3b57dbb06aa266a90d1cd3389956e8e07c595e719dfa8e50d1994a65c1f65f01d3796d7c7a4fae4722f2354e79bd16b11a48f7b68fc104f1a08ff346b66cb.jpg&quot; /&gt;&lt;/picture&gt;

&lt;h2 id=&quot;how-it-operates&quot;&gt;How it Operates&lt;/h2&gt;

&lt;p&gt;The doorbell is installed to the office space and “listens” to the already existing wireless doorbell ring button
we have behind the door. When a visitor rings the doorbell, first the “regular” doorbell rings and a second later,
the Snarky Doorbell enhances that ring with a snarky voice comment.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;I used to sit very close to the office’s outer door. As we had no secretary, it was often me, who answered the door.
I was annoyed by the repeating “ding-dong” ringtone and was motivated to do something about it: what if the doorbell
could speak, and express its feelings? What if I built my own doorbell, that was snarky?&lt;/p&gt;

&lt;p&gt;I had &lt;a href=&quot;https://sqroot.eu/2015/office-prank-building-a-secondary-remote-to-a-wireless-doorbell&quot;&gt;previously messed around with our wireless doorbell&lt;/a&gt; and thought it would be a quick and easy project. Boy, was I wrong - it took over two years to complete it, with various technical challenges.&lt;/p&gt;

&lt;h2 id=&quot;the-build&quot;&gt;The Build&lt;/h2&gt;

&lt;iframe style=&quot;width: 100%&quot; width=&quot;700&quot; height=&quot;600&quot; src=&quot;https://www.youtube-nocookie.com/embed/ut_KckcVxW0?rel=0&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;The build process took over two years of intermittent tinkering.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-ub4CBBJNYNZJpSKtkphBgtxTFCZNpLJ1ga45vFZilgR83VkL3MUcQYYViRMU6DFyjGlCFcrrf81c3ue359zUhA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/1-b9be0204124d60d649a522ad92984182dc5314264da4b27581ae39bc566296047cdd590bdcc51c418615891314e831728c694215caeb7fcd5cdee7b7e7dcd484.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-2k7iGxzn7iG4CYUyMnNWIRMC7LWCgrXLHLHpwANvugHW5x+5toyBFZtp4dK2jvHu3T0j8X45sStR8szPXXwabw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/2-da4ee21b1ce7ee21b8098532327356211302ecb58282b5cb1cb1e9c0036fba01d6e71fb9b68c81159b69e1d2b68ef1eedd3d23f17e39b12b51f2cccf5d7c1a6f.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-EZHha30KQTyuo9UvALFtW/b8nuGcTfRS+wfZyOA/I1VYsDDYpOlZ2b4C4g8Q05fd1LKb2Fg7v80Kh+TA7FX1rA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/3-1191e16b7d0a413caea3d52f00b16d5bf6fc9ee19c4df452fb07d9c8e03f235558b030d8a4e959d9be02e20f10d397ddd4b29bd8583bbfcd0a87e4c0ec55f5ac.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-4CK4qO4suSDU7hUiHpmNmSmsM/YV6P07gy/jdT3hWND8pHTqG+xYWO5c7FTO3XxIR1bCYUVedqgt9xC7YHY0UQ==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/4-e022b8a8ee2cb920d4ee15221e998d9929ac33f615e8fd3b832fe3753de158d0fca474ea1bec5858ee5cec54cedd7c484756c261455e76a82df710bb60763451.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-Ra2EAOpKA1FUmoSJrwWnwIATFxYLsXUH3hgQw9bfSVgM9zFD9jxRgW35LUgxJFDKdrniqwye/g9JTLTWwFXJ8A==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/5-45ad8400ea4a0351549a8489af05a7c0801317160bb17507de1810c3d6df49580cf73143f63c51816df92d48312450ca76b9e2ab0c9efe0f494cb4d6c055c9f0.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-BOBBQzZxbhIRxH1UUrkvPUDTIJDyLUf1HrvyOEb7aE9drlvF5CkrdKlXmsBZUoZjun3jDwJeT8bJgG/4FoJpPg==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/6-04e0414336716e1211c47d5452b92f3d40d32090f22d47f51ebbf23846fb684f5dae5bc5e4292b74a9579ac059528663ba7de30f025e4fc6c9806ff81682693e.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-za0eh5Ko7qHbWmIKwp/kpT4t4c9C+wQJftxWNTqV1O6IvBOGUkh0P3AChx/Qhi46ebzjx6Dsy814v7oEGa1RHw==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/7-cdad1e8792a8eea1db5a620ac29fe4a53e2de1cf42fb04097edc56353a95d4ee88bc13865248743f7002871fd0862e3a79bce3c7a0eccbcd78bfba0419ad511f.jpg&quot; /&gt;
&lt;img alt=&quot;Build photo&quot; integrity=&quot;sha512-b1iat+hvIFW+o0Xl7efuZNL1pbl4oS0vWOobNWoXN9vQLNRSdJKjqBDbYxMhQKjOIYKPHcNG2kCqs7lq1JRfTA==&quot; crossorigin=&quot;anonymous&quot; src=&quot;/assets/2017/snarky/8-6f589ab7e86f2055bea345e5ede7ee64d2f5a5b978a12d2f58ea1b356a1737dbd02cd4527492a3a810db63132140a8ce21828f1dc346da40aab3b96ad4945f4c.jpg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Several custom voice personals (“Easily excitable manager”, “Old lady”)&lt;/li&gt;
  &lt;li&gt;Settings (voice, language, volume) can be changed via knobs on the front panel&lt;/li&gt;
  &lt;li&gt;Built-in WiFi HTTP RESTful API server (statistics on doorbell rings)&lt;/li&gt;
  &lt;li&gt;Open source project plans&lt;/li&gt;
  &lt;li&gt;Non-intrusive integration with the existing doorbell system (uses the same doorbell button)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;

&lt;p&gt;Our wireless doorbell is a pretty standard one - when the ring button is pressed, it sends a ASK-encoded signal over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;433MHz&lt;/code&gt;
radio frequency to the doorbell unit, which listens to it and rings.&lt;/p&gt;

&lt;p&gt;Snarky Doorbell is, in essence, another signal receiver. In the doorbell, there is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Atmega328&lt;/code&gt; chip with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;433MHz&lt;/code&gt; receiver,
that constantly listens for incoming signals. When a signal from the doorbell remote is detected, the module
outputs a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HIGH&lt;/code&gt; signal, that is then sent to a Raspberry Pi pin.&lt;/p&gt;

&lt;p&gt;The Pi activates and plays a pre-recorded, randomly picked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wav&lt;/code&gt; file as the ringtone through a connected &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.5mm&lt;/code&gt; speaker.&lt;/p&gt;

&lt;p&gt;The doorbell is enclosed in a wooden enclosure. Front panel has three rotary encoders for controlling doorbell
volume, current voice persona and settings.&lt;/p&gt;

&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/anroots/snarky-doorbell&quot;&gt;Source code and build files&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ut_KckcVxW0&amp;amp;t=1s&quot;&gt;Build video on YouTube&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/anroots/snarky-doorbell/tree/master/wav/voices/english&quot;&gt;Listen to doorbell ringtones&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;/h2&gt;

&lt;p&gt;The following awesome people gave the doorbell their voice:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Julian Linke&lt;/li&gt;
  &lt;li&gt;Maarit Cimolonskas&lt;/li&gt;
  &lt;li&gt;Harles Paesüld&lt;/li&gt;
  &lt;li&gt;Tormi Tuuling&lt;/li&gt;
  &lt;li&gt;Kaupo Toom&lt;/li&gt;
  &lt;li&gt;Ken Kanarik&lt;/li&gt;
  &lt;li&gt;Nele Sergejeva&lt;/li&gt;
  &lt;li&gt;Ando Roots&lt;/li&gt;
  &lt;li&gt;Maria Liiger&lt;/li&gt;
  &lt;li&gt;Rauno Meronen&lt;/li&gt;
  &lt;li&gt;Tanel Sirp&lt;/li&gt;
  &lt;li&gt;Toivo Värbu&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 19 Nov 2017 00:00:00 +0200</pubDate>
        <link>https://sqroot.eu/2017/snarky-doorbell</link>
        <guid isPermaLink="true">https://sqroot.eu/2017/snarky-doorbell</guid>
        
        
        <category>Hardware</category>
        
      </item>
    
  </channel>
</rss>
