Compare commits

...

5 Commits

14 changed files with 105 additions and 26 deletions

View File

@ -8,6 +8,7 @@ const related = require("eleventy-plugin-related");
const markdownIt = require("markdown-it");
const markdownItAnchor = require("markdown-it-anchor");
const sass = require("sass");
const footnotes = require('eleventy-plugin-footnotes');
const figure = require('./src/_includes/components/figure.js');
const bounce = require('./src/_includes/components/bounce.js');
@ -37,6 +38,10 @@ module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(syntaxHighlight);
eleventyConfig.addPlugin(timeToRead);
eleventyConfig.addPlugin(safeLinks);
eleventyConfig.addPlugin(footnotes, {
"title": "footnotes",
"baseClass": "footnotes"
});
eleventyConfig.addShortcode('figure', figure(md));
eleventyConfig.addShortcode('bounce', bounce);

View File

@ -1,4 +1,5 @@
* more fitting syntax highlighting theme
* photo gallery thing for grouped together images, looking kinda like message thing in like discord or telegram
* add an rss feed next to the atom feed for Reasons that came to me in a dream last night but i forgort
* fix template rendering error when multiple posts have same publishing date
* fix template rendering error when multiple posts have same publishing date
* add some more OG article tags specifically on article, and generally more metadata tags that may ever so slightly help with SEO and whatnot

17
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@11ty/eleventy-plugin-rss": "^1.2.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
"@sardine/eleventy-plugin-external-links": "^1.4.0",
"eleventy-plugin-footnotes": "^0.11.0",
"eleventy-plugin-related": "^1.0.6",
"eleventy-plugin-time-to-read": "^1.3.0",
"markdown-it": "^13.0.2",
@ -583,6 +584,14 @@
"fsevents": "~2.3.2"
}
},
"node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"engines": {
"node": ">=6"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -788,6 +797,14 @@
"node": ">=0.10.0"
}
},
"node_modules/eleventy-plugin-footnotes": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/eleventy-plugin-footnotes/-/eleventy-plugin-footnotes-0.11.0.tgz",
"integrity": "sha512-NQd6jNPekxIhESIIWPKUv2XXoYYknfDG8KjCdftSMGquncu1u9StVIDPmBinPChl4l68d8qTgmMXyM7kRxwGsg==",
"dependencies": {
"clsx": "^1.1.1"
}
},
"node_modules/eleventy-plugin-related": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/eleventy-plugin-related/-/eleventy-plugin-related-1.0.6.tgz",

View File

@ -12,6 +12,7 @@
"@11ty/eleventy-plugin-rss": "^1.2.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
"@sardine/eleventy-plugin-external-links": "^1.4.0",
"eleventy-plugin-footnotes": "^0.11.0",
"eleventy-plugin-related": "^1.0.6",
"eleventy-plugin-time-to-read": "^1.3.0",
"markdown-it": "^13.0.2",

View File

@ -32,6 +32,14 @@
"name": "ko-fi",
"link": "https://ko-fi.com/nyancrimew"
},
{
"name": "letterboxd",
"link": "https://letterboxd.com/nyancrimew/"
},
{
"name": "instagram",
"link": "https://instagram.com/nyancrimew"
},
{
"name": "analytics",
"link": "https://umami.crimew.gay/share/M77OUJ83Q4qBcOjZ/maia.crimew.gay"

View File

@ -16,7 +16,7 @@
<meta property="og:image" content="{% if feature_image %}{{ site.url }}{{ feature_image }}{% else %}{{ site.url }}/img/cover.jpg{% endif %}">
{% if feature_alt %}<meta property="og:image:alt" content="{{ feature_alt }}">{% endif %}
<meta property="og:site_name" content="{{ site.title }}">
<meta name="article:author" content="{{ site.name }}">
<meta name="article:author" content="{{ site.name }}{% if coauthor %},{{ coauthor.name }}{% endif %}">
{% if page.date %}<meta name="article:published_time" content="{{ page.date | date_to_datetime }}">{% endif %}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{ site.twitter }}">

View File

@ -16,7 +16,7 @@ subhead: blog
<span class="middot"></span>
<span class="readtime">{{ content | timeToRead }} to read</span>
<span class="middot"></span>
<span>by <span class="author by" id="author">{{ site.name }}</span></span>
<span>by <span class="author by" id="author">{{ site.name }}</span>{% if coauthor %} and <a class="author by" id="author" href="{{ coauthor.link }}">{{ coauthor.name }}</a>{% endif %}</span>
{% if tags %}
<span class="middot"></span>
<span>in
@ -40,6 +40,7 @@ subhead: blog
</div>
{% endif %}
{{ content | safe }}
{% footnotes %}
<a class="banner-link" href="https://ko-fi.com/nyancrimew">
<div class="kofi-banner">
if you enjoyed this or any of my other work feel free to support me on my <span class="like-a">ko-fi</span>. this is my only real source of income so anything goes a long way,

View File

@ -72,6 +72,7 @@ footer,
margin-right: auto;
padding-top: 2em;
padding-bottom: 2em;
counter-reset: footnotes;
}
table {
@ -292,4 +293,48 @@ blockquote.greentext::after {
.sleepy-zone-webring-next-site a::after {
content: "";
margin-inline-start: 1ch;
}
/**
* Inline footnotes references
* 1. Increment the counter at each new reference
* 2. Reset link styles to make it appear like regular text
*/
a[aria-describedby="footnotes-label"] {
counter-increment: footnotes; /* 1 */
text-decoration: none; /* 2 */
color: inherit; /* 2 */
cursor: default; /* 2 */
outline: none; /* 2 */
}
/**
* Actual numbered references
* 1. Display the current state of the counter (e.g. `[1]`)
* 2. Align text as superscript
* 3. Make the number smaller (since it's superscript)
* 4. Slightly offset the number from the text
* 5. Reset link styles on the number to show it's usable
*/
a[aria-describedby="footnotes-label"]::after {
content: '[' counter(footnotes) ']'; /* 1 */
vertical-align: super; /* 2 */
font-size: 0.85em; /* 3 */
margin-left: 2px; /* 4 */
color: $accent; /* 5 */
text-decoration: underline; /* 5 */
cursor: pointer; /* 5 */
}
/**
* Resetting the default focused styles on the number
*/
a[aria-describedby="footnotes-label"]:focus::after {
outline: thin dotted;
outline-offset: 2px;
}
.footnotes {
text-align: unset;
padding-top: initial;
}

View File

@ -5,23 +5,22 @@ date: git Last Modified
{% extends 'layouts/default.njk' %}
{% block main %}
<div style="display: flex; flex-wrap: wrap; justify-content: center;">
<div style="flex-grow: 1; flex-shrink: 1; flex-basis: 30%; min-width: 200px; max-width: 70%;">
<div style="flex-grow: 1; flex-shrink: 1; flex-basis: 30%; min-width: 200px; max-width: 70%; padding: 4px;">
<img src="/img/kitten_cropped.png" alt="a drawing of a small white kitten with black spots sitting and looking at you">
</div>
<div style="flex-grow: 2; flex-shrink: 2; flex-basis: 60%;">
<p>
hello i am {{ site.name }} <sup>({{ site.pronouns }})</sup> and i am gay, mostly for girls, and i'm a tiny kitten :3
hey! im {{ site.name }} <sup>({{ site.pronouns }})</sup>, welcome to my website! this site is primarily home to my <a href="/posts">blog</a>, containing my investigative journalism,
work on hacktivism and technical articles on some of my own hacks. outside my journalistic and activist work i try to <a href="https://soundcloud.com/nyancrimew">make music</a>, am a live dj
and do various other creative things.
</p>
<p>
i know lot's of things about cyber security, programming and far too little about music but i still
try to do all those things at once. if you like the things i do here or on social media you can
<a href="https://ko-fi.com/nyancrimew" target="_blank">support me on ko-fi</a>. links to the various things i do
can be found in the footer. if you're looking for some more serious info about me,
<a href="https://en.wikipedia.org/wiki/maia_arson_crimew" target="_blank">there is wikipedia for that</a>.
if you like the things i do here or on social media you can <a href="https://ko-fi.com/nyancrimew">support me on ko-fi</a>, which is my main source of income, so anythign helps! links to the various other places you can find me
are in the footer and to learn more about my background <a href="https://en.wikipedia.org/wiki/maia_arson_crimew">there is my wikipedia article</a>.
</p>
<p>
this website anonymously (without cookies) collects basic analytics on a self hosted instance of <a href="https://umami.is">umami</a>,
in the interest of transparency those analytics are publicly viewable <a href="https://umami.crimew.gay/share/M77OUJ83Q4qBcOjZ/maia.crimew.gay">here</a>.
in the interest of transparency the collected data is publicly viewable <a href="https://umami.crimew.gay/share/M77OUJ83Q4qBcOjZ/maia.crimew.gay">here</a>.
</p>
</div>
</div>

View File

@ -23,7 +23,7 @@ permalink: /posts/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumbe
<span class="middot"></span>
<span class="readtime">{{ entry.content | timeToRead }} to read</span>
<span class="middot"></span>
<span>by <span class="author by" id="author">{{ site.name }}</span></span>
<span>by <span class="author by" id="author">{{ site.name }}</span>{% if entry.data.coauthor %} and <span class="author by" id="author">{{ entry.data.coauthor.name }}</span>{% endif %}</span>
{% if entry.data.tags %}
<span class="middot"></span>
<span>in

View File

@ -6,6 +6,8 @@ feature_image: /img/posts/fuckstalkerware-4/cover.jpg
feature_alt: "a glitchy edited very pink collage of various marketing images for TheTruthSpy with their logo diagonally in the center"
tags:
- "#FuckStalkerware"
- shady business
- investigation
- stalkerware
- research
- analysis

View File

@ -13,29 +13,29 @@ feature_alt: "a glitchy edited screenshot of the kick.com homepage"
a few days ago an anonymous (the adjective, not the hacking collective) group of researchers reached out to me regarding a write-up they made i might be interested in covering. interestingly enough their write-up about how twitch competitor [kick.com](https://kick.com) isn't very secure was hosted on a kick.com subdomain - my interest was piqued.
### the curious case of the write-up
## the curious case of the write-up
the [link to the write-up](https://files.kick.com/tmp/66a348a9-08ac-48fd-87c9-100fa537c1b6) (now taken down, [archived](https://web.archive.org/web/20230801182040/https://files.kick.com/tmp/66a348a9-08ac-48fd-87c9-100fa537c1b6), more on why this is broken in a bit) i was sent was seemingly hosted on files.kick.com, the cdn used by kick. furthermore the group explained to me that to allow them to anonymously update the write-up without the link changing, they actually use a TOR to clearnet proxy, so the actual page is hosted on an onion site ([gk3eisnvj45msa5fo7kvd4betop6zmoiplena64lowncgdcsktoo6jad.onion](http://gk3eisnvj45msa5fo7kvd4betop6zmoiplena64lowncgdcsktoo6jad.onion), [clearweb (onion.re) mirror](https://gk3eisnvj45msa5fo7kvd4betop6zmoiplena64lowncgdcsktoo6jad.onion.re)) and loaded via [corsproxy](https://corsproxy.io/) and onion.re/tor.pm, which is also why the actual content of the write-up won't display on archive.org. and with that curiosity out of the way it's time to properly go over the write-up titled "Considering using Kick? Think again". block quotes (the indented quotes) in the following blog post will be verbatim sections from the write-up.
### first vuln: chat message fabrication
## first vuln: chat message fabrication
> We first looked over Kick's user interface with DevTools, and noticed when pinning a message, the entire metadata of the message gets sent with it. When you modify said payload to include a fake username/content/badges, the server will blindly accept it, allowing you to impersonate any chat member. Incredible!
this sounds fun! so i went ahead and tried to replicate it:
#### step 1: record a request
### step 1: record a request
in went ahead and begrudgingly created a kick account to test the things laid out in the write-up. i then opened the chat on my own channel, sent a message and with the dev tools network tab open pinned it to the chat to record the payload sent.
![a screenshot of the kick.com chat UI as well as the dev tools network tab showing the json payload for pinning a message](/img/posts/kick.com-sucks/fabrication-step1.jpg)
#### step 2: editing and replaying
### step 2: editing and replaying
since i didn't wanna bother bypassing cloudflare in any capacity just for this quick proof of concept, i decided to just use the built-in firefox "Edit and Resend" feature to replay the message pin payload. i edited the sender of the message, the message contents, added a silly little verified badge and hit send :3
![the firefox "edit and resend" feature in action showing an edited pinned-message request](/img/posts/kick.com-sucks/fabrication-step2.jpg)
#### success: it really is just that easy huh
### success: it really is just that easy huh
well, here we go, finally proof that the definitely very real (as evidenced by the verification badge) tyler "ninja" blevins meowed in my kick chat! i had to pin that one for sure !!
@ -43,7 +43,7 @@ well, here we go, finally proof that the definitely very real (as evidenced by t
the limitation of this vuln is that message fabrication is only possible for moderators of any given channel, though the fact that it applies specifically to pinned messages means there is still a lot of potential for scams and fraud here
#### reply fabrication
### reply fabrication
upon asking the group for confirmation that the pin based message fabrication only works for channels you have pin permissions in, i was told that their chat reply implementation also allows for fabrication, so i quickly reproduced that as well.
@ -60,13 +60,13 @@ damn, tyler "ninja" blevins really loves meowing :3
in the past this apparently worked on arbitrary channels - the api even still returns a success message, confirming message creation, but nothing appears in chat. now it only does on your own channel which certainly is an extremely weird mitigation strategy.
### let's just responsibly disclose this i guess
## let's just responsibly disclose this i guess
> We first debated about trying to responsibly disclose this vulnerability, the side of this is that Kick is heavily funded by Stake, a illegal online crypto casino, which is very legally and morally questionable. The debate ended up in us atleast trying to find a security contact... we found none. That's why we're writing this document instead of contacting Kick privately - we can't.
not only do kick and stake make it incredibly hard to even try to responsibly disclose vulnerabilities, they are also "known to ignore security vulnerabilities and pursue legal action against whistleblowers instead of fixing them," according to the group. this is why their write-up has been published anonymously and sent to me to report on. in a conversation the group told me they were further motivated to not responsibly disclose as to not support a platform "specifically made to promote illegal gambling \[content\], since twitch blocked it." so their research continued...
### second vuln: arbitrary file write / XSS
## second vuln: arbitrary file write / XSS
> While digging into saving profile pictures for some sort of vulnerability, we found that **Kick** implemented [Larevel's Vapor upload system](https://docs.vapor.build/1.0/resources/storage.html#file-uploads) incorrectly. This gave anyone full control of the content type and extension (allowing you to upload more than just images). These files were hosted on a domain in-scope for **all Kick.com cookies!**. Since Kick was pretty short sighted, they decided to make all authentication tokens accessible on all subdomains.
@ -76,13 +76,13 @@ the write-up itself, hosted on files.kick.com using this vulnerability, is the p
given that the write-up itself already definitely proved the viability of this vulnerability, and i had been shown a video by the group showcasing the vulnerability in action, i decided not to reproduce this one myself.
### third vuln: arbitrary file read / improper aws access control
## third vuln: arbitrary file read / improper aws access control
> So, you know that domain from earlier? Yeah, `files[.]kick[.]com`. Turns out, the main user content bucket was publicly viewable by just going to the [root of the domain](https://files.kick.com/)! Fun, am I right? All your user uploaded content available to the public, but it gets worse! It doesn't even get removed if you delete it. That probably breaks some privacy law, but we're too lazy to investigate.
i also verified this one myself by checking the bucket (`kick-files-prod`) contents using the [aws cli](https://aws.amazon.com/cli/), and have started archiving as much of the bucket as i can (at the time of writing that is around 50+gb of mostly user generated content). a quick check verifies that at the very least the bucket does not allow for public write or delete access; publicly allowing read access is still pretty bad nevertheless.
### conclusion
## conclusion
> Kick is definitely not a better alternative to Twitch, and this is not even all of the flaws we found. Some of them would be even more dangerous to publish publicly. It's incredible how streamers like to go on every platform without doing the smallest bit of investigation.
> [...] I know Twitch sucks, but this really isnt the alternative. A small startup could do better then this. Use YouTube gaming, theyre pretty cool, and we'd rather trust Google instead of a Gambling comp with shit security.
@ -90,10 +90,10 @@ i also verified this one myself by checking the bucket (`kick-files-prod`) conte
i definitely agree with this sentiment. i am also very curious regarding further trivially found vulerabilities (including the ones teased in the write-up), and im hopeful this write-up and my blog post can inspire some more interesting security research on kick.com, making it at the very least somewhat more secure hopefully. morally i also fully agree that trusting a platform which primarily exists to promote gambling and gambling content, owned by one of the biggest players in that industry, is foolish, no matter how good their creator payouts may be. this is further evidenced by how the only channels i saw ever having more than maybe 2000 viewers on kick during this investigation were famous gambling content creators, no other category ever seemed to garner much views.
### update (aug. 3, 08:50 UTC)
## update (aug. 3, 08:50 UTC)
it appears that kick has deployed mitigations for message fabrication, s3 file listing remains unfixed (despite being the easiest thing to fix), from which i can only conclude that they do not consider information leakage to be of high severity.
### update 2 (aug. 3, 17:00 UTC)
## update 2 (aug. 3, 17:00 UTC)
so it turns out they have not actually really fixed shit, pin based fabrication still works, the only mitigation that has been done is turning off persistence for ALL pins (real or fake), meaning they disappear on refresh. both real and fake pins are however still distributed to all viewers at the time of posting.

View File

@ -25,7 +25,7 @@ earlier this year, [the popular far right fediverse instance poast was hacked](h
- ~~a self proclaimed "national socialist" who's a professor at gardner-webb university~~
- just sooo many people in the tech industry
### correction
## correction
after some feedback regarding potential false positives in the list, the source of the compiled document asked me to publish the following correction: "Upon further research, Richard (Shawn) Carmichael aka psychosis67 is not a professor at Gardner-Webb University, but an IT guy from Humboldt, Iowa who impersonated the university professor from North Carolina with the same name on his now deleted LinkedIn profile.", a formal apology has been sent to the professor. furthermore we found that user bluj162 was also mapped wrong (to the chief operating officer of a school district), research here however shows that bluj162 is the son of J. Sanchez of Palm Beach (who i presume managed his dads LinkedIn?).

View File

@ -28,7 +28,7 @@ date: git Last Modified
<small class="updated">(updated <time datetime="{{ entry.data.changed_date | date_to_datetime }}">{{ entry.data.changed_date | date_formatted }}</time>)</small>
{% endif %}
<span class="middot"></span>
<span>by <span class="author by" id="author">{{ site.name }}</span></span>
<span>by <span class="author by" id="author">{{ site.name }}</span>{% if entry.data.coauthor %} and <span class="author by" id="author">{{ entry.data.coauthor.name }}</span>{% endif %}</span>
{% if entry.data.tags %}
<span class="middot"></span>
<span>in