<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>LINICKX.com</title><link>https://www.linickx.com/</link><description></description><lastBuildDate>Sun, 11 Jan 2026 19:36:00 +0000</lastBuildDate><item><title>Wi-Fi (Broadcom BCM4331) for an old iMac (iMac13,1) in 2026</title><link>https://www.linickx.com/wi-fi-broadcom-bcm4331-for-an-old-imac-imac131-in-2026</link><description>&lt;p&gt;My Christmas project this year was to make my old 2012 iMac work; previously I have used &lt;a href="https://dortania.github.io/OpenCore-Legacy-Patcher/"&gt;OpenCore Legacy Patcher&lt;/a&gt; to keep MacOS going but that was become less useable -- Enter Linux!
This note is specifically geared towards OpenSUSE Tumbleweed, but is hopefully helpful for anyone trying similar with any other distro.&lt;/p&gt;
&lt;h2&gt;TLDR;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Install b43-fwcutter&lt;/li&gt;
&lt;li&gt;Download &lt;a href="https://web.archive.org/web/20240708013600/http://www.lwfinger.com/b43-firmware/broadcom-wl-6.30.163.46.tar.bz2"&gt;broadcom-wl-6.30.163.46.tar.bz2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sudo b43-fwcutter -w /usr/lib/firmware broadcom-wl-6.30.163.46.wl_apsta.o&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Reboot &amp;amp; Hope!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Long form&lt;/h2&gt;
&lt;p&gt;Booting from the tumbleweed ISO/USB worked well, obviously the bluetooth keyboard/mouse don't work, but bluetooth is detected and will work later. Wi-Fi is not detected at all, an Ethernet cable was required to get networking up. Upon completing the install, I started to investigate how to fix Wi-Fi. On Tumbleweed, the &lt;code&gt;pullin-bcm43xx-firmware&lt;/code&gt; package provides &lt;code&gt;/usr/sbin/install_bcm43xx_firmware&lt;/code&gt; however, even tho it "runs", it has an error and Wi-Fi still doesn't work and the reason is because &lt;code&gt;www.lwfinger.com/b43-firmware/&lt;/code&gt; no longer exists.&lt;/p&gt;
&lt;p&gt;Browsing the internet archive, I found a working snapshot for 8th July 2024: &lt;a href="https://web.archive.org/web/20240708013600/http://www.lwfinger.com/b43-firmware/"&gt;https://web.archive.org/web/20240708013600/http://www.lwfinger.com/b43-firmware/&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Steps:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Download &lt;a href="https://web.archive.org/web/20240708013600/http://www.lwfinger.com/b43-firmware/broadcom-wl-6.30.163.46.tar.bz2"&gt;broadcom-wl-6.30.163.46.tar.bz2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If it's not installed, you'll need &lt;code&gt;b43-fwcutter&lt;/code&gt;, so &lt;code&gt;sudo zypper install b43-fwcutter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Unpack the archive: &lt;code&gt;tar -xjf broadcom-wl-6.30.163.46.tar.bz2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Install the driver:  &lt;code&gt;sudo b43-fwcutter -w /usr/lib/firmware broadcom-wl-6.30.163.46.wl_apsta.o&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Reboot ... there's probably a way to avoid the reboot by restating Network Manager, but whatever!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After the reboot, you should see the WLAN adapter available.&lt;/p&gt;
&lt;h3&gt;Closing thoughts.&lt;/h3&gt;
&lt;p&gt;I am hosting a copy of the driver here, incase the archive goes down: &lt;a href="https://www.linickx.com/files/2026/01/broadcom-wl-6.30.163.46.tar.bz2"&gt;www.linickx.com/files/2026/01/broadcom-wl-6.30.163.46.tar.bz2&lt;/a&gt;. For me, the driver only seems to be working on 2.4Ghz, even tho' the BCM4331 support 5Ghz 802.11a 🤷🏻‍♂️ ... and performance seems to be a poor 5Mb/s. But for now, I'm on with this as my plan is to use the iMac as a kinda distraction free SSH or Writing terminal; perhaps I can fix that later and update here.&lt;/p&gt;
&lt;p&gt;If anyone knows how to get the nVidia driver working &lt;a href="https://infosec.exchange/@linickx"&gt;please hit me up&lt;/a&gt; as I'm having to manually tweak the screen brightness with each reboot.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Sun, 11 Jan 2026 19:36:00 +0000</pubDate><guid isPermaLink="false">tag:www.linickx.com,2026-01-11:wi-fi-broadcom-bcm4331-for-an-old-imac-imac131-in-2026</guid><category>Linux</category><category>iMac</category><category>MacOS</category><category>Apple</category><category>OSX</category></item><item><title>DNSCrypt Proxy on Home Assistant</title><link>https://www.linickx.com/dnscrypt-proxy-on-home-assistant</link><description>&lt;p&gt;I have published a Home Assistant Addon for DNSCrypt Proxy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;TLDR:&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In the HA Addon-store add my repository 👉🏻 https://github.com/linickx/ha-addons&lt;/li&gt;
&lt;li&gt;Install DNSCrypt Proxy (&lt;em&gt;and Start the addon&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;/addon_configs/ba53f40c-dnscrypt-proxy/dnscrypt-proxy.toml&lt;/code&gt; to suit your needs (&lt;em&gt;restart addon to take effect&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Profit?!&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2&gt;What is DNSCrypt Proxy?&lt;/h2&gt;
&lt;p&gt;By default DNS traffic (&lt;em&gt;TCP &amp;amp; UDP 53&lt;/em&gt;) is not encrypted, i.e. visible to snoopers; not all devices, especially IoT devices support modern encrypted DNS protocols like &lt;a href="https://en.wikipedia.org/wiki/DNS_over_HTTPS"&gt;DoH&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/DNS_over_TLS"&gt;DoT&lt;/a&gt; so DNSCrypt Proxy is a way of securing DNS for those devices -- they send clear text DNS to the proxy, it encrypts the traffic up to your chosen DNS provider.&lt;/p&gt;
&lt;h2&gt;Why DNSCrypt Proxy?&lt;/h2&gt;
&lt;p&gt;This is choice depending on your security preferences/requirements, do you need or want encrypted DNS? Generally encrypting as much of your traffic as you can is a good thing, but if you don't agree that's ok:&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/09/threat-model-sm.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;h2&gt;How to install DNSCrypt Proxy.&lt;/h2&gt;
&lt;p&gt;DNSCrypt Proxy is presented as an addon, which are Home Assistant containers, get 3rd party addons you first have to setup a repository,&lt;/p&gt;
&lt;h3&gt;Step 1 - My Addon Repository&lt;/h3&gt;
&lt;p&gt;Within Home Assistant, perform the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Settings -&amp;gt; Add-ons -&amp;gt; ADD-ON STORE&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;In the top right &lt;code&gt;3x Dots&lt;/code&gt;, select &lt;code&gt;Repositories&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add https://github.com/linickx/ha-addons&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;... Using the same top right &lt;code&gt;3x Dots&lt;/code&gt;, click check for updates. It also doesn't hurt to refresh your browser.&lt;/p&gt;
&lt;h3&gt;Step 2 - Install&lt;/h3&gt;
&lt;p&gt;With a little luck, now in Home Assistant under &lt;code&gt;Settings -&amp;gt; Add-ons -&amp;gt; ADD-ON STORE&lt;/code&gt;, if you scroll to the bottom you should see this:&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/09/linickx-addons-dnscrypt.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;p&gt;✨ Click it! ✨&lt;/p&gt;
&lt;p&gt;Then, click &lt;code&gt;Install&lt;/code&gt;, and once it's installed, click &lt;code&gt;Start&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;How to configure DNSCrypt Proxy.&lt;/h2&gt;
&lt;p&gt;DNSCrypt &lt;a href="https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Configuration"&gt;configuration is a .toml file&lt;/a&gt;; the easiest way to edit it in Home Assistant is with &lt;a href="https://github.com/hassio-addons/addon-vscode"&gt;the VSCode Add-on&lt;/a&gt;, if your a terminal ninja use Vi in SSH.&lt;/p&gt;
&lt;p&gt;Edit 👉🏻 &lt;code&gt;/addon_configs/ba53f40c-dnscrypt-proxy/dnscrypt-proxy.toml&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;File Path Warning!&lt;/h3&gt;
&lt;p&gt;The DNSCrypt proxy runs as a container, the path you edit (from VSCode/SSH) is different to what the container sees, i.e.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/addon_configs/ba53f40c-dnscrypt-proxy/dnscrypt-proxy.toml&lt;/code&gt; == &lt;code&gt;/config/dnscrypt-proxy.toml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So, if you need to include any external files, such as blocklists the use the later &lt;em&gt;container&lt;/em&gt; path of &lt;code&gt;/config/&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;/Done!&lt;/h2&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Sat, 27 Sep 2025 12:08:00 +0100</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-09-27:dnscrypt-proxy-on-home-assistant</guid><category>Security</category><category>HomeAssistant</category></item><item><title>Home Assistant on KVM - Disable Secure Boot</title><link>https://www.linickx.com/home-assistant-on-kvm---disable-secure-boot</link><description>&lt;p&gt;The documentation for running &lt;a href="https://www.home-assistant.io/installation/alternative#hypervisor-specific-configuration"&gt;HAOS on KVM&lt;/a&gt; is pretty good but not enough for me, in fairness it state that &lt;em&gt;Secure Boot&lt;/em&gt; is not supported, but the clues given to disable that are a little cryptic, this post are my notes.&lt;/p&gt;
&lt;h2&gt;Preface: Some personal tweaks.&lt;/h2&gt;
&lt;p&gt;I used the &lt;code&gt;virt-install&lt;/code&gt; command given, but the default tries to connect to the console -- which without secure boot disabled is just a blank screen, so &lt;code&gt;--noautoconsole&lt;/code&gt; is needed.&lt;/p&gt;
&lt;p&gt;Also, I don't have a default network, all my VM's are on a bridge interface which means I also need &lt;code&gt;--network bridge=br0&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So, my final install command looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;virt-install --name haos --description &amp;quot;Home Assistant OS&amp;quot; --os-variant=generic --ram=4096 --vcpus=2 --disk /opt/haos/haos_ova-16.2.qcow2,bus=scsi --controller type=scsi,model=virtio-scsi --import --graphics none --boot uefi --network bridge=br1 --noautoconsole
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;( &lt;em&gt;Change your disk path as necessary&lt;/em&gt; )&lt;/p&gt;
&lt;h2&gt;Now: To disable secure boot.&lt;/h2&gt;
&lt;p&gt;You VM is probably running, but not working, shut it down with &lt;code&gt;sudo virsh shutdown haos&lt;/code&gt; it might be stuck, so you might have to use &lt;code&gt;sudo virsh destroy hasos&lt;/code&gt; to forcefully kill it.&lt;/p&gt;
&lt;p&gt;Now run &lt;code&gt;sudo virsh edit haos&lt;/code&gt;, this should open an XML like this screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/09/Some-XML-from-KVM.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;p&gt;It doesn't matter if it's not exactly the same, your hypervisor might have selected a different EFI firmware. Next steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change &lt;em&gt;enrolled-keys&lt;/em&gt; to &lt;code&gt;no&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Change &lt;em&gt;secure-boot&lt;/em&gt; to &lt;code&gt;no&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;👉🏼 &lt;strong&gt;Delete the line starting with&lt;/strong&gt; &lt;code&gt;&amp;lt;loader readonly='yes' ...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;👉🏼 &lt;strong&gt;Delete the line starting with&lt;/strong&gt;  &lt;code&gt;&amp;lt;nvram template= ...&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The final XML snippet should look something like:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;os firmware='efi'&amp;gt;
    &amp;lt;type arch='x86_64' machine='pc-i440fx-10.0'&amp;gt;hvm&amp;lt;/type&amp;gt;
    &amp;lt;firmware&amp;gt;
      &amp;lt;feature enabled='no' name='enrolled-keys'/&amp;gt;
      &amp;lt;feature enabled='no' name='secure-boot'/&amp;gt;
    &amp;lt;/firmware&amp;gt;
    &amp;lt;boot dev='hd'/&amp;gt;
&amp;lt;/os&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;First boot: Reset nvram.&lt;/h2&gt;
&lt;p&gt;After making the above changes, when you start (&lt;em&gt;power-on&lt;/em&gt;) the machine for the first time you need to get KVM to select a new firmware, so run:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;virsh start haos --reset-nvram
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that's been done once, then normal start should work, even autostart.&lt;/p&gt;
&lt;h2&gt;Done!&lt;/h2&gt;
&lt;p&gt;I use &lt;a href="https://cockpit-project.org"&gt;cockpit&lt;/a&gt; to manage my KVMs, this is what it looks like! 😊&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/09/HomeAssiatnt-KVM-Cockpit.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;h3&gt;References:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;https://libvirt.org/kbase/secureboot.html#changing-an-existing-vm&lt;/li&gt;
&lt;li&gt;https://www.home-assistant.io/installation/alternative#hypervisor-specific-configuration&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Sun, 21 Sep 2025 13:48:00 +0100</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-09-21:home-assistant-on-kvm---disable-secure-boot</guid><category>HomeAssistant</category><category>KVM</category><category>Linux</category></item><item><title>Keebio IRIS layout &amp; printout for MacOS</title><link>https://www.linickx.com/keebio-iris-layout--printout-for-macos</link><description>&lt;p&gt;I spent 3 hours on this so you don't have too, well many credits goes to &lt;a href="https://benwilliamson.com/keyboard/"&gt;this guy, Ben Williamson for publishing his layout which I modified.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The nice people at &lt;a href="https://keeb.io"&gt;Keeb.io&lt;/a&gt; ship their IRIS keyboards with a handy print out that shows all the default keys &amp;amp; layers, which is American. Out of the box, I needed to make some changes such as moving &lt;code&gt;|&lt;/code&gt;, I also wanted the OSX Mission Control buttons, and then I moved &lt;em&gt;Enter&lt;/em&gt; because I really don't understand the default thumb assignment, after 5 minutes tinkering I realised I no longer knew where a bunch of keys were and the print out wasn't helping.&lt;/p&gt;
&lt;p&gt;This is my solution:&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/07/keeb-io-iris.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👉🏻 &lt;a href="https://www.linickx.com/files/2025/07/keeb-io-iris.use-via-layout.json"&gt;keeb-io-iris.use-via-layout.json&lt;/a&gt; - Load this into &lt;a href="https://usevia.app/"&gt;usevia.app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;👉🏻 &lt;a href="https://www.linickx.com/files/2025/07/keeb-io-iris.print-layout.json"&gt;keeb-io-iris.print-layout.json&lt;/a&gt; - Load this into &lt;a href="https://www.keyboard-layout-editor.com/"&gt;www.keyboard-layout-editor.com&lt;/a&gt; or &lt;a href="https://www.keyboard-layout-editor.com/#/gists/b1911fd44732a21679d701546171be14"&gt;click here&lt;/a&gt; to &lt;a href="https://gist.github.com/linickx/b1911fd44732a21679d701546171be14"&gt;load this gist&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From there you can either print out the graphic and work, or make your customisations!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Mon, 21 Jul 2025 16:29:00 +0100</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-07-21:keebio-iris-layout--printout-for-macos</guid><category>MacOS</category><category>Apple</category><category>OSX</category><category>UseVIA</category><category>QMK</category><category>Keyboard</category></item><item><title>Removing Modules from Netatmo Weather Station</title><link>https://www.linickx.com/removing-modules-from-netatmo-weather-station</link><description>&lt;p&gt;Last Year, storms in the UK caused damage to my Netatmo outdoor module, it became permanently disconnected from the indoor base station.&lt;/p&gt;
&lt;p&gt;The iPhone app seems to require a working module to remove it, i.e. it wants to connect first before letting you delete it, which not only is a bit weird but of course doesn't work if the module is broken. After logging a ticket with Netatmo's support team, they eventually shared these two links...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://n3twizard.blob.core.windows.net/wizard/NetatmoModulesManager_Windows.exe"&gt;Module Manager for Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://n3twizard.blob.core.windows.net/wizard/NetatmoModulesManager_MacOS.dmg"&gt;Module Manager for MacOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="/files/2025/02/Netatmo_WeatherStation_Module_Manager.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;p&gt;With this, you can connect the base station to your Mac/PC and delete the modules from there, nice!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Thu, 06 Feb 2025 17:34:00 +0000</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-02-06:removing-modules-from-netatmo-weather-station</guid><category>IoT</category><category>Netatmo</category></item><item><title>Python: Uploading to Legacy SharePoint On Premise</title><link>https://www.linickx.com/python-uploading-to-legacy-sharepoint-on-premise</link><description>&lt;p&gt;Finding this solution via Google/Bing/etc was just impossible, so this post is an attempt to make this easier.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Some Important Information:&lt;/em&gt; If you're using SharePoint online, i.e. a cloud solution, something part of office365 or whatever it's called today, this post is &lt;strong&gt;NOT&lt;/strong&gt; for you; there are plenty of python posts, libraries and packages for that, this is what you need to do if you business is still running a legacy on-prem solution and the normal things don't work.&lt;/p&gt;
&lt;p&gt;This solution uses the old REST API, now there is some kind of relationship with &lt;code&gt;accounts.accesscontrol.windows.net&lt;/code&gt; and I have no idea why?!&lt;/p&gt;
&lt;h2&gt;My story.&lt;/h2&gt;
&lt;p&gt;For "reasons" my &lt;code&gt;$work&lt;/code&gt; has both online and on-prem solutions, the online one works great and that's what I normally dealt with but due to "reasons" I needed to upload to on-prem. After hours of googling, and trying different things in python, I gave up and wrote my solution in PowerShell using the &lt;a href="https://pnp.github.io/powershell/"&gt;PNP PowerShell Module&lt;/a&gt; which got me over the initial hurdle but since the rest of my project was in python it was only a tactical fix.&lt;/p&gt;
&lt;p&gt;To solve this in python, I started initially with Wireshark and a man-in-the-middle proxy and pulling out the REST calls, &lt;code&gt;get_access_token()&lt;/code&gt; was written that way but it was painful, it really wasn't clear to me how file uploads was working. I left it for a while, the tactical fix was still ok.&lt;/p&gt;
&lt;h2&gt;My first AI win!&lt;/h2&gt;
&lt;p&gt;A new scenario came up, I needed to get data from my DB and create a file in this legacy SharePoint, so either I was gonna have to start talking to my DB in PowerShell or solve this in python. As is the trend in ~2024~ 2025 we now ask GenAI, &lt;strong&gt;OF COURSE THE CODE SUGGESTED WAS WRONG AND DIDN'T WORK&lt;/strong&gt; but that's what we expect right?&lt;/p&gt;
&lt;p&gt;However, the code suggested did give me some clues, based on the suggestion I was able to start tweaking the code and &lt;em&gt;ta-da&lt;/em&gt;! it works, I could upload the file! A few more questions, a bit of googling and tweaking I even managed to update the metadata. I did not get as far as listing/finding existing files and performing a download as currently I don't need to, but if I do, maybe I'll update this post.&lt;/p&gt;
&lt;h2&gt;Some Sharepoint Stuff...&lt;/h2&gt;
&lt;p&gt;On my SharePoint document library, I've created a custom column/field for the sha256 sum of the uploaded file; if you want that replace &lt;code&gt;x0034_ha256&lt;/code&gt; with whatever your field code is... notice the code is &lt;em&gt;not&lt;/em&gt; the name, so create the column, then edit it and in the address bar of your browser you can see the code.&lt;/p&gt;
&lt;p&gt;If you don't need the sha256, just comment out &amp;amp; remove &lt;code&gt;update_file_properties()&lt;/code&gt; &lt;/p&gt;
&lt;h2&gt;My Python Code.&lt;/h2&gt;
&lt;p&gt;I hope this is useful to someone, good luck!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;#!/usr/bin/env python
# coding=utf-8
# Python linter configuration.
# pylint: disable=W0718 # Broad Except
import logging
import requests # pip install requests

logging.basicConfig(level=logging.DEBUG)

CLIENT_ID = &amp;quot;replace_me&amp;quot;
CLIENT_SECRET = &amp;quot;replace_me_too&amp;quot;
SITE_HOST = 'sharepoint.domain.com'
SITE_NAME = 'ABC123'
SITE_URL = f'https://{SITE_HOST}/sites/{SITE_NAME}'
UPLOAD_FOLDER = &amp;quot;Documents/Uploaded Files&amp;quot;
SHAREPOINT_LIBRARY = &amp;quot;Documents&amp;quot;
FILE_PATH = &amp;quot;test.txt&amp;quot;
FILE_TITLE = &amp;quot;this is a title for test.txt&amp;quot;
FILE_HASH_COL = '_x0034_ha256'
FILE_HASH_VALUE = 'abc123' # Replace with the actual hash value

def get_access_token():
    &amp;quot;&amp;quot;&amp;quot;
        # Step 1: Obtain an access token
    &amp;quot;&amp;quot;&amp;quot;
    r = requests.get(f&amp;quot;{SITE_URL}/_vti_bin/client.svc&amp;quot;, timeout=10, headers={'Authorization': 'Bearer', 'Accept': 'application/json'})

    logging.debug(r.status_code) # &amp;lt;- 401
    logging.debug(r.headers['WWW-Authenticate'])

    auth_headers = {}
    for ah in str(r.headers['WWW-Authenticate']).split(','):
        key = str(ah.split('=')[0]).strip()
        try:
            val = str(ah.split('=')[1]).replace('&amp;quot;', &amp;quot;&amp;quot;)
        except IndexError:
            val = None

        auth_headers[key] = val

    logging.debug(auth_headers)
    logging.debug(r.json())

    data = {
        'grant_type':'client_credentials',
        'client_id':f&amp;quot;{CLIENT_ID}@{auth_headers['Bearer realm']}&amp;quot;,
        'client_secret':CLIENT_SECRET,
        'scope':f&amp;quot;{auth_headers['client_id']}/{SITE_HOST}@{auth_headers['Bearer realm']}&amp;quot;,
        'resource':f&amp;quot;{auth_headers['client_id']}/{SITE_HOST}@{auth_headers['Bearer realm']}&amp;quot;,
    }
    response = requests.post(f&amp;quot;https://accounts.accesscontrol.windows.net/{auth_headers['Bearer realm']}/tokens/OAuth/2&amp;quot;, timeout=10, data=data)
    logging.debug(response.status_code) # &amp;lt;- 200
    logging.debug(response.json())

    if response.status_code == 200:
        return response.json().get('access_token')

    response.raise_for_status()
    return None


def upload_file(access_token):
    &amp;quot;&amp;quot;&amp;quot;
        # Step 2: Upload the file to SharePoint
    &amp;quot;&amp;quot;&amp;quot;
    upload_url = f&amp;quot;{SITE_URL}/_api/web/GetFolderByServerRelativeUrl('{UPLOAD_FOLDER}')/Files/add(url='{FILE_PATH}', overwrite=true)&amp;quot;

    with open(FILE_PATH, 'rb') as file:
        headers = {
            &amp;quot;Authorization&amp;quot;: f&amp;quot;Bearer {access_token}&amp;quot;,
            &amp;quot;Accept&amp;quot;: &amp;quot;application/json;odata=verbose&amp;quot;,
            &amp;quot;Content-Type&amp;quot;: &amp;quot;application/octet-stream&amp;quot;
        }
        response = requests.post(upload_url, headers=headers, data=file, timeout=10)

    logging.debug(response.json())

    if response.status_code == 200:
        logging.info(&amp;quot;File uploaded successfully!&amp;quot;)
        return response.json()  # Return the response to use the returned file info

    response.raise_for_status()
    return None

def update_file_properties(access_token, file_info):
    &amp;quot;&amp;quot;&amp;quot;
    # Step 3: Update the file properties (Title and Custom Column)
    &amp;quot;&amp;quot;&amp;quot;
    update_url = file_info['d']['ListItemAllFields']['__deferred']['uri']
    logging.debug(update_url)
    file_type = file_info['d']['__metadata']['type']
    logging.debug(file_type)
    e_tag = file_info['d']['ETag']
    logging.debug(e_tag)

    # Payload for the update
    payload = {
        '__metadata': {'type': 'SP.Data.Internal_x0020_DocumentsItem'},
        'Title': FILE_TITLE,
        'OData__x0034_ha256': FILE_HASH_VALUE
    }

    headers = {
        &amp;quot;Authorization&amp;quot;: f&amp;quot;Bearer {access_token}&amp;quot;,
        &amp;quot;Accept&amp;quot;: &amp;quot;application/json;odata=verbose&amp;quot;,
        &amp;quot;Content-Type&amp;quot;: &amp;quot;application/json;odata=verbose&amp;quot;,
        &amp;quot;IF-MATCH&amp;quot;: &amp;quot;*&amp;quot;,            # Update the file regardless of the current version
        &amp;quot;X-HTTP-Method&amp;quot;: &amp;quot;MERGE&amp;quot;    # Specify the method for updating
    }

    response = requests.post(update_url, headers=headers, json=payload, timeout=10)

    if response.status_code == 204:
        logging.info(&amp;quot;File properties updated successfully!&amp;quot;)
        logging.debug(response.text)
    else:
        response.raise_for_status()

if __name__ == &amp;quot;__main__&amp;quot;:
    try:
        token = get_access_token()               # Obtain access token
        json_info = upload_file(token)           # Upload the file with the token
        update_file_properties(token, json_info) # Update the file properties
    except Exception as e:
        logging.error(&amp;quot;An error occurred: %s&amp;quot;, e)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;ha-ha-ha, GenAI doesn't do that... but this is relevant: https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Thu, 16 Jan 2025 17:36:00 +0000</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-01-16:python-uploading-to-legacy-sharepoint-on-premise</guid><category>python</category><category>Microsoft</category></item><item><title>IoT DNS Anomaly Detection with Home Detector</title><link>https://www.linickx.com/iot-dns-anomaly-detection-with-home-detector</link><description>&lt;p&gt;After implementing &lt;a href="https://www.linickx.com/honeypot-running-open-canary-on-home-assistant"&gt;an Open-Canary based home honeypot in part 1&lt;/a&gt;, for my research project I moved onto implementing a DNS based anomaly detection intrusion detection system ... try saying that 3 times fast after a few pints! 😆&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;📝 This post assumes that you already &lt;a href="https://github.com/linickx/HomeDetector/blob/main/docs/INSTALL.md"&gt;have Home Detector installed&lt;/a&gt; on your Home Assistant server.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The idea is an internal, home network honeypot would only trigger if there was already a threat on your LAN, in order to &lt;em&gt;attempt&lt;/em&gt; to catch someone/something earlier I built a simple DNS anomaly detection engine; there's an important gotcha here, although the honeypot was low-effort-drop-in (plug-n-play), DNS inspection is a bit more &lt;em&gt;technical&lt;/em&gt; you will need a method of updating the DNS settings on your IoTs to make this work, either by changing your DHCP setting, doing something on your router, or by touching each device (if they support custom DNS that is!).&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;Home Detector acts as a local DNS forwarder, point your IoT/Smart-Things at it and for 30days it'll start recording the DNS lookups. After 30days, it'll consider what it saw as &lt;em&gt;the baseline&lt;/em&gt; and therefore anything new after that point will generate an alert.&lt;/p&gt;
&lt;p&gt;The baseline is per  &lt;em&gt;IOT thing&lt;/em&gt;, which can be a single host IP, a range of IPs or a subnet depending on your home setup, so you're going to need the real-source-ip of your &lt;em&gt;IOT thing&lt;/em&gt; hitting Home Assistant (The Home Detector Add-on)&lt;/p&gt;
&lt;h2&gt;Enable DNS Interception&lt;/h2&gt;
&lt;p&gt;The DNS interception is &lt;strong&gt;opt-in&lt;/strong&gt; which means there's 2x steps:&lt;/p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;The first is point your system at it, i.e. update the DNS settings of the IOT device to have Home Assistant's IP as a DNS server. &lt;/p&gt;
&lt;p&gt;How you do this will vary, you might be able to update your router to use Home Assistant as the DNS server for all your LAN. You might be able to change the DNS server on the IoT device it's self. Or if you cannot change DNS &lt;em&gt;anywhere&lt;/em&gt;, disable DHCP on your router and &lt;a href="https://github.com/home-assistant/addons/blob/master/dhcp_server/DOCS.md"&gt;install a DHCP server add-on&lt;/a&gt; and set the DNS server IP to that of Home Assistant.&lt;/p&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;It's ok if &lt;em&gt;all&lt;/em&gt; your DNS hits Home Detector (Home Assistant) as by default, the add-on will pass through, not touching the responses and everything should continue to work.&lt;/p&gt;
&lt;p&gt;To enable the detection, under add-on settings, enable interception for specific IP addresses, like this:&lt;/p&gt;
&lt;p&gt;Tweak any other &lt;a href="https://github.com/linickx/ha-addons/blob/main/homedetector/DOCS.md"&gt;settings you fancy from the Docs&lt;/a&gt; as necessary.&lt;/p&gt;
&lt;h2&gt;Enjoy the DNS goodness&lt;/h2&gt;
&lt;p&gt;Within the Home Detector Dashboard, there are 3x views.&lt;/p&gt;
&lt;h3&gt;(i) The Alerts&lt;/h3&gt;
&lt;p&gt;By default, Home Detector will generate &lt;code&gt;dns-domain&lt;/code&gt; alerts, there are alarms for new &lt;em&gt;domains&lt;/em&gt; being queried, the SOA record is used to determine domain ownership.&lt;/p&gt;
&lt;p&gt;If you enabled &lt;em&gt;Detected on Host Query&lt;/em&gt; then Home Detector will generate &lt;code&gt;dns-query&lt;/code&gt; alerts, these are alarms for new &lt;em&gt;host queries&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here you can see a bunch of Amazon Alexa alerts on my console, these are new domains that the very talkative little box has started calling out to...&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/01/home-detector-dns-alerts.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;h3&gt;(ii) The DNS Domains&lt;/h3&gt;
&lt;p&gt;On the Domains page, you can review the domains that are in &lt;code&gt;pass&lt;/code&gt; state or &lt;code&gt;block&lt;/code&gt; state, for the first 30days (by default) all domains will be in pass, only after the baseline is created will &lt;em&gt;blocks&lt;/em&gt; start to appear.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🔥 By Default, &lt;strong&gt;&lt;em&gt;Block does not mean Block&lt;/em&gt;&lt;/strong&gt;, it means 🚨 alarm 🚨 (&lt;em&gt;perhaps not my best choice&lt;/em&gt;). Only if you enable the DNS Firewall under settings will the DNS be blocked, Home Detector will send &lt;code&gt;NXDOMAIN&lt;/code&gt; (&lt;em&gt;domain not found&lt;/em&gt;) responses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is what my domains page looks like, the first range for &lt;code&gt;ntp.org&lt;/code&gt; is for my shelly devices, the next 5x are for my heating/themostat, and then the bottom ranges are for alexa's... as you can see there's 135 row, quite a lot of learnt traffic in my LAN.... and this is &lt;strong&gt;JUST&lt;/strong&gt; the IoT devices, Phones/Laptops/etcs do not log here and in my documentation I warn against doing that 😬&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/01/home-detector-dns-domains.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;h3&gt;(iii) The Queries&lt;/h3&gt;
&lt;p&gt;Like the domains page, the queries page allows you to review all the look-ups from a device in either &lt;code&gt;pass&lt;/code&gt; or &lt;code&gt;block&lt;/code&gt; state.&lt;/p&gt;
&lt;h2&gt;Why am I doing this?&lt;/h2&gt;
&lt;p&gt;If you've got this far, 👍🏼 nice 👍🏼 !&lt;/p&gt;
&lt;p&gt;The point of this is to monitor what your IoT/Smart-Things are doing, you should get an idea quickly of what is normal, and &lt;strong&gt;IF&lt;/strong&gt; a device got compromised it would certainly start doing &lt;em&gt;different&lt;/em&gt; queries, like downloading malware-firmware, or downloading scripts from compromised sites... Command-and-Control needs DNS to function.&lt;/p&gt;
&lt;h2&gt;A word of Warning&lt;/h2&gt;
&lt;p&gt;The noise from my home stuff has been low, shelly, etc have a couple of domains and everything works as expected, but with 👾 Amazon Alexa devices there be monsters ahead! 👾  ... those things seem to be constantly using new hosts and new domains, it's eye-opening but also annoying, so intercept those things with care.&lt;/p&gt;
&lt;h2&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;There's a fair amount of &lt;em&gt;future work&lt;/em&gt; I'd like to look at,  changing domains from &lt;em&gt;pass&lt;/em&gt; to &lt;em&gt;block&lt;/em&gt; by typing instead of drop-downs is quite annoying 💩 ... also, I'd like to implement some built-in signatures to assert what is normal before the learning phase is completed. Pull requests are welcome but the first thing I need to do is update all the dependencies, as since finishing the project, github's dependabot has been going mental! &lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Sun, 05 Jan 2025 18:01:00 +0000</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-01-05:iot-dns-anomaly-detection-with-home-detector</guid><category>Security</category><category>Home Assistant</category><category>Home Detector</category></item><item><title>Honeypot: Running Open Canary on Home Assistant</title><link>https://www.linickx.com/honeypot-running-open-canary-on-home-assistant</link><description>&lt;p&gt;This project, 🎉 &lt;a href="https://github.com/linickx/HomeDetector"&gt;Home Detector&lt;/a&gt; 🎉 , started life as an academic project and is something I hope to continue, if you're interested in some home intrusion detection, read-on! &lt;/p&gt;
&lt;h2&gt;Some Background &amp;amp; Context&lt;/h2&gt;
&lt;p&gt;In my 40s, I have decided to go back to school and for my MSc final thesis I researched intrusion detection for &lt;em&gt;home networks&lt;/em&gt; 😱 . The lens was simple do we &lt;em&gt;know&lt;/em&gt; if our home LAN/Wi-Fi is under attack, does your Dad, Nan, Uncle or Aunt... even as a &lt;em&gt;nerd&lt;/em&gt; reading this blog, do you have any intrusion detection at home?! (Hint: I didn't!)&lt;/p&gt;
&lt;p&gt;It turns out, intrusion detection at home is &lt;em&gt;hard&lt;/em&gt;, sure you can install HIDS (&lt;em&gt;Host Intrusion Detection Systems&lt;/em&gt;) on your Laptop/PC but what about your phone, table or internet-enabled-fridge! 🤔 &lt;/p&gt;
&lt;p&gt;The last-one is the kicker, as a Home Assistant fan, I've got more and more smart-home, IoT stuff, how would I detect Mira-worm style compromise? ... do I even know what my IoT stuff is doing when I'm not looking?! NIDS (&lt;em&gt;Network Intrusion Detection Systems&lt;/em&gt;) of course are &lt;em&gt;an&lt;/em&gt; answer but not &lt;em&gt;that&lt;/em&gt; practical, do you have a pinch-point to inspect/tap... what about networks with all-in-one Wi-Fi+Router, how do you inspect that?&lt;/p&gt;
&lt;p&gt;In my paper, I proposed 2x solutions, this is &lt;strong&gt;Part 1 - A Honeypot&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;A honeypot is know as Intrusion Detection &lt;em&gt;via Deception&lt;/em&gt;, that is you place a juicy target on your network to draw attention away from your real stuff, when the threat actor trips the alarm you know about it; of course the threat actor is &lt;em&gt;already&lt;/em&gt; on a device, but this is the point, how would you know? The honeypot approach is a something-is-better-than-nothing approach, if your CCTV is compromised, and the threat is looking for another device and they fire your honeypot you have &lt;strong&gt;an alarm&lt;/strong&gt; to respond to. 🚨&lt;/p&gt;
&lt;h2&gt;Installing my Home Detector Add-On&lt;/h2&gt;
&lt;p&gt;I've wrapped up &lt;a href="https://github.com/thinkst/opencanary"&gt;Open Canary&lt;/a&gt; into a Home Assistant Add-on, so installation is easy:&lt;/p&gt;
&lt;h3&gt;1. Install my Add-on Repository&lt;/h3&gt;
&lt;p&gt;To get my add-on, you can either &lt;a href="https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Flinickx%2Fha-addons"&gt;click this link to add my repository&lt;/a&gt; or follow these manual steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click Settings,&lt;/li&gt;
&lt;li&gt;Click Add-ons,&lt;/li&gt;
&lt;li&gt;Click Add-On Store,&lt;/li&gt;
&lt;li&gt;Click The three dots in the top-right,&lt;/li&gt;
&lt;li&gt;Click Repositories,&lt;/li&gt;
&lt;li&gt;Type in: &lt;code&gt;https://github.com/linickx/ha-addons&lt;/code&gt; and Click Add&lt;/li&gt;
&lt;li&gt;Click The three dots in the top-right,&lt;/li&gt;
&lt;li&gt;Click Check for Updates&lt;/li&gt;
&lt;li&gt;Refresh the page a couple of times&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Install Home Detector&lt;/h3&gt;
&lt;p&gt;Once you've got &lt;a href="https://github.com/linickx/ha-addons"&gt;the repo&lt;/a&gt;' setup, scroll down to the bottom and install Home Detector.&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/01/linickx-addons-home-detector.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;p&gt;Make sure the add-on is started &amp;amp; you're done.&lt;/p&gt;
&lt;h2&gt;Look Ma! I'm running a Telnet Honey Pot&lt;/h2&gt;
&lt;p&gt;With no config, and just a running add-on you have a Telnet honeypot. If you try to connect (&amp;amp; fail auth) you'll get a pop-up notification in Home Assistant.&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/01/home-detector-ha-notification-for-telnet.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;p&gt;And an entry in the Home Detector dashboard.&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/2025/01/home-detector-telnet-alert.png" class="img-fluid" &gt;&lt;/p&gt;
&lt;p&gt;If you have SSH running, telnet will look like a weaker target for anyone running a sneaky port-scan on your LAN.&lt;/p&gt;
&lt;h2&gt;Enabling the HTTP (NAS Like) Honeypot&lt;/h2&gt;
&lt;p&gt;If you want to step-up, you can enable The HTTP honeypot which presents a NAS like log-in page.&lt;/p&gt;
&lt;p&gt;Enabling is simply opening the port and re-starting the add-on!&lt;/p&gt;
&lt;p&gt;To enable the port, &lt;em&gt;within Home Assistant&lt;/em&gt; go to &lt;code&gt;Settings&lt;/code&gt; -&amp;gt; &lt;code&gt;Add-Ons&lt;/code&gt; -&amp;gt; &lt;code&gt;Home Detector&lt;/code&gt; -&amp;gt; &lt;code&gt;Configuration&lt;/code&gt; , scroll to the bottom to &lt;code&gt;Network&lt;/code&gt; and &lt;em&gt;toggle&lt;/em&gt; &lt;code&gt;Show disabled ports&lt;/code&gt;, then type in &lt;em&gt;80&lt;/em&gt; where it says &lt;code&gt;HoneyPot (Fake) WebServer Port&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;The cyber-kill-chain&lt;/h2&gt;
&lt;p&gt;At this point, it's important to remember the modus operandi of a threat actor. The first step is always some kind of reconnaissance even after compromise, there's usually another round of reconnaissance to pivot and further secure the footing, so if your CCTV is compromised, the default port-scan of home assistant (without SSH by default) doesn't look that &lt;em&gt;interesting&lt;/em&gt;, the default admin port (8123) is above nmap's default range, by enabling the Telnet (&amp;amp; HTTP) honeypot, these &lt;em&gt;interesting&lt;/em&gt; ports will appear in a default nmap, so the likelihood of detection increases and therefore the opportunity to &lt;em&gt;kill&lt;/em&gt; the threat actors chain of actions.&lt;/p&gt;
&lt;h2&gt;Contributing&lt;/h2&gt;
&lt;p&gt;Open Canary has ✨ &lt;em&gt;loads&lt;/em&gt; ✨ of features &amp;amp; customisation, none of which have been implemented here yet, but I would certainly love to implement some more features... top of my list, custom Web Theme for the HTTP Honeypot, pull requests welcome, I am only &lt;em&gt;just&lt;/em&gt; about ready to start accepting merges, I had to wait for marking of my paper to be completed and 😊&lt;/p&gt;
&lt;h2&gt;Coming up in Part 2...&lt;/h2&gt;
&lt;p&gt;For my paper I moved onto &lt;code&gt;DNS anomaly detection&lt;/code&gt;, as a way of detecting compromised IoT earlier than a threat actor trying to pivot, please take a look 👉🏻 &lt;a href="iot-dns-anomaly-detection-with-home-detector"&gt;HERE&lt;/a&gt; 👈🏼 if you're interested in home cyber security.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Wed, 01 Jan 2025 12:43:00 +0000</pubDate><guid isPermaLink="false">tag:www.linickx.com,2025-01-01:honeypot-running-open-canary-on-home-assistant</guid><category>Security</category><category>Home Assistant</category><category>Open Canary</category><category>Home Detector</category></item><item><title>Goodbye root-cookie</title><link>https://www.linickx.com/goodbye-root-cookie</link><description>&lt;p&gt;&lt;code&gt;TLDR:&lt;/code&gt; 🔥🔥🔥 If you still use root-cookie, please delete it from your WordPress/Website 🔥🔥🔥🔥&lt;/p&gt;
&lt;p&gt;Today I have requested that the Plugins team over at WordPress.org org delete &lt;a href="https://wordpress.org/plugins/root-cookie"&gt;my root-cookie plugin&lt;/a&gt;. I started it back in &lt;a href="https://www.linickx.com/root-cookie-for-wp26"&gt;2008 for WP 2.6&lt;/a&gt;, probably before if you dig into the SVN history, back when things were very different.&lt;/p&gt;
&lt;p&gt;Back in the early days of WordPress, it was a &lt;em&gt;"sub directory"&lt;/em&gt;, i.e. you setup your site with a home page, and then WordPress (blog) was a below that. The problem root-cookie was designed to solve, is that there was no way of accessing the WordPress authentication cookie outside the WordPress folder, so if you wanted to something as simple as change a banner, or theme based on being logged in, you could't. root-cookie was very simple, it hooked into WordPress's authentication functions and stripped the folder out of the cookie, and assigned it to the "root" of the domain, then from your custom code you could read it and do &lt;em&gt;whatever&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I really, &lt;em&gt;really&lt;/em&gt; cannot remember what the admin page did or looked like, there's probably some screenshots around here but apparently it contains a Cross Site Request Forgery (CSRF) vulnerability, the steps (&lt;em&gt;apparently, I've not tested&lt;/em&gt;) to reproduce are:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make a logged in admin click a link with the following HTML (replace the domain)&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;body onload=&amp;quot;document.forms[0].submit()&amp;quot;&amp;gt;
&amp;lt;form action=&amp;quot;http://{domain}/wp-admin/options-general.php?page=root-cookie&amp;quot; method=&amp;quot;POST&amp;quot;&amp;gt;
&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;rootcookie_submit_hidden&amp;quot; value='Y' /&amp;gt;
&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;rootcookie_subdomain_manual&amp;quot; value='&amp;amp;&amp;quot;&amp;gt;&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;' /&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;REF: https://patchstack.com/&lt;/p&gt;
&lt;p&gt;👉🏻 Given that I have not maintained this plugin for &lt;strong&gt;over 13 years&lt;/strong&gt;, I do &lt;em&gt;NOT&lt;/em&gt; intend to publish an update and have requested the plugin be deleted.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;From: Nick&lt;br /&gt;
To: plugins wordpress.org&lt;br /&gt;
Date: 14 Dec 2024, 15:47&lt;br /&gt;
Subject:  Please Delete "root-cookie"&lt;br /&gt;
Body:&lt;/p&gt;
&lt;p&gt;Hello,
Please delete https://wordpress.org/plugins/root-cookie/&lt;/p&gt;
&lt;p&gt;The plugin has not been maintained in 13years, apparently recently it was discovered to contain a CSRF vulnerability, I do not intend to fix it therefore it would be safer for the community if the plugin is removed from wordpress.org.&lt;/p&gt;
&lt;p&gt;Stats show only 11 downloads per week, I don't suppose the plugin is needed anymore, the first version was released in 2008 for WP2.6, I expect a lot has changed since then :)&lt;/p&gt;
&lt;p&gt;Many Thanks in advance for your support.&lt;br /&gt;
Kind Regards,&lt;br /&gt;
Nick &lt;br /&gt;
&lt;/p&gt;
&lt;/blockquote&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Sat, 14 Dec 2024 15:59:00 +0000</pubDate><guid isPermaLink="false">tag:www.linickx.com,2024-12-14:goodbye-root-cookie</guid><category>WordPress</category><category>plugin</category><category>root-cookie</category><category>Vulnerability</category></item><item><title>Fly.io - Docker NGINX with s3fs</title><link>https://www.linickx.com/flyio---docker-nginx-with-s3fs</link><description>&lt;p&gt;I've been experimenting with fly.io; applications are Docker containers, here are some instructions to get NGINX up-n-running, with Fuse (s3fs) mounting an S3/Tigris bucket. The goal I was looking for was directy listings for the bucket, but honestly I wouldn't recommend it because it's very slooooow! ... about 5 seconds on first load.&lt;/p&gt;
&lt;p&gt;If you want to play along anyway, &lt;a href="https://github.com/linickx/fly-docker-nginxs3fs"&gt;download a copy of my github repo&lt;/a&gt;, the instructions assume that &lt;a href="https://fly.io//files/2024/08/flyctl/install/"&gt;fly-cli&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;amazon-cli&lt;/a&gt; are both already installed.&lt;/p&gt;
&lt;h2&gt;Step 1 - Fly Launch&lt;/h2&gt;
&lt;p&gt;Run &lt;code&gt;fly launch --no-deploy&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╰─❯ fly launch --no-deploy
Scanning source code
Detected a Dockerfile app
Creating app in /home/nick/fly-docker-nginxs3fs
We're about to launch your app on Fly.io. Here's what you're getting:

Organization: NB                     (fly launch defaults to the personal org)
Name:         fly-docker-nginxs3fs   (derived from your directory name)
Region:       London, United Kingdom (this is the fastest region for you)
App Machines: shared-cpu-1x, 1GB RAM (most apps need about 1GB of RAM)
Postgres:     &amp;lt;none&amp;gt;                 (not requested)
Redis:        &amp;lt;none&amp;gt;                 (not requested)
Tigris:       &amp;lt;none&amp;gt;                 (not requested)

? Do you want to tweak these settings before proceeding? (y/N) Y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Select &lt;strong&gt;Y&lt;/strong&gt;&lt;em&gt;es&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the Browser window that opens, scroll down and create a bucket...&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of fly.io console, creating a bucket" src="/files/2024/08/add-a-bucket.png" /&gt;&lt;/p&gt;
&lt;p&gt;Back on your console, some keys have been generated...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Opening https://fly.io/cli/launch/xxx[REDATED]xxx ...

Waiting for launch data... Done
Created app 'fly-docker-nginxs3fs' in organization 'personal'
Admin URL: https://fly.io/apps/fly-docker-nginxs3fs
Hostname: fly-docker-nginxs3fs.fly.dev
Run `fly tokens create deploy -x 999999h` to create a token and set it as the FLY_API_TOKEN secret in your GitHub repository settings
See https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions
Your Tigris project (mys3fstest) is ready. See details and next steps with: https://fly.io/docs/reference/tigris/

Setting the following secrets on fly-docker-nginxs3fs:
AWS_ACCESS_KEY_ID: tid_yyy[REDATED]yyy
AWS_ENDPOINT_URL_S3: https://fly.storage.tigris.dev
AWS_REGION: auto
AWS_SECRET_ACCESS_KEY: tsec_zzz[REDATED]zzz
BUCKET_NAME: mys3fstest

Wrote config file fly.toml
Validating /home/nick/fly-docker-nginxs3fs/fly.toml
✓ Configuration is valid
Your app is ready! Deploy with `flyctl deploy`
╰─❯ 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take a backup of these, as you'll never see them again!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS_ACCESS_KEY_ID&lt;/li&gt;
&lt;li&gt;AWS_SECRET_ACCESS_KEY&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Step 2- Fly Deploy&lt;/h1&gt;
&lt;p&gt;Now Deploy &lt;code&gt;fly deploy --dns-checks=false&lt;/code&gt; (&lt;em&gt;Disabling the ping to 8.8.8.8 because it's annoying!&lt;/em&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╰─❯ fly deploy --dns-checks=false
==&amp;gt; Verifying app config
Validating /home/nick/fly-docker-nginxs3fs/fly.toml
✓ Configuration is valid
--&amp;gt; Verified app config
==&amp;gt; Building image
Remote builder fly-builder-weathered-forest-2010 ready
Remote builder fly-builder-weathered-forest-2010 ready
==&amp;gt; Building image with Docker
--&amp;gt; docker host: 24.0.7 linux x86_64
[+] Building 2.0s (12/12) FINISHED
 =&amp;gt; [internal] load .dockerignore 0.4s
 =&amp;gt; =&amp;gt; transferring context: 2B 0.4s
 =&amp;gt; [internal] load build definition from Dockerfile  0.5s
 =&amp;gt; =&amp;gt; transferring dockerfile: 541B 0.5s
 =&amp;gt; [internal] load metadata for docker.io/library/nginx:alpine-slim 0.6s
 =&amp;gt; [1/7] FROM docker.io/library/nginx:alpine-slim@sha256:2be9e698d136d4d9be33d1852b1259bc1b80e20aed0c964cbcd6086da7fad5c7 0.0s
 =&amp;gt; [internal] load build context 0.5s
 =&amp;gt; =&amp;gt; transferring context: 1.14kB   0.5s
 =&amp;gt; CACHED [2/7] RUN apk update       0.0s
 =&amp;gt; CACHED [3/7] RUN apk add --no-cache openssl s3fs-fuse   0.0s
 =&amp;gt; CACHED [4/7] RUN mkdir /etc/nginx/templates             0.0s
 =&amp;gt; [5/7] COPY etc/nginx/templates/default.conf.template /etc/nginx/templates/default.conf.template   0.0s
 =&amp;gt; [6/7] COPY docker-entrypoint.d/40-s3fs.sh /docker-entrypoint.d/40-s3fs.sh   0.0s
 =&amp;gt; [7/7] RUN chmod 755 /docker-entrypoint.d/40-s3fs.sh     0.1s
 =&amp;gt; exporting to image                0.0s
 =&amp;gt; =&amp;gt; exporting layers               0.0s
 =&amp;gt; =&amp;gt; writing image sha256:73f897416cd820470a05839773fa3efc9109325985d2e4fa5c81477c14a3a5d2    0.0s
 =&amp;gt; =&amp;gt; naming to registry.fly.io/fly-docker-nginxs3fs:deployment-01J6CZAKTZP2WXQ2QC5MP4MM    0.0s
--&amp;gt; Building image done
==&amp;gt; Pushing image to fly
The push refers to repository [registry.fly.io/fly-docker-nginxs3fs]
0aa928e18663: Pushed
41551b3786e0: Pushed
3033ae542f6f: Pushed
8ad7f7ee614a: Layer already exists
bafbe3c5986a: Layer already exists
deployment-01J6CZAKTZP2WXQ2QC5MP4MM: digest: sha256:96b381cd48b63cd55c4a35e8c58ae2f5129152a11a74d9825ad10b7156fd1c12 size: 3026
--&amp;gt; Pushing image done
image: registry.fly.io/fly-docker-nginxs3fs:deployment-01J6CZAKTZP2WXQ2QC5MP4MM
image size: 25 MB

Watch your deployment at https://fly.io/apps/fly-docker-nginxs3fs/monitoring

-------
Updating existing machines in 'fly-docker-nginxs3fs' with rolling strategy

-------
 ✔ [1/2] Cleared lease for 328716d1f00668
 ✔ [2/2] Cleared lease for e7843060b496d8
-------

Visit your newly deployed app at https://fly-docker-nginxs3fs.fly.dev/
╰─❯
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Step 3 - Files in a bucket&lt;/h1&gt;
&lt;p&gt;If you browse to the URL in the terminal, you'll see a default NGINX index page. If you browse to your URL + Bucket Name, like &lt;code&gt;https://fly-docker-nginxs3fs.fly.dev/mys3fstest/&lt;/code&gt; you'll see an empty bucket.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of empty bucket via NGINX" src="/files/2024/08/empty-bucket-via-nginx.png" /&gt;&lt;/p&gt;
&lt;p&gt;To add some files, remember those credentials, you can use them with &lt;a href="https://aws.amazon.com/cli/"&gt;AWS's CLI&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╰─❯ 
export AWS_ACCESS_KEY_ID=&amp;quot;tid_yyy[REDATED]yyy&amp;quot;
export AWS_ENDPOINT_URL_S3=&amp;quot;https://fly.storage.tigris.dev&amp;quot;
export AWS_REGION=&amp;quot;auto&amp;quot;
export AWS_SECRET_ACCESS_KEY=&amp;quot;tsec_zzz[REDATED]zzz&amp;quot;
╰─❯ aws s3 ls
2024-08-28 17:52:20 mys3fstest
╰─❯ 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, let's do a &lt;em&gt;Hello World&lt;/em&gt; example...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;╰─❯ echo 'hello world' &amp;gt; test.txt
╰─❯ aws s3 cp ./test.txt s3://mys3fstest
upload: ./test.txt to s3://mys3fstest/test.txt
╰─❯ aws s3 ls s3://mys3fstest
2024-08-28 18:26:20         12 test.txt
╰─❯
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And view the results in the browser...&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of NGINX dir listing with example test.txt" src="/files/2024/08/file-in-bucket-via-nginx.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of test.txt contents, via NGINX" src="/files/2024/08/file-contents-via-nginx.png" /&gt;&lt;/p&gt;
&lt;h1&gt;End&lt;/h1&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https://github.com/s3fs-fuse/s3fs-fuse&lt;/li&gt;
&lt;li&gt;https://hub.docker.com/_/nginx&lt;/li&gt;
&lt;/ul&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Nick Bettison</dc:creator><pubDate>Thu, 29 Aug 2024 08:22:00 +0100</pubDate><guid isPermaLink="false">tag:www.linickx.com,2024-08-29:flyio---docker-nginx-with-s3fs</guid><category>fly.io</category><category>nginx</category><category>docker</category><category>s3</category><category>fuse</category><category>s3fs</category><category>aws</category></item></channel></rss>