Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

89 changed files with 723 additions and 1829 deletions

View File

@ -1,21 +1,13 @@
const path = require("node:path");
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight');
const pluginRss = require('@11ty/eleventy-plugin-rss');
const timeToRead = require('eleventy-plugin-time-to-read');
const safeLinks = require('@sardine/eleventy-plugin-external-links');
const eleventySass = require("@11tyrocks/eleventy-plugin-sass-lightningcss");
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');
module.exports = function (eleventyConfig) {
const isDev = (process.env.ELEVENTY_ENV || "dev") == "dev";
const parseDate = (str) => {
if (str instanceof Date) {
return str;
@ -31,41 +23,22 @@ module.exports = function (eleventyConfig) {
trimBlocks: true
});
const md = markdownIt({ "html": true }).use(markdownItAnchor, { "level": 2 });
eleventyConfig.setLibrary("md", md);
eleventyConfig.setLibrary("md", markdownIt({ "html": true }).use(markdownItAnchor, { "level": 2 }));
eleventyConfig.addPlugin(pluginRss);
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);
eleventyConfig.addPlugin(eleventySass);
eleventyConfig.addPassthroughCopy({ "src/static": "/" });
eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/dist/reveal.css": "reveal.js/reveal.css" });
eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/dist/reveal.esm.js": "reveal.js/reveal.esm.js" });
eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/plugin/markdown/markdown.esm.js": "reveal.js/plugin/markdown/markdown.esm.js" });
eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/plugin/highlight/highlight.esm.js": "reveal.js/plugin/highlight/highlight.esm.js" });
eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/plugin/highlight/monokai.css": "reveal.js/plugin/highlight/monokai.css" });
eleventyConfig.addPassthroughCopy({ "node_modules/reveal.js/plugin/notes/notes.esm.js": "reveal.js/plugin/notes/notes.esm.js" });
eleventyConfig.addFilter("date_to_datetime", async (obj) => {
if (!obj) {
return "";
}
eleventyConfig.addFilter("date_to_datetime", (obj) => {
const date = parseDate(obj);
return date.toISOString();
});
eleventyConfig.addFilter("date_formatted", async (obj) => {
if (!obj) {
return "";
}
eleventyConfig.addFilter("date_formatted", (obj) => {
const date = parseDate(obj);
const month = formatPart({ month: "short" }, date);
@ -75,22 +48,18 @@ module.exports = function (eleventyConfig) {
const minutes = date.getUTCMinutes();
if (hours != 0 && minutes != 0) {
return `${month} ${day}, ${year} - ${hours}:${minutes} UTC`;
}
return `${month} ${day}, ${year}`;
});
eleventyConfig.addFilter('urlescape', async str => {
eleventyConfig.addFilter('urlescape', str => {
return str.split('/').map(part => encodeURI(part)).join('/')
});
eleventyConfig.addFilter('md_inline', async str => {
return md.renderInline(str);
});
// TODO: possibly turn this into a post processing step instead of a filter (or at least make it a shortcode)
eleventyConfig.addFilter("related", async function(obj) {
eleventyConfig.addFilter("related", function(obj) {
const post = this.ctx;
const posts = this.ctx.collections.posts.map(post => post.data);
@ -117,38 +86,6 @@ module.exports = function (eleventyConfig) {
return collection.getFilteredByGlob('src/posts/*.md').reverse()
});
eleventyConfig.addCollection('decks', collection => {
return collection.getFilteredByGlob('src/decks/*.md')
// append the raw content
.map(item => {
const content = item.template.frontMatter.content;
item.data.rawMarkdown = content || "";
return item;
});
});
eleventyConfig.addTemplateFormats("scss");
eleventyConfig.addExtension("scss", {
outputFileExtension: "css",
compile: function (inputContent, inputPath) {
let parsed = path.parse(inputPath);
let result = sass.compileString(inputContent, {
style: isDev ? "expanded" : "compressed",
loadPaths: [
parsed.dir || "."
]
});
this.addDependencies(inputPath, result.loadedUrls);
return async (data) => {
return result.css;
};
}
})
return {
templateFormats: ["njk", "md", "html"],
dir: {

View File

@ -1,5 +1,3 @@
* 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
* add some more OG article tags specifically on article, and generally more metadata tags that may ever so slightly help with SEO and whatnot
* add an rss feed next to the atom feed for Reasons that came to me in a dream last night but i forgort

868
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,16 +8,14 @@
"update": "git pull && npm i && npm run build"
},
"dependencies": {
"@11ty/eleventy": "^v2.0.1",
"@11ty/eleventy": "^v2.0.0-beta.1",
"@11ty/eleventy-plugin-rss": "^1.2.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0",
"@11tyrocks/eleventy-plugin-sass-lightningcss": "^1.0.3",
"@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",
"markdown-it-anchor": "^8.6.7",
"reveal.js": "^5.0.1",
"sass": "^1.69.5"
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.7"
}
}

2
robots.txt Normal file
View File

@ -0,0 +1,2 @@
User-agent: GPTBot
Disallow: /

View File

@ -1,20 +0,0 @@
[
{
"title": "Queer Memes: Forms and Communities of Composition",
"authors": "Abbie Levesque DeCamp",
"year": "2023",
"publisher": "Northeastern University Boston",
"link": "https://repository.library.northeastern.edu/files/neu:4f22t092c",
"pdf": "https://repository.library.northeastern.edu/files/neu:4f22t092c/fulltext.pdf",
"doi": "https://doi.org/10.17760/D20618644"
},
{
"title": "Singular Purpose: Calculating the Degree of Ethno-Religious Over-representation in the US No-Fly List",
"authors": "Matteo Garofalo",
"year": "2024",
"publisher": "International Journal for Crime, Justice and Social Democracy",
"link": "https://www.crimejusticejournal.com/article/view/3069",
"pdf": "https://www.crimejusticejournal.com/article/view/3069/1445",
"doi": "https://doi.org/10.5204/ijcjsd.3069"
}
]

View File

@ -1,23 +1,19 @@
{
"links": [
{
"name": "atom/rss feed",
"name": "rss feed",
"link": "https://maia.crimew.gay/feed.xml"
},
{
"name": "tumblr",
"link": "https://tumblr.com/nyancrimew"
"link": "https://nyancrimew.tumblr.com"
},
{
"name": "twitter",
"link": "https://twitter.com/awawawhoami"
},
{
"name": "fediverse",
"name": "fedded verse",
"link": "https://crimew.gay/maia"
},
{
"name": "soundcloud",
"name": "sounded cloud",
"link": "https://soundcloud.com/nyancrimew"
},
{
@ -25,20 +21,20 @@
"link": "https://last.fm/user/nyancrimew"
},
{
"name": "github",
"name": "gitted hub",
"link": "https://github.com/nyancrimew"
},
{
"name": "gitted tea",
"link": "https://git.lavender.software/nyancrimew"
},
{
"name": "ko-fi",
"link": "https://ko-fi.com/nyancrimew"
},
{
"name": "letterboxd",
"link": "https://letterboxd.com/nyancrimew/"
},
{
"name": "instagram",
"link": "https://instagram.com/nyancrimew"
"name": "reddit",
"link": "https://reddit.com/u/nyancrimew"
},
{
"name": "analytics",
@ -145,11 +141,6 @@
"alt": "ilwag.com",
"title": "cute lil tunes :3",
"link": "https://ilwag.com"
},
{
"badge": "solely.png",
"alt": "solely",
"link": "https://arciniega.one"
}
]
}

View File

@ -7,10 +7,6 @@
"name": "blog",
"link": "/posts/"
},
{
"name": "citations",
"link": "/citations/"
},
{
"name": "contact",
"link": "/contact/"

View File

@ -5,11 +5,14 @@
"tags": [
"nyancrimew",
"maia arson crimew",
"android",
"switzerland",
"hacktivism",
"developer"
"lucerne",
"developer",
"hacktivism"
],
"twitter": "@awawawhoami",
"twitter": "@maiaarson",
"name": "maia arson crimew",
"pronouns": "it/she",
"language": "en",

View File

@ -1,22 +0,0 @@
const cache = new Map();
module.exports = async ({ path, check_path = 'src/static/' + path, type = "css" }) => {
// caching hashes significantly speeds up build time
var hash = undefined;
if (cache.get(check_path)) {
hash = cache.get(check_path);
} else {
hash = revision = require('child_process')
.execSync(`git rev-list HEAD -1 -- ${check_path}`)
.toString().trim().slice(0, 7);
cache.set(check_path, hash);
}
if (type == "css") {
return `<link rel="stylesheet" href="${path}?h=${hash}"/>\n`;
} else if (type == "js") {
return `<script src="${path}?h=${hash}"></script>\n`;
} else {
throw new Error('undefined bounce type');
}
}

View File

@ -1,13 +0,0 @@
module.exports = (md) => async ({ src, alt, caption = '', type = 'img' }) => `
<figure>
<div>
${
type == 'video' ?
`<video controls onloadstart="this.volume=0.5">
<source src="${src}" type="video/mp4">
</video>` : `<img src="${src}" alt="${alt}" />`
}
</div>
${caption ? `<figcaption>${md.renderInline(caption)}</figcaption>` : ''}
</figure>
`

View File

@ -16,5 +16,6 @@
{% if item.link %}<a href="{{ item.link }}" target="_blank">{% endif %}<img src="/badges/{{ item.badge }}" alt="{{ item.alt }}" {% if item.title %}title="{{ item.title }}"{% endif %}>{% if item.link %}</a>{% endif %}
{% endfor %}
</div>
<script src="https://lavender.software/webring/webring-{{ site.webring.version }}.js" data-site-id="{{ site.webring.siteId }}"></script>
<script src="https://sleepy.zone/webring/webring-{{ site.sleepyWebring.version }}.js" data-site-id="{{ site.sleepyWebring.siteId }}"></script>
</footer>

View File

@ -1 +0,0 @@
<!-- empty until we can move away from pagination work around -->

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title if title else site.title }}</title>
{% bounce { path: '/css/style.css', check_path: 'src/css' } %}
<link rel="stylesheet" href="/css/style.css"/>
<link rel="stylesheet" href="/prism.css"/>
<meta name="description" content="{{ description if description else site.description }}" />
@ -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 }}{% if coauthor %},{{ coauthor.name }}{% endif %}">
<meta name="article:author" content="{{ site.name }}">
{% 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 }}">
@ -42,5 +42,5 @@
</div>
{% include "components/footer.njk" %}
</body>
{% bounce { path: '/oneko.js', type: 'js' } %}
<script src="/oneko.js"></script>
</html>

View File

@ -6,14 +6,7 @@ subhead: blog
<article>
<header class="article_header">
{% if feature_image %}
<figure id="feature">
<div>
<img src="{{ feature_image }}" alt="{{ feature_alt if feature_alt else "feature image for '" + title + "'" }}"/>
</div>
{% if feature_caption %}
<figcaption>{{ feature_caption | md_inline | safe }}</figcaption>
{% endif %}
</figure>
<img src="{{ feature_image }}" alt="{{ feature_alt if feature_alt else "feature image for '" + title + "'" }}" style="padding-bottom: 10px;" height="auto" width="75%" layout="responsive"/>
{% endif %}
<div class="byline">
<time datetime="{{date | date_to_datetime }}">{{ date | date_formatted }}</time>
@ -23,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>{% if coauthor %} and <a class="author by" id="author" href="{{ coauthor.link }}">{{ coauthor.name }}</a>{% endif %}</span>
<span>by <span class="author by" id="author">{{ site.name }}</span></span>
{% if tags %}
<span class="middot"></span>
<span>in
@ -47,11 +40,10 @@ 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 main source of income so anything goes a long way,
and monthly contributions help tremendously with budgeting. &lt;3
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,
and monthly contributions help tremendously with budgeting.
</div>
</a>
</article>

View File

@ -1,6 +0,0 @@
$bg: rgb(254, 175, 214);
$text: rgb(92, 53, 124);
$accent: rgb(146, 0, 80);
$active-links: rgb(124, 6, 160);
$divider: rgb(219, 103, 167);
$semi-bg: rgba(221, 116, 174, 0.211);

View File

@ -1,30 +0,0 @@
// Exposes theme's variables for easy re-use in CSS for plugin authors
:root {
--r-background-color: #{$backgroundColor};
--r-main-font: #{$mainFont};
--r-main-font-size: #{$mainFontSize};
--r-main-color: #{$mainColor};
--r-block-margin: #{$blockMargin};
--r-heading-margin: #{$headingMargin};
--r-heading-font: #{$headingFont};
--r-heading-color: #{$headingColor};
--r-heading-line-height: #{$headingLineHeight};
--r-heading-letter-spacing: #{$headingLetterSpacing};
--r-heading-text-transform: #{$headingTextTransform};
--r-heading-text-shadow: #{$headingTextShadow};
--r-heading-font-weight: #{$headingFontWeight};
--r-heading1-text-shadow: #{$heading1TextShadow};
--r-heading1-size: #{$heading1Size};
--r-heading2-size: #{$heading2Size};
--r-heading3-size: #{$heading3Size};
--r-heading4-size: #{$heading4Size};
--r-code-font: #{$codeFont};
--r-link-color: #{$linkColor};
--r-link-color-dark: #{darken($linkColor , 15% )};
--r-link-color-hover: #{$linkColorHover};
--r-selection-background-color: #{$selectionBackgroundColor};
--r-selection-color: #{$selectionColor};
--r-overlay-element-bg-color: #{$overlayElementBgColor};
--r-overlay-element-fg-color: #{$overlayElementFgColor};
}

View File

@ -1,45 +0,0 @@
@mixin vertical-gradient( $top, $bottom ) {
background: $top;
background: -moz-linear-gradient( top, $top 0%, $bottom 100% );
background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) );
background: -webkit-linear-gradient( top, $top 0%, $bottom 100% );
background: -o-linear-gradient( top, $top 0%, $bottom 100% );
background: -ms-linear-gradient( top, $top 0%, $bottom 100% );
background: linear-gradient( top, $top 0%, $bottom 100% );
}
@mixin horizontal-gradient( $top, $bottom ) {
background: $top;
background: -moz-linear-gradient( left, $top 0%, $bottom 100% );
background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) );
background: -webkit-linear-gradient( left, $top 0%, $bottom 100% );
background: -o-linear-gradient( left, $top 0%, $bottom 100% );
background: -ms-linear-gradient( left, $top 0%, $bottom 100% );
background: linear-gradient( left, $top 0%, $bottom 100% );
}
@mixin radial-gradient( $outer, $inner, $type: circle ) {
background: $outer;
background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) );
background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% );
background: radial-gradient( center, $type cover, $inner 0%, $outer 100% );
}
@mixin light-bg-text-color( $color ) {
section.has-light-background {
&, h1, h2, h3, h4, h5, h6 {
color: $color;
}
}
}
@mixin dark-bg-text-color( $color ) {
section.has-dark-background {
&, h1, h2, h3, h4, h5, h6 {
color: $color;
}
}
}

View File

@ -1,50 +0,0 @@
// Base settings for all themes that can optionally be
// overridden by the super-theme
// Background of the presentation
$backgroundColor: #2b2b2b;
// Primary/body text
$mainFont: 'Lato', sans-serif;
$mainFontSize: 40px;
$mainColor: #eee;
// Vertical spacing between blocks of text
$blockMargin: 20px;
// Headings
$headingMargin: 0 0 $blockMargin 0;
$headingFont: 'League Gothic', Impact, sans-serif;
$headingColor: #eee;
$headingLineHeight: 1.2;
$headingLetterSpacing: normal;
$headingTextTransform: uppercase;
$headingTextShadow: none;
$headingFontWeight: normal;
$heading1TextShadow: $headingTextShadow;
$heading1Size: 3.77em;
$heading2Size: 2.11em;
$heading3Size: 1.55em;
$heading4Size: 1.00em;
$codeFont: monospace;
// Links and actions
$linkColor: #13DAEC;
$linkColorHover: lighten( $linkColor, 20% );
// Text selection
$selectionBackgroundColor: #FF5E99;
$selectionColor: #fff;
// Colors used for UI elements that are overlaid on top of
// the presentation
$overlayElementBgColor: 240, 240, 240;
$overlayElementFgColor: 0, 0, 0;
// Generates the presentation background, can be overridden
// to return a background image or gradient
@mixin bodyBackground() {
background: $backgroundColor;
}

View File

@ -1,331 +0,0 @@
// Base theme template for reveal.js
/*********************************************
* GLOBAL STYLES
*********************************************/
@import "./exposer";
.reveal-viewport {
@include bodyBackground();
background-color: var(--r-background-color);
}
.reveal {
font-family: var(--r-main-font);
font-size: var(--r-main-font-size);
font-weight: normal;
color: var(--r-main-color);
}
.reveal ::selection {
color: var(--r-selection-color);
background: var(--r-selection-background-color);
text-shadow: none;
}
.reveal ::-moz-selection {
color: var(--r-selection-color);
background: var(--r-selection-background-color);
text-shadow: none;
}
.reveal .slides section,
.reveal .slides section>section {
line-height: 1.3;
font-weight: inherit;
}
/*********************************************
* HEADERS
*********************************************/
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5,
.reveal h6 {
margin: var(--r-heading-margin);
color: var(--r-heading-color);
font-family: var(--r-heading-font);
font-weight: var(--r-heading-font-weight);
line-height: var(--r-heading-line-height);
letter-spacing: var(--r-heading-letter-spacing);
text-transform: var(--r-heading-text-transform);
text-shadow: var(--r-heading-text-shadow);
word-wrap: break-word;
}
.reveal h1 {font-size: var(--r-heading1-size); }
.reveal h2 {font-size: var(--r-heading2-size); }
.reveal h3 {font-size: var(--r-heading3-size); }
.reveal h4 {font-size: var(--r-heading4-size); }
.reveal h1 {
text-shadow: var(--r-heading1-text-shadow);
}
/*********************************************
* OTHER
*********************************************/
.reveal p {
margin: var(--r-block-margin) 0;
line-height: 1.3;
}
/* Remove trailing margins after titles */
.reveal h1:last-child,
.reveal h2:last-child,
.reveal h3:last-child,
.reveal h4:last-child,
.reveal h5:last-child,
.reveal h6:last-child {
margin-bottom: 0;
}
/* Ensure certain elements are never larger than the slide itself */
.reveal img,
.reveal video,
.reveal iframe {
max-width: 95%;
max-height: 95%;
}
.reveal strong,
.reveal b {
font-weight: bold;
}
.reveal em {
font-style: italic;
}
.reveal ol,
.reveal dl,
.reveal ul {
display: inline-block;
text-align: left;
margin: 0 0 0 1em;
}
.reveal ol {
list-style-type: decimal;
}
.reveal ul {
list-style-type: disc;
}
.reveal ul ul {
list-style-type: square;
}
.reveal ul ul ul {
list-style-type: circle;
}
.reveal ul ul,
.reveal ul ol,
.reveal ol ol,
.reveal ol ul {
display: block;
margin-left: 40px;
}
.reveal dt {
font-weight: bold;
}
.reveal dd {
margin-left: 40px;
}
.reveal blockquote {
display: block;
position: relative;
width: 70%;
margin: var(--r-block-margin) auto;
padding: 5px;
font-style: italic;
background: rgba(255, 255, 255, 0.05);
box-shadow: 0px 0px 2px rgba(0,0,0,0.2);
}
.reveal blockquote p:first-child,
.reveal blockquote p:last-child {
display: inline-block;
}
.reveal q {
font-style: italic;
}
.reveal pre {
display: block;
position: relative;
width: 90%;
margin: var(--r-block-margin) auto;
text-align: left;
font-size: 0.55em;
font-family: var(--r-code-font);
line-height: 1.2em;
word-wrap: break-word;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15);
}
.reveal code {
font-family: var(--r-code-font);
text-transform: none;
tab-size: 2;
}
.reveal pre code {
display: block;
padding: 5px;
overflow: auto;
max-height: 400px;
word-wrap: normal;
}
.reveal .code-wrapper {
white-space: normal;
}
.reveal .code-wrapper code {
white-space: pre;
}
.reveal table {
margin: auto;
border-collapse: collapse;
border-spacing: 0;
}
.reveal table th {
font-weight: bold;
}
.reveal table th,
.reveal table td {
text-align: left;
padding: 0.2em 0.5em 0.2em 0.5em;
border-bottom: 1px solid;
}
.reveal table th[align="center"],
.reveal table td[align="center"] {
text-align: center;
}
.reveal table th[align="right"],
.reveal table td[align="right"] {
text-align: right;
}
.reveal table tbody tr:last-child th,
.reveal table tbody tr:last-child td {
border-bottom: none;
}
.reveal sup {
vertical-align: super;
font-size: smaller;
}
.reveal sub {
vertical-align: sub;
font-size: smaller;
}
.reveal small {
display: inline-block;
font-size: 0.6em;
line-height: 1.2em;
vertical-align: top;
}
.reveal small * {
vertical-align: top;
}
.reveal img {
margin: var(--r-block-margin) 0;
}
/*********************************************
* LINKS
*********************************************/
.reveal a {
color: var(--r-link-color);
text-decoration: none;
transition: color .15s ease;
}
.reveal a:hover {
color: var(--r-link-color-hover);
text-shadow: none;
border: none;
}
.reveal .roll span:after {
color: #fff;
// background: darken( var(--r-link-color), 15% );
background: var(--r-link-color-dark);
}
/*********************************************
* Frame helper
*********************************************/
.reveal .r-frame {
border: 4px solid var(--r-main-color);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
}
.reveal a .r-frame {
transition: all .15s linear;
}
.reveal a:hover .r-frame {
border-color: var(--r-link-color);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
}
/*********************************************
* NAVIGATION CONTROLS
*********************************************/
.reveal .controls {
color: var(--r-link-color);
}
/*********************************************
* PROGRESS BAR
*********************************************/
.reveal .progress {
background: rgba(0,0,0,0.2);
color: var(--r-link-color);
}
/*********************************************
* PRINT BACKGROUND
*********************************************/
@media print {
.backgrounds {
background-color: var(--r-background-color);
}
}

View File

@ -1,29 +0,0 @@
---
title: maia academic citations :3
subhead: academic citations
permalink: /citations/index.html
date: git Last Modified
---
{% extends 'layouts/default.njk' %}
{% block main %}
<p>a collection of various academic mentions of me and my work, if you have
also cited my work in a paper but it isn't on this list yet feel free to <a href="/contact/">contact me</a></p>
<div>
<ul>
{% for citation in citations %}
<li class="list-entry">
<h3><a href="{{ citation.link }}">{{ citation.title }}</a>{% if citation.pdf %} (<a href="{{ citation.pdf }}">pdf</a>){% endif %}</h3>
<div class="byline">
<span>published <span class="year">{{ citation.year }}</span></span>
<span class="middot"></span>
<span>by <span class="author by" id="author">{{ citation.authors }}</span></span>
{% if citation.doi %}
<span class="middot"></span>
<span><a href="{{ citation.doi }}"><code>{{ citation.doi }}</code></a></span>
{% endif %}
</div>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}

View File

@ -6,5 +6,5 @@ date: git Last Modified
---
{% extends 'layouts/default.njk' %}
{% block main %}
<p>feel free to contact me for tips, journalistic inquiries, requests for data, booking for public speaking events, etc. via email at <a href="mailto:maia@crimew.gay"><code>maia@crimew.gay</code></a> (if possible encrypted using my <a href="/files/pgp.asc">pgp key</a> <code>[A1D5 2A78 96E9 7F52 B2DF 63A1 556B ABBC C484 D39B]</code>) or via signal at <a href="https://signal.me/#eu/PKeiMUVunTSdaxHWjK9lsgcl9xaj9ujDys92u-APVl4dsHz1iw5BFKPaVf2d-aDx">@nyancrimew.01</a> (please only use signal for serious inquiries).</p>
<p>feel free to contact me for tips, journalistic inquiries, requests for data, booking for public speaking events, etc. via email at <a href="mailto:maia@crimew.gay"><code>maia@crimew.gay</code></a> (if possible encrypted using my <a href="/files/pgp.asc">pgp key</a> <code>[A1D5 2A78 96E9 7F52 B2DF 63A1 556B ABBC C484 D39B]</code>).</p>
{% endblock %}

View File

@ -1,40 +0,0 @@
/**
* maia site theme for reveal.js.
*/
@import "../_includes/scss/mixins";
@import "../_includes/scss/settings";
@import "../_includes/scss/colors.scss";
// Override theme settings (see ../template/settings.scss)
$backgroundColor: $bg;
$mainColor: $text;
$headingColor: $text;
$mainFontSize: 30px;
$mainFont: monospace, serif, sans-serif;
$headingFont: monospace, serif, sans-serif;
$headingTextShadow: none;
$headingLetterSpacing: normal;
$headingTextTransform: normal;
$headingFontWeight: 600;
$linkColor: $accent;
$linkColorHover: $active-links;
$selectionBackgroundColor: lighten( $linkColor, 25% );
$heading1Size: 2.5em;
$heading2Size: 1.6em;
$heading3Size: 1.3em;
$heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff);
// Theme template ------------------------------
@import "../_includes/scss/theme";
// ---------------------------------------------

View File

@ -1,4 +1,9 @@
@import "../_includes/scss/colors.scss";
$bg: rgb(254, 175, 214);
$text: rgb(92, 53, 124);
$accent: rgb(146, 0, 80);
$active-links: rgb(124, 6, 160);
$divider: rgb(219, 103, 167);
$semi-bg: rgba(221, 116, 174, 0.211);
html {
background-color: $bg;
@ -9,11 +14,6 @@ a {
color: $accent;
}
::selection {
background-color: rgba($accent, 0.7);
color: #ffb8e8;
}
.like-a {
color: $accent;
text-decoration: underline;
@ -61,59 +61,17 @@ footer,
.list-entry {
list-style-type: none;
h2, h3 {
h2 {
margin-bottom: 0;
}
}
#content {
max-width: 1000px;
max-width: 900px;
margin-left: auto;
margin-right: auto;
padding-top: 2em;
padding-bottom: 2em;
counter-reset: footnotes;
}
table {
display: block;
overflow-x: auto;
border-collapse: collapse;
white-space: nowrap;
border: none;
th, td {
border: 1px solid;
padding-top: 4px;
padding-bottom: 4px;
padding-left: 6px;
padding-right: 6px;
text-align: center;
}
th, tr td:first-child {
border: 1.5px solid;
background-color: $semi-bg;
font-weight: bold;
}
th {
border-top: none;
}
tr {
th, td:first-child {
border-left: none;
}
td, th:last-child {
border-right: none;
}
}
tr:last-child td {
border-bottom: none;
}
}
.byline {
@ -127,8 +85,7 @@ table {
time,
.author,
.updated,
.year {
.updated {
font-weight: bold;
}
@ -174,60 +131,6 @@ video {
max-width: 100%;
}
figure {
margin-left: 0;
margin-right: 0;
width: fit-content;
}
figcaption {
text-align: center;
font-style: italic;
}
blockquote {
background-color: $semi-bg;
border-left: 3px solid $accent;
padding: .5em .5em;
p {
display: inline;
margin-top: 0;
line-height: 1.4em;
position: relative;
font-style: italic;
}
span{
display:block;
font-style: normal;
font-weight: bold;
margin-top: .2em;
}
}
blockquote:before {
color: $accent;
content: "\201C";
font-size: 4em;
line-height: 0;
margin-right: 1px;
vertical-align: -0.4em;
}
span.greentext {
color: #789922;
}
blockquote.greentext::before {
content: none;
display: none;
}
blockquote.greentext::after {
content: none;
display: none;
}
.tag {
font-weight: bold;
}
@ -260,6 +163,10 @@ blockquote.greentext::after {
}
}
.greentext {
color: #789922;
}
.lavender-webring-container,
.sleepy-zone-webring-container {
all: unset;
@ -293,48 +200,4 @@ 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.6em; /* 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

@ -1,58 +0,0 @@
---
pagination:
data: collections.decks
size: 1
permalink: /decks/{{ pagination.items[0].fileSlug }}/index.html
---
{% for deck in pagination.items %}
<!DOCTYPE html>
<html lang="{{ site.language }}">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ deck.data.title if deck.data.title else site.title }}</title>
{% bounce { path: '/css/style.css', check_path: 'src/css' } %}
<meta name="theme-color" content="#eca9cb">
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
<link rel="shortcut icon" href="/favicon.ico">
{% if env.environment.isProd %}
<script async src="https://umami.crimew.gay/script.js" data-website-id="fa7a72e7-acbc-488d-beb2-213886be0262"></script>
{% endif %}
{% bounce { path: '/reveal.js/reveal.css', check_path: 'node_modules/reveal.js/dist/reveal.css' } %}
{% bounce { path: '/css/reveal-maia.css', check_path: 'src/css' } %}
<!-- TODO: custom code theme -->
{% bounce { path: '/reveal.js/plugin/highlight/monokai.css', check_path: 'node_modules/reveal.js/plugin/highlight/monokai.css' } %}
<script type="module">
import Reveal from '/reveal.js/reveal.esm.js';
import Markdown from '/reveal.js/plugin/markdown/markdown.esm.js';
import RevealHighlight from '/reveal.js/plugin/highlight/highlight.esm.js';
import RevealNotes from '/reveal.js/plugin/notes/notes.esm.js';
let deck = new Reveal({
plugins: [ Markdown, RevealHighlight, RevealNotes ],
hash: true,
controlsTutorial: false
})
deck.initialize();
</script>
</head>
<body>
<div class="reveal">
<div class="slides">
<section data-markdown>
<textarea data-template>
{{ deck.data.rawMarkdown }}
</textarea>
</section>
<div>
<div>
</body>
</html>
{% endfor %}

View File

@ -1,4 +0,0 @@
{
"layout": "layouts/deck",
"permalink": "decks/{{ page.fileSlug }}/blank.html"
}

View File

@ -1,316 +0,0 @@
---
title: "#FuckStalkerware at ETH"
---
<!-- .slide: data-auto-animate -->
<img src="/img/kitten_cropped.png" class="r-stretch"/>
# hacking a morally bankrupt industry
## a talk about stalkerware, hacktivism and ethics
## [maia arson crimew](https://maia.crimew.gay)
**content warning:** discussion of abuse/controlling behavior
---
<!-- .slide: data-auto-animate -->
<img src="/img/kitten_cropped.png" class="r-stretch"/>
## maia arson crimew
* is 24 years old <!-- .element: class="fragment" -->
* uses it(/she) pronouns <!-- .element: class="fragment" -->
* has been a hacktivist since 2019 <!-- .element: class="fragment" -->
* got indicted in 2021 ^-^ oopie <!-- .element: class="fragment" -->
* leaked the 2019 version of the US no fly list in 2023 <!-- .element: class="fragment" -->
* is a silly "journalist/blogger" <!-- .element: class="fragment" -->
* is literally a kitten <!-- .element: class="fragment" -->
---
<!-- .slide: data-auto-animate data-auto-animate-restart -->
## what did it do for the rest of this year
---
<!-- .slide: data-auto-animate -->
## what did it do for the rest of this year
* published thousands of emails revealing the secret US based working group behind much of current international anti-trans legislation
* reported on various hacks by other actors <!-- .element: class="fragment" -->
* a cybersecurity company pwned by a random 4chan user <!-- .element: class="fragment" -->
* kittensec leaking romanian and EU government data <!-- .element: class="fragment" -->
* a write up on various security issues in the streaming platform kick.com <!-- .element: class="fragment" -->
* an exclusive report on how rosgosstrakh got hacked <!-- .element: class="fragment" -->
---
<!-- .slide: data-auto-animate -->
## what did it do for the rest of this year
* investigative internet pop culture journalism
* an ifunny clone that isn't actually what it seems at all <!-- .element: class="fragment" -->
* how a popular tiktok meme account has a dark past and connections to the far right <!-- .element: class="fragment" -->
* guested on various political and pop culture podcasts <!-- .element: class="fragment" -->
* various other media work <!-- .element: class="fragment" -->
* <!-- .element: class="fragment" --> started the <b>#FuckStalkerware</b> project to help combat stalkerware and get an insight into the industry
Note:
pocasts such as well there's your problem, the worst of all possible worlds, red planet and many more
media work both giving interviews and portraits about myself and acting as an expert on various topics
---
## let's cover some basics
* what's hacktivism<!-- .element: class="fragment" -->
* what is my motivation<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-0/cover.jpg" data-background-opacity="0.2" data-auto-animate data-auto-animate-restart -->
## what is stalkerware
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-0/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## what is stalkerware
* commercially available spyware
* often advertised for:<!-- .element: class="fragment" -->
* "parental control" <!-- .element: class="fragment" -->
* figuring out if your partner is cheating on you<!-- .element: class="fragment" -->
* hidden from the target, often pretends to be system application<!-- .element: class="fragment" -->
* usually requires brief physical access, can be remotely installed<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-0/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## what is stalkerware
* reports activity on the victim device, such as:
* text messages sent and received<!-- .element: class="fragment" -->
* phone calls made (sometimes with recording)<!-- .element: class="fragment" -->
* websites visited<!-- .element: class="fragment" -->
* any photos taken<!-- .element: class="fragment" -->
* geolocation<!-- .element: class="fragment" -->
* ambient audio recordings<!-- .element: class="fragment" -->
* sometimes allows remote sending of text messages<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-1/cover.jpg" data-background-opacity="0.2" -->
## why is this bad?
Note:
spying on partners is bad, spying on kids is bad, trying to solve social issues with technology, stolen text messages allow theft of 2fa codes and taking over other accounts, privacy is a fucking human right for everyone no matter who they are, what they do or how old they are
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-1/cover.jpg" data-background-opacity="0.2" -->
## why we hack stalkerware providers
* legislation and courts are slow<!-- .element: class="fragment" -->
* we can collectively defend ourselves from abusive technology<!-- .element: class="fragment" -->
* most stalkerware providers have horrible security<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
<video data-autoplay src="/img/posts/fuckstalkerware-2/tizer.mp4"></video>
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
* an iranian stalkerware<!-- .element: class="fragment" -->
* users/victims all over the world<!-- .element: class="fragment" -->
* 750k users<!-- .element: class="fragment" -->
* extremely trivial to hack<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
* exposed .git directory allows stealing dashboard source code using [goop](https://github.com/nyancrimew/goop)
<img src="/img/posts/fuckstalkerware-2/goop.jpg"/>
* turns out to be a trashy php monorepo for both frontend + backend<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### trying to find something to exploit
* auth cookies are in the format of<!-- .element: class="fragment" --> `userid.passwordmd5.lang.timezone.db_type`
* user ids are sequential<!-- .element: class="fragment" -->
* yes, the password as represented in the db with the db salt and all is in the cookie<!-- .element: class="fragment" -->
* db type is either a or b, where b appears to stand for "backup", both my accounts are on type b<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### trying to find something to exploit
for auth via level2 phone app an "app key" is required, which is described by code comments as follows:
```php
// $app_key is generated in level2 app hash(md5_pass.username.private_key)
// $u_id will send from level2 app to identify target user
// $tz is level2 app phone timezone
// $lang is level2 app phone default language
```
the mentioned private key (which is actually a static salt) is<!-- .element: class="fragment" --> `asrome_intermilan_realmadrid`.
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### trying to find something to exploit
* `uploadPhoto`, `uploadRecordAmbient` and `uploadRecordCall` allow arbitrary file uploads
```php [9]
$allowed = array('3gp');
$objFile = & $file_array["recordcall"];
$filename = $objFile['name'];
$record_id = explode(".",$filename);
$record_id = explode("_",$record_id[0]);
$record_id = $record_id[2];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if(!in_array($ext,$allowed) ) {
// error_log("HACKER:".basename( $objFile["name"] ));
}
```
<!-- .element: class="fragment" -->
* <!-- .element: class="fragment" --> <code>uploadRecordAmbient</code> and <code>uploadRecordCall</code> actually note that this is a vulnerability and a check for only allowing .mp3 or .3gp files respectively exists but result is ignored
* this should work to give us code execution<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### trying to find something to exploit
* one problem left: we need a device id
* reversing a bit more of the code to figure out how to register a device to my test account<!-- .element: class="fragment" -->
* we now have a device with the very numeric id 'maia'<!-- .element: class="fragment" -->
* time to upload a "photo" (base64 encoded webshell)<!-- .element: class="fragment" -->
* as a little extra flex i use directory traveral to place it at /funky.php<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate data-autoslide="64554" -->
## example: SpyHide
### it's exploitin' time
<img src="/img/posts/fuckstalkerware-2/funkytimes.jpg"/>
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### it's exploitin' time
* compress and download all webroots hosted on this server using the webshell
* grabbing all databases using an existing adminer install<!-- .element: class="fragment" -->
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### it's exploitin' time
<img src="/img/decks/fuckstalkerware/adminer.jpg"/>
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### analysis
* over 230gb of exfiltrated data<!-- .element: class="fragment" -->
* source code, databases<!-- .element: class="fragment" -->
* photos, calls and ambient audio recordings from phones<!-- .element: class="fragment" -->
* some account owners have spied on as much as 30 different devices over the course of multiple years, stalking some people accross multiple phone changes<!-- .element: class="fragment" -->
* dataset actually makes it somewhat possible to identify victims, containing some imeis and phone numbers<!-- .element: class="fragment" -->
Note:
no journalists, victim support groups or researchers appear to have made use of that fact so far as far as im aware
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### analysis
* a look through email addresses used for registration reveals around 190 users with various government email addresses
* at least 16 us government addresses, incl .mil and various correctional officers<!-- .element: class="fragment" -->
* 5 users from colombian national police<!-- .element: class="fragment" -->
* massive amounts of users from brazilian and philippine departments of education<!-- .element: class="fragment" -->
* spyhide data retention claims are a lie<!-- .element: class="fragment" -->
* photos and recordings from as far back as 2020 found despite claims they are deleted after 3 months<!-- .element: class="fragment" -->
Note:
there is no email verification, so data may be skewed
police and correctional officer use implies possible evaluation of commercial spyware for law enforcement use, a pattern observed in other datasets as well
based on code analysis data is only deleted when operator stops paying.
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### analysis
<img src="/img/decks/fuckstalkerware/spyhide-gps-world.jpg" class="r-stretch"/>
*image credit:* [TechCrunch](https://techcrunch.com/2023/07/24/spyhide-stalkerware-android/)
Note:
a map of all recorded gps location data points in the dataset, showing spyhide being used all over the world with hotspots in europa, brazil, indonesia and the US
---
<!-- .slide: data-background-image="/img/posts/fuckstalkerware-2/cover.jpg" data-background-opacity="0.2" data-auto-animate -->
## example: SpyHide
### the result
* SpyHide briefly rebrands as Oospy<!-- .element: class="fragment" -->
* a few days after techcrunch and i published our stories hetzner takes down the spyhide backend server<!-- .element: class="fragment" -->
* paypal is contacted about the paypal account used for spyhide/oospy billing<!-- .element: class="fragment" -->
* paypal payment option disappears, we do not know if paypal took action<!-- .element: class="fragment" -->
* main known developer is confronted about the paypal account<!-- .element: class="fragment" -->
* oospy goes completely offline<!-- .element: class="fragment" -->
* as far as we can tell they have not come back online<!-- .element: class="fragment" -->
* this is not a one time thing (see LetMeSpy)<!-- .element: class="fragment" -->
---
<!-- .slide: data-auto-animate data-auto-animate-restart -->
## conclusions
---
<!-- .slide: data-auto-animate -->
## conclusions
* hacking stalkerware works, and gives effective results
* indispensable data for understanding the industry, reporting on it and fighting against it<!-- .element: class="fragment" -->
* it should not be easy and profitable to run a stalkerware business<!-- .element: class="fragment" -->
* more and more just give up instead of rebranding and keeping at it<!-- .element: class="fragment" -->
---
<!-- .slide: data-auto-animate -->
## conclusions
### morality
legality ≠ morality
Note:
victims need to be freed from, informed about and protected against stalkerware now, not in 10 years when it might be illegal in some places, giving victims and support orgs leverage and evicence to stand against not just their abusers but also the companies enabling and preying on them, we can break the market now
---
<img src="/img/kitten_cropped.png" class="r-stretch"/>
# Q & A with maia
i am unable to answer questions regarding legal proceedings concerning me, don't ask. i will also not answer any other question putting me or others at any unreasonable legal risks.

View File

@ -5,22 +5,23 @@ 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%; padding: 4px;">
<div style="flex-grow: 1; flex-shrink: 1; flex-basis: 30%; min-width: 200px; max-width: 70%;">
<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>
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.
hello i am {{ site.name }} <sup>({{ site.pronouns }})</sup> and i am gay, mostly for girls, and i'm a tiny kitten :3
</p>
<p>
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>.
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>.
</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 the collected data is publicly viewable <a href="https://umami.crimew.gay/share/M77OUJ83Q4qBcOjZ/maia.crimew.gay">here</a>.
in the interest of transparency those analytics are publicly viewable <a href="https://umami.crimew.gay/share/M77OUJ83Q4qBcOjZ/maia.crimew.gay">here</a>.
</p>
</div>
</div>

View File

@ -4,7 +4,7 @@ subhead: blog
pagination:
data: collections.posts
addAllPagesToCollections: true
size: 20
size: 10
permalink: /posts/{% if pagination.pageNumber > 0 %}page/{{ pagination.pageNumber }}/{% endif %}index.html
---
{% extends 'layouts/default.njk' %}
@ -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>{% if entry.data.coauthor %} and <span class="author by" id="author">{{ entry.data.coauthor.name }}</span>{% endif %}</span>
<span>by <span class="author by" id="author">{{ site.name }}</span></span>
{% if entry.data.tags %}
<span class="middot"></span>
<span>in

View File

@ -9,7 +9,6 @@ tags:
- osint
- research
- memes
- culture
---
> [this blog post was originally a tumblr post](https://www.tumblr.com/nyancrimew/719391254132195328/entirely-unrelated-to-the-actual-posts-above-but), inline links are sources

View File

@ -1,83 +0,0 @@
---
title: "we have reached rabbit hole rock bottom"
date: 2023-11-03
description: "an increasingly wild tale of spiritual tiktoks, hyperpop, NFTs, white supremacy, cults and even more NFTs"
feature_image: /img/posts/brg/cover.jpg
feature_alt: "a glitchy edited collage of various images and screenshots related to basedretardgang, remilia and milady"
tags:
- analysis
- osint
- research
- memes
- culture
- politics
- social media
content_warnings:
- slurs
- xenophobia
- suicide/self harm
- grooming
- eating disorders
- cults
- femcel culture
- edgelord shit
- NFTs
---
if you've ever used tiktok before and had a somewhat queer and weird fyp you've probably seen one of basedretardgang's (their username on tiktok is now `basedredactedgang`) tiktoks before, videos of asian girls (mostly kpop stars and chinese models) posing in nature or dancing overlaid with a feminine text to speech voice listing off somewhat edgy mental health themed affirmations. the weird mix is confusing yet also incredibly captivating; which is probably how they have amassed almost 60 thousand followers and almost 2 million likes in just over a year. their bio simply reads "444x7x2, this is fantasy, there is no #𝔅𝔊, i love you".
{% figure { src: '/img/posts/brg/tiktok.mp4', type: 'video', caption: 'the most popular tiktok on BRGs tiktok account. it has almost 1mil views' } %}
## the dive begins
as with any other mysterious account on the internet a lot of people in the comments were wildly speculating who might be behind BRG. i too got curious after the account kept appearing on my feed again and again. however, as opposed to the average tiktok user, i actually decided to click on the carrd link in the bio. the site contains links to their social media accounts, their discord server and their bandcamp. the latest tweet on the twitter account is a retweet of a post from BRG-affiliated `@affirmationals` announcing the minting of 3333 NFTs of BRG created affirmational poster. the bandcamp link redirects to the 'Remilia Records' label bandcamp page via a `remilia.org` subdomain, which currently contains nothing but the first BRG album (of which 150 casettes were sold).
remilia... that sounds vaguely familiar, im sure ive read about them before, and not in any good context. their website, which is a shopify-hosted online store, has various banners with scrolling blue text displaying sentences such as "We're whitepilled", "We're Wired, we're Not in Employment Education or Training" and "Remilia will save the internet". most of their merchandise contains silly [chibi](https://en.wikipedia.org/wiki/Chibi_(style)) avatars in a style reminiscent of old video games. the posing reminds me a lot of NFT profile pictures. in the middle of the site there is an announcement for the basedretardgang album, calling BRG the "chaotic, lovepilled collective formed of network spirituality acolytes from the Milady community" further claiming that they were "the World's First Post-Identity Hyper-Referential Post-Authorship K-Pop Group". the 'About Us' link in the site's menu takes us to yet another site, this one being for the "Milady Maker" NFT project. the avatars from earlier are indeed NFTs. the old japanese videogame inspiration becomes even more evident on the milady website, there is even an embedded audio player with a soft videogame music style soundtrack for the website.
<figure>
<div>
<audio controls loop>
<source src="/files/posts/brg/ost.ogg" type="audio/ogg">
<source src="/files/posts/brg/ost.mp3" type="audio/mpeg">
</audio>
</div>
<figcaption>the milady website OST. you can listen to it while you read the rest of this article</figcaption>
</figure>
{% figure { src: '/img/posts/brg/there-is-no-meme.jpg', alt: 'an image of a milady avatar with a circle of flowers surrounding their head. the image is captioned saying "there is no meme, i love you"', caption: 'this really popular meme ([even elon musk shared it](https://twitter.com/elonmusk/status/1656326406618619910)) contains a milady avatar' } %}
## horrible history reveals itself
one of the first things that comes up when you google "remilia milady" is [this Web3 is Going Just Great article](https://web3isgoinggreat.com/single/founder-of-milady-nft-project-revealed-to-have-horrifying-history) (which is based on this [this twitter thread by 0xngmi](https://twitter.com/0xngmi/status/1528572556894142464)), covering the dark past of Charlotte Fang, the founder of remilia. the allegations are heavy: under the pseudonym "miya", fang used to be a core member of a supremacist cult called [Kali Yuga](https://www.researchgate.net/publication/340026825_Esoteric_Fascism_Online) Accelerationism (abbreviated "kaliacc"), a popular promotional tweet for which showed images of a severely underweight person having cut a swastika into their tummy. in kaliacc and other [pro-ana](https://en.wikipedia.org/wiki/Promotion_of_anorexia) spaces, fang (in their own words) and other members "groomed" and "bullied" young people, particularly trans and underage girls, into disordered eating and self harm. many other key members of remilia were allegedly also involved with said cult, and the main remilia website at one point even contained quotes from kaliacc. also under the "miya" alias, they were also involved in a cyberpunk-themed suicide cult originating from 4chan called [TSUKI Project](https://www.vice.com/en/article/ne3p9z/the-obscure-4chan-religion-that-promises-a-cyberpunk-afterlife), while allegedly (like anything from 4chan) "just a troll" or as others claim merely an ARG it still resulted in at least one suicide. after fang at first tried to deny the accusation, they [eventually admitted to being miya](https://mobile.twitter.com/CharlotteFang77/status/1527987970862718976), resorting to understating their actions as "trolling" which doesn't reflect their "real views". despite at the time claiming to be stepping down from their involvement in milady and remilia, they are now, over a year later, still deeply involved in both and credited both on the milady website as well as in the remilia and milady twitter account bios. another [well researched twitter thread a few months later](https://twitter.com/nyatsumimi/status/1534318797200539650) further links fang to ["Gordon Goner"](https://en.wikipedia.org/wiki/Bored_Ape#Founders), one of the founders of Bored Ape Yacht Club, with leaked messages by fang saying they used to talk to goner in a kaliacc and that he might have been the inspiration for milady. certainly also explains why the company behind bayc, Yuga Labs, is named after the same Kali Yuga as kaliacc.
## going deeper
the spiritual vibes surrounding basedretardgang were starting to leave a pretty sour taste at this point, but i felt the need to dig deeper and find out where this all leads me - i decided to join the BRG discord server. in there i was immediately greeted by channels such as **`#🙏-prayer-circle`**, **`#💣-targeted-lovebomb-c2a`**, **`#💹-retard-finance`** (since renamed to **`#💹-pinkrock-financial`**, clearly as a nod to [BlackRock](https://en.wikipedia.org/wiki/BlackRock)) and **`#🔎-retard-truth`**. the prayer circle is, as the name implies, a channel where people request prayers and pray for others, supporting each other in difficult life situations, or just unpromptedly praying for all the other 'tardies'. the lovebomb channel is somewhat similar - people who are going through some shit might vent and request emotional support or 'love' might just be sent out to everyone in the server, be it in the form of emojis or positive affirmations. the finance channel, as you might expect at this point, is primarily about crypto investment. it contains people such as the founder of [Alpha Wolves DAO](https://twitter.com/alphawolvesdao) trading shitcoins with names such as "$BPD", and of course lots of NFT talk. in **`#🔎-retard-truth`** we can learn a lot about various conspiracy theories and the interpretations of the "BRG faith" members of the server might have.
{% figure { src: '/img/posts/brg/cdgraph.jpg', alt: 'a screenshot of a discord message containing an image of a hand drawn graph. it displays a cycle of depression, melancholy, stillness, calm, excitement, mania and greed in the middle of the image there is a massive CD emoji', caption: 'whatever the fuck this could mean' } %}
during my time in the discord server there were almost daily announcement **`@everyone`** pings, or sometimes even just simple <code><b>@everyone</b> i love you</code> messages in the general chat. one announcement a few days ago really caught my eye though - BRG was organizing a show in a well known underground venue with an incredibly stacked lineup, half of it various underground rap and hyperpop legends and the other half random members of BRG's music group. how did all of these reputable artists agree to play such an edgy show? as i quickly learned from furious tweets all over hyperpop twitter (i cant believe i just put those words in an article), they didn't. most artists on the bill allegedly weren't aware of the BRG association of the event until the flyer dropped and weren't shown any of the rest of the evening's lineup. multiple of those artists retracted and about two days later the venue and promoters dropped BRG as well. i get pinged in another announcement, apparently "the show has run into some hiccups" given their "military industrial complex funding" which is "a problem for some reason", they then state that having to look for a new venue and lineup is a blessing actually since they will have "much more freedom!" this way. the offhand mention of military industrial complex funding here is making fun of various post-announcement twitter callouts that reference the milady rave earlier this year. the lineup of that event also featured underground legends such as [2hollis](https://soundcloud.com/2hollis), and it was additionally co-sponsored by [The Praxis Society](https://www.motherjones.com/politics/2023/09/praxis-society-city-dryden-brown-peter-thiel/), a Peter Thiel-funded startup trying to build a libertarian paradise city in the mediterranean, where all the great thinkers of our times are supposed to live. this isn't actually super relevant to BRG or the story at hand, but feels worth mentioning anyways while we're going down this rabbit hole together.
## the ideology/vibes
a lot of the ideology surrounding BRG and milady is much more about vibes and aesthetics than any particularly specific political orientation or goal. it's built up around femcel culture, the idea of having low intelligence and not having to think, and a certain post-ironic obsession with china and particularly chinese women. a lot of BRG members, especially in the core, take on the persona of a chinese girl, using random photos from [xiaohongshu](https://en.wikipedia.org/wiki/Xiaohongshu) and videos from [douyin](https://en.wikipedia.org/wiki/TikTok). a lot of their posts on twitter contain wild norm-breaking claims, either directly repeating chinese propaganda ("china is 3000 years ahead of the west", denial of the [uyghur genocide](https://en.wikipedia.org/wiki/Uyghur_genocide), etc.) or by making edgy claims about how unemployed chinese e-girls are the peak of humanity, even going as far as calling them "Chinese Aryans".
{% figure { src: '/img/posts/brg/chinese-aryan-tweet.jpg', alt: 'a screenshot of a tweet by BRG Rain that reads "The ameri-mutt fears the Chinese Aryan. It\'s an example of everything that they are lacking in. The pure quirked up vibe that is coming off of just one picture is enough to send them into shock. They cannot comprehend what it\'s like to be a transracial princess and I pity them." it has an image of a random chinese e-girl attached', caption: 'i am really starting to question my sanity more and more as i write this piece' } %}
a lot of these posts obviously attract massive backlash and thus attention on western social media, with the tweets often getting tens of thousands of interactions. the fetishization of chinese women and the larping as such is taken even further by some members, claiming that [rcta](https://www.indy100.com/tiktok/rcta-tiktok-meaning-transracial-asian) (race change to another, or "transracialism") is valid. however it's important to keep in mind with all of these claims, like with any other channer style post-ironic edgy movement, that most of what is said is considered merely "trolling" by the posters. the goal isnt to actually Be Chinese, it's about inhabiting the fictional idea of what the life a douyin star might be like.
{% figure { src: '/img/posts/brg/adhd.jpg', alt: 'a screenshot of a discord message, it reads "ADHD is not real, it doesn\'t exist. I have epic Chinese wigger retard syndrome disorder condition, it\'s where I wake up and go sicko mode every day. Other symptoms of this disorder include addiction to raw garlic, compulsive lovebombing, excessive happiness and success, and a deficiency in complacency and anxiety. The only treatment to this disorder is persistent sin."'} %}
## "there is no brg, i love you."
*it's all some elabaorate joke, and anyone who falls for it or takes it at face value has noone but themselves to blame.* given the ties to various NFT projects BRG actually makes it super lucrative to have people fall for their idea of a greater goal. they adopt the accelerationist idea of the "clear pill", as opposed to red, blue, white or blackpilling; clearpilling is about a radical acceptance of societal chaos, finding acceptance in the things being as fucked up as they are. when i asked what the mission of BRG is a staff member told me in DMs,
> Ultimately our mission is freedom for ourselves and those around us. I personally believe that the only way to combat censorship and hysteria is to present so much conflicting information that the observer has no choice but to either go insane trying to understand or to simply live laugh and love.
{% figure { src: '/img/posts/brg/what-if.jpg', alt: 'a screenshot of a tweet by luvbug, it reads "what if we could make them seethe so much that they give up their self assigned role as a world saver and simply lived laughed and loved? what if... what if we see you hurting and after much thought, our conclusion was to confuse you until you surrendered to faith. what if..."', caption: 'in addition to the statement above i was sent a link to this tweet'} %}
there is a certain comfort in not having to think for yourself, just letting things happen around you and i too have shared quite a few queer "no thoughts head empty" memes or joked about never having to to think or do things given im a kitten. escapism like that is much needed as a break from the overwhelming and often seemingly doomed capitalist world we live in, but i don't believe there is much use in this as an ideology, something i would call 'defeatist accelerationism'. it can be observed in many similar circles and entails letting whatever happens happen while revelling in the absuridity of it all, not giving a thought at all to consequences, falling back to the idea that it's all just a game. this might be somewhat healing at first, and that's certainly why it draws people in, but in the longer term it will result in nothing and consequences will come down on you regardless of if you care about them or not ([i would know](https://en.wikipedia.org/wiki/Maia_arson_crimew#Indictment)). as [C.T. Kelly](https://www.patreon.com/normalhoroscopes) puts it, "the end point of an ideology like this is that it gets popular enough to be commercialized. Because it is a pure aesthetic, it will be flattened and resold until it is no longer transgressive."
the hard thing about writing about communities like this is that any kind of coverage they get, no matter how negative, will be seen as a positive. the discord server already contains various memes and 'propaganda' referencing the recent twitter callouts and the same will probably happen with this article. BRG considers themselves "already cancelled", so everything will just carry on as normal, which is illustrated well by the staff member i talked to simply saying "don't worry about it" when asked about the various allegations against BRG. my hopes with this piece however are to help out any bypassers and curious googlers trying to understand what hides behind the weird tiktok/instagram account they stumbled upon and to highlight just one of many weird new 'post-modern' internet subcultures like this one.
a huge thanks goes to [C.T. Kelly](https://www.patreon.com/normalhoroscopes) and Armaan Maharaj for the massive help dissecting the culture in and around BRG and and for keeping me sane while working on this piece, despite it doing "some cocomelon shit" to all our brains.

View File

@ -37,4 +37,4 @@ ok i feel like it should already just be clear from the previous section why sta
alright so, see point 5 above? yea that, i will be collecting stalkerware breaches sent to me, looking into companies myself, and blogging about them one by one. revealing (as far as possible) how unsecure they are, who's behind them, trying to get comment, and helping other journalists with stalkerware related reporting. two blog posts are already in the works, and if you have anything to contribute to potential reporting (vulns you find in stalkerware software, leaked data, investigations, insider info \[your identity will be protected], etc) or are a journalist looking to cover anything in this series in more detail, [contact me](/contact/).
*note: [the EFF has also been doing really important work rooting out stalkerware for many years now](https://stopstalkerware.org/) (cool website to learn even more about stalkerware too)*
> note: [the EFF has also been doing really important work rooting out stalkerware for many years now](https://stopstalkerware.org/) (cool website to learn even more about stalkerware too), which i have previously contributed to with other work, which i will not link due to it being linked to my deadname

View File

@ -1,7 +1,6 @@
---
title: "#FuckStalkerware pt. 3 - ownspy got, well, owned"
date: 2023-08-25
changed_date: 2023-09-13
description: "more like ownedspy amiright"
feature_image: /img/posts/fuckstalkerware-3/cover.jpg
feature_alt: "screenshot of the start of a file called README.txt, there is big ascii textart reading 'ownedspy', and text below reads 'ownspy is REALLY REALLY owned!!! #fuckstalkerware #antisec #acab' and 'The #fuckstalkerware games continue. Another one bites the dust.'"
@ -177,7 +176,7 @@ the release message then ends here in "Greetz to LeopardBoy and the Decepticons.
other than the write-up the package i was sent contained a text file with all device ids, a text file with users listed in `<email>:<hashed password>` format (hi and welcome to my blog post troy hunt), as well as the raw admin portal and isreg scraping results, containing additional user data, some info on target device (phone type, os version, ownspy version), all user sign in IPs and dates and payment history. i have decided to republish this data as is, i have no interest in protecting stalkers and given victim data has been deleted there is little risk of direct additional compromises.
**ownedspy.zip (ZIP, 151405 files, 368MB), previously available as a torrent**
**ownedspy.zip (ZIP, 151405 files, 368MB), available as a [torrent](/files/posts/fuckstalkerware-3/ownedspy.zip.torrent) ([magnet](magnet:?xt=urn:btih:cf0cc9cd6dae802d2bf415ccb4cc9b29c32a04f0&dn=ownedspy.zip))**
## basic analysis

View File

@ -1,78 +0,0 @@
---
title: "#FuckStalkerware pt. 4 - the truth come out: does TheTruthSpy is secure"
date: 2024-02-12
description: "they had like two years to fix this shit, jesus christ"
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
- leak
- exploit
- asp.net
- security
content_warnings:
- mentions of abuse/controlling behaviour
---
*if you want to know if your phone is/was infected with TheTruthSpy's stalkerware you can use the [lookup tool provided by TechCrunch](https://techcrunch.com/pages/theTruthSpy-investigation/), which has been updated to include all data from this leak as well. to learn about what stalkerware is and why it is bad read the [first entry of this series](/posts/fuckstalkerware-0/).*
just how many times can a company get hacked in exactly the same way until they (hopefully) start giving a shit? the answer turns out to be at least **four times**, which let's jusr say, is quite often. [originally hacked twice in 2022](https://techcrunch.com/2022/02/22/stalkerware-network-spilling-data/) TheTruthSpy (and its parent company 1Byte) may have just broken some sort of world record, getting hacked again by [ByteMeCrew](https://t.me/ByteMeCrew) and [SiegedSec](https://t.me/SiegedSecurity) in the exact same way and then *again* by me in about four different ways.
when members of the two hacking groups looked into TruthSpy last december while searching for stalkerware to hack, they independently stumbled upon the same [IDOR](https://en.wikipedia.org/wiki/Insecure_direct_object_reference) <small>(help out wikipedia and anyone trying to learn more by expanding this article)</small> vulnerability originally reported on by TechCrunch ([CVE](https://nvd.nist.gov/vuln/detail/CVE-2022-0732)), which evidently had not been fixed yet. this easily exploited type of vulnerability appears when data is retrieved without verifying that the client has the right to do so. a query parameter denoting a user ID (`like https://example.com/users/?id=123`), for example, allows for simple enumeration and scraping of data that is typically difficult to access otherwise. since this vulnerability in TruthSpy STILL isn't fixed at the time of writing i am unfortunately unable to publicly talk about where and how exactly this vulnerability was exploited as i usually would.
upon exclusively receiving the data from ByteMeCrew to report on it i decided to contact [Zack Whittaker](https://techcrunch.com/author/zack-whittaker/) (who wrote the aforementioned TechCrunch article) to collaborate on the research and reporting (shoutout to Zack for being one of the very few journalists writing about stalkerware btw, much love). he quickly got to reaching out to the server hosters and payment providers used by TruthSpy to inform them of the TOS violations. the resulting game of whack-a-mole ended with them switching to Moldovan hosting company [AlexHost](https://alexhost.com), who has yet to respond to any requests, and moving checkouts to p2p payments (presumably via crypto) via their support portal (after 1Byte initially scrambled to use the checkout experiences of their non-stalkerware projects for TruthSpy as well).
with most of the in-depth reporting on TruthSpy's background already having been done by Zack two years ago, i decided to focus my research on trying to uncover more of the inside workings of 1Byte, their various non-stalkerware ventures (primarily online language learning apps), their CEO Van "Vardy" Thieu and the full breadth of their disregard for cybersecurity 101.
### 1Byte, i am inside you
> take me down to [IDOR city](/img/posts/fuckstalkerware-4/what-is-this-mp4-city.mp4) where the bugs are dumb and the site is shitty
one of the first things i wondered was whether i could find an employee with TheTruthSpy on their personal device for testing and indeed, a search for "1Byte" in the leaked data reveals a device that has two contacts containing "1Byte" in their name as well as various contacts for test devices, most of which included the device model in the name.
![a heavily redacted screenshot of visual studio code, showing a csv file as a search result for the term "1Byte" with various contacts related to test devices and 1Byte employees](/img/posts/fuckstalkerware-4/1byte-contacts.jpg)
one of the two employees found there publicly identifies himself as a database engineer working at 1Byte on linkedin. the other one is harder to track down, though their phone number is linked to a [vk](https://en.wikipedia.org/wiki/VK_(service)) account active all the way back in 2014, advertising a predecessor to what has now become the TruthSpy network of apps. we can't gather much more info from this test device though, as only contacts were actually ever synced.
sticking to general 1Byte infrastructure i scanned for subdomains on the 1Byte corporate domain and just like TechCrunch found partial and public Jexpa Framework (the common framework/backend used for all 1Byte apps) documentation. yep, they fucked up again. what i found this time was even more interesting though: two different supposedly internal portals for employees. the first of the two was a [gitbook](https://www.gitbook.com/) documenting most of their employee onboarding process and company structure, conveniently including an organizational diagram of the company, among various other bits of interesting corporate data.
![an organizational diagram of the 1Byte company mentioning various management people and departments in vietnamese](/img/posts/fuckstalkerware-4/1byte-orgchart.jpg)
and yet the second one, a [freshdesk](https://www.freshworks.com/freshdesk/) helpdesk for employees, would prove to be even more useful for gaining an inside look at 1Byte. contained within the knowledge base is information on the per-department software stack, salary information, detailed employment benefit terms, a guide on buying botted facebook likes for their marketing team as well as a link to a publicly viewable time tracking google sheet. over the various sheets i was able to see all the logged time in 2023 for all 1Byte employees, their full names, whether they work full or part time and their roles at the company.
![a partially redacted screenshot of a vietnamese google sheet showing time tracking info of all 13 1Byte vietnam employees in september 2023](/img/posts/fuckstalkerware-4/1byte-timesheet.jpg)
now with a basic understanding of the company internals it was time to start exploring their various products to try and find some more interesting data. monitoring the sites network traffic using firefox developer tools i signed up for one of their websites, a daily english pronounciation training app. clicking around on the site and using various features i got a bit of an idea of the shared Jexpa backend. making some bold assumptions about the security of the API i almost immediately found multiple IDOR vulnerabilities, letting me grab all user data and even analytics tracking data without any authentication of any kind. matching this user data (about 35 thousand users across all applications) to the employee names we found earlier gave me a list of personal email addresses and phone numbers for some of them, which i used to reach out for comments, very curious to see if anyone would be willing to speak to me about the company. at the time of writing none of the three current and former employees i reached out to have given any response, this article will be updated if they do.
because it wouldn't be a [#FuckStalkerware](/posts/tagged/fuckstalkerware/) post anymore without a bit of webshell action, i tested the profile picture update endpoint for arbitrary file uploads and as is standard by now it sure allowed for it, once again without authentication of any kind. the problem i began facing then though was having to deal with [ASP.NET](https://en.wikipedia.org/wiki/ASP.NET) for the arbitrary code execution, since their infrastructure all runs on windows. since i want to avoid ever having to deal with a windows cmd shell and am lazy as shit i spent quite some time finding a cozy enough advanced ASP webshell that also doesnt immediately break when i try to use it. thankfully i eventually found something that would work in my favorite [chinese webshell collection on github](https://github.com/tennc/webshell) (look, doing skid shit is fun and easy, we all do it sometimes, especially when working with windows, and i have already written more than enough single-use tooling for this research). while this shell generally worked really well for what i wanted to do i still somehow managed to crash the Jexpa CDN .NET instance, semi-breaking their apps for almost a day, with the person who eventually fixed that not even noticing my intrusion. awesome ^-^
![screenshot of the r00ts.asp webshell running on the jframework webserver. it is in green on black design and most ui text is in chinese](/img/posts/fuckstalkerware-4/r00ts.jpg)
with the shell planted on the system i did my usual prowl through the file system, copying anything i was interested in (backups, webserver .NET binaries, etc) to the public cdn directory so i could very quickly download them using [aria2c](https://aria2.github.io/). digging through this data i didn't really find much of note that i hadn't already grabbed via IDOR, but it was still an interesting insight into their infrastructure and another testament to their bad security.
finally having a separate test phone again to run shady software on in an isolated context, i set out to also actually look over the TruthSpy attack surface as well. a decompilation i did of the client earlier showed that the app contacts its backend completely over plain HTTP, which is a massive privacy and security issue due to how easy it makes the interception of all traffic when on the same network, like on public wifi. however, it also makes my analysis super easy :3! i set up [ZAP](http://zaproxy.org/) to intercept all traffic from the phone and installed the client. it was apparent that the device api still has no authentication beyond sending the device id with all requests.
trying to get a potential way to drop another webshell i played around with the photo history and remote photo features, "remotely" taking a photo of myself without touching the phone at all. it definitely felt kind of scary, even after all the research ive already done into stalkerware by now. after some futile tries to use the endpoint to upload arbitrary files i gave up, but as Zack has previously [reported on data leaked from the TruthSpy server](https://techcrunch.com/2023/07/20/thetruthspy-stalkerware-forged-passports-millions/) already i wasn't too bummed. looking through all the other endpoints called by the client i ended up finding the final IDOR vuln to complete the data puzzle i'd been assembling, a way to get the abuser account email addresses from the device ids i already had from the ByteMe leak. however i only managed to grab emails for about half of all affected devices, as the device api is seemingly just broken for a large number of (older) devices, returning internal error messages (mostly null pointers and array out of index errors) rather than the requested data.
{% figure { src: '/img/posts/fuckstalkerware-4/tts-selfie.jpg', alt: 'a low resolution selfie of me covering my face with one hand doign the peace sign and holding my other hand up in the air. i am wearing a merch piece from the musician femtanyl, a long sleeve and headphones', caption: 'the hands free selfie i remotely took using TruthSpy' } %}
### digging your own grave 101
before publishing this article i reached out to Van "Vardy" Thieu to give his company time to fix all of the discussed security issues and give a chance to comment ahead of release. after somewhat pressing him on the urgency of these issues multiple times he committed to getting his team to fix at least some of the issues "after 8 hours". with nothing having changed two days later i gave him another heads up, to which Thieu gave a longer and clearly pretty annoyed response, with him among other things stating that they "do not care of it too much" about the reported security issues, blaming it on their small team size and an alleged lack of funds, saying it is "a low priority".
> we dont have enough time to explain [to] you. so you can write what you want. <span>Van "Vardy" Thieu, CEO of 1Byte</span>
regarding the publicly linked and accessible google sheets with employee information he claims that "it is internal info and it is not allowed to be public by you. [...] it looks like you are a hacker and want to expose info without permission", refusing to fix even that. he also further repeats his past claims of not being involved with TruthSpy (which according to Thieu has "another name (not the name you wrote)"), claiming it is an outsourcing project for a customer done "7,8 years ago" that they have no control over anymore. this is verifiably wrong: the current server infrastructure for TruthSpy references the name of another business publicly associated with Thieu and checkout infrastructure of various 1Byte projects is being used for them, so even if it were a project they operate for a third party it still is fully under their control.
### conclusion
the main thing this long investigation has shown is that not only is the stalkerware platform by 1Byte horribly insecure, but also all their other ventures, such as the educational tools under the VardyTest brand are no different. expecting this company to ever change or improve seems foolish looking at the track record they have paired with Thieu's statements, but the only way forward i see for them is to completely shut down operations and disband to show they at least somewhat care about user safety, even if it's too little too late. more broadly this once again shows that most companies who run stalkerware operations primarily do so as a quick and easy cash grab, but dealing with the various legal, ethical, and moral risks and challenges only really makes sense if all other ventures are horribly failing.
while i am not one to believe in regulation as a proper solution to combat problems such as stalkerware i would hope to at least see some sort of legal action against a company like 1Byte, who has been running a [massive fraud operation](https://techcrunch.com/2023/07/20/thetruthspy-stalkerware-forged-passports-millions/) for years while enabling domestic abuse at a massive scale, all with a provable complete disregard for user security, even if it's just symbolic.
*if you have any data, insider info, vulnerabilities or any other tips related to stalkerware (or in general) you can securely reach out either to [me](/contact) or [Zack](https://techcrunch.com/author/zack-whittaker/).*

View File

@ -1,34 +0,0 @@
---
title: "#FuckStalkerware pt. 5 - déjà vu? OwnSpy pwned again"
date: 2024-05-07
description: reporting on stalkerware feels like being trapped in a timeloop
feature_image: /img/posts/fuckstalkerware-5/cover.jpg
feature_alt: a glitchy pink illustration of a y2k-/cyberpunk-style stalkerware dashboard with a y2k-style WebDetetive logo in the top left and crosshairs drawn over the whole image
feature_caption: feature art by [Mukky's World](https://mukkysworld.neocities.org/)
tags:
- "#FuckStalkerware"
- stalkerware
- research
- analysis
- leak
- exploit
- security
content_warnings:
- mentions of abuse/controlling behaviour
---
y'know, after the [TruthSpy](/posts/fuckstalkerware-4/) saga earlier this year i shouldn't be surprised anymore when stalkerware companies get hacked the same way two or three times, but i didnt expect to have to already write a followup to the [third article in this series](/posts/fuckstalkerware-3/). but here we are: an anonymous source [tipped me off](/contact) about another way to access the administration portal discussed in the [writeup](/files/posts/fuckstalkerware-3/README.txt) by the original hacker.
in the original hack last summer, my source managed to access an administration portal for {% footnoteref "portuguese-exists", "realizing the company is called WebDetetive (you know, in portuguese, the language they speak in brazil) and not WebDete<b>c</b>tive a bit earlier would've made my research for this piece significantly faster and easier, but would've unfortunately also required reading skills" %}WebDetetive{% endfootnoteref %} (a whitelabelled version of OwnSpy for the brazilian market) using a convoluted multi-step process involving [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) and cookie reuse. and while those vulnerabilities seem to be fixed now—with one of the servers targeted in the original attack still being offline—there was an easier way into the `admin.webdetetive.com.br` panel all along. the anonymous tipper for this story, looking into the panel from the old write-up, simply guessed some commonly used URLs. and after a bit of brute-forcing for a signup page, they found this:
![a screenshot of a signup form at admin.webdetetive.com.br/signup.php. it is entitled "sign up OwnSpy affiliate network"](/img/posts/fuckstalkerware-5/signup.jpg)
it really is that easy: you sign up using the form and immediately gain access to the admin portal. the frontend looks fairly similar to the OwnSpy affiliate network dashboard, with many pages having been simply copied over, which probably resulted in the accidental inclusion of the registration page. a key difference to the affiliate dashboard, however, is that the admin portal shows you the personal information of all customers on the service.
the "API Log" page, for example, shows a list of actions performed by and on user accounts, including signups, credit recharges, device activations, and account deletions. clicking on an email address in this log shows all customer and target device info, letting you perform various actions on the account, such as extending licenses, disconnecting devices or accessing the stalkerware dashboard as the customer for troubleshooting. the latter, in fact, actually allows us to confirm (for once) a claim that tends to be rather outlandish in the stalkerware industry: most data OwnSpy collects is {% footnoteref "e2e-how", "decompiling the android client shows this to be true as well; the data is encrypted on-device" %}indeed end-to-end encrypted{% endfootnoteref %} and neither support staff nor any bad actors with access to OwnSpy systems can see most victim data. the one big exception is location data, which isn't encrypted in any way (despite being one of the most sensitive pieces of information available). the log also confirms that the built-in device delete feature was used in last summers hack to disconnect all devices from the service. it is not clear, however, if the pre-hack data was restored by OwnSpy.
{% figure { src: "/img/posts/fuckstalkerware-5/user-portal.jpg", alt: "a screenshot of the WebDetetive stalkerware dashboard showing various pieces of redacted victim info and a heavily blurred map in the middle", caption: "even though admins have full access to customer dashboards, most data is still encrypted (we still redacted all encrypted data to ensure it can't be decrypted by anyone in the future)" } %}
at this point i wanted to dive a bit deeper, since the exact connection between WebDetetive and OwnSpy still wasn't quite clear. reading through the writeup from last year again, i realized there was a mention of yet another brand name i hadnt seen before, SaferSpy. upon checking it out, both the landing page and portal are pretty much verbatim copies of those in WebDetetive but in english instead, despite being made for the brazilian market. they both even point to the same servers internally, so i was able to just sign into the admin portal with the credentials i created on WebDetetive's end, with the only difference being the customers displayed. the only other difference between the two is in who runs each service: WebDetetive's domain is registered to brazilian businessmen Roberto Duarte Fochezatto and Leonardo Duarte Costa (whose main business—besides selling stalkerware—appears to be reselling used vehicles), while SaferSpy has no names linked to it but uses a completely different domain registrar and hoster. it's pretty clear that these sites are most likely whitelabelled resellers of OwnSpy, however: they share a backend of `era3000.com`, registered in the same city as Mobile Innovations—the spanish company behind OwnSpy—and hosted via OVH's spanish branch instead of their brazilian branch.
in an attempt to get some answers to my questions above, i reached out to Antonio Calatrava, the spanish CEO of Mobile Innovations. he didn't respond to my request, but when i checked the servers again a few days later, the WebDetetive and SaferSpy admin portals had been reworked to remove my access: the signup form had been removed, my account was completely deleted and the OwnSpy affiliate network portal vanished entirely from the internet, now redirecting to the OwnSpy landing page and leaving me as neither an admin nor an affiliate (for my next business idea i might start reselling used cars). and even though Calatrava didn't respond to my email (he might have been too busy with his AI podcast), im treating the super fast vulnerability fixes on both SaferSpy and WebDetetive infrastructure as further evidence that they are indeed reseller sites mostly operated by Mobile Innovations themselves.

View File

@ -33,7 +33,7 @@ i am informed that the US government has charged me for "conspiracy, wire fraud,
less than a week later i wake up to hundreds of dms and massive chaos on social media, i am once again going through a news cycle, the third time in just two weeks. my US indictment has been unsealed and there is a big press release on the justice.gov website.
> A cyber-criminal could be anywhere in the world. Thanks to our foreign partnerships, international borders won't provide a haven for their illegal activities,” said Donald Voiret, FBI Special Agent in Charge, Seattle. “This indictment demonstrates the FBIs commitment to working with our partners around the globe to disrupt and dismantle criminal enterprises that target Americans and their businesses.
> A cyber-criminal could be anywhere in the world. Thanks to our foreign partnerships, international borders won't provide a haven for their illegal activities,” said Donald Voiret, FBI Special Agent in Charge, Seattle. “This indictment demonstrates the FBIs commitment to working with our partners around the globe to disrupt and dismantle criminal enterprises that target Americans and their businesses.
i have been made an example.

View File

@ -14,8 +14,9 @@ feature_image: /img/posts/how-to-hack-an-airline/cover.jpg
feature_alt: "a glitchy edited photo of an airplane"
---
*note: this is a slightly more technical\* and comedic write up of the story covered by my friends over at dailydot, which you can read [here](https://www.dailydot.com/debug/no-fly-list-us-tsa-unprotected-server-commuteair/)*
*<small>i say slightly since there isnt a whole lot of complicated technical stuff going on here in the first place</small>*
> note: this is a slightly more technical* and comedic write up of the story covered by my friends over at dailydot, which you can read [here](https://www.dailydot.com/debug/no-fly-list-us-tsa-unprotected-server-commuteair/)
> <small>*i say slightly since there isnt a whole lot of complicated technical stuff going on here in the first place</small>
## step 1: boredom

View File

@ -1,59 +0,0 @@
---
title: "so i guess i hacked samsung?!"
date: 2024-04-01
description: "it's not quite xz but at least my grandma knows what samsung is"
feature_image: /img/posts/i-hacked-samsung/cover.jpg
feature_alt: "a glitchy edited image of clouds and a screenshot of samsung cloud accompanied by their logo"
tags:
- bug bounty
- leak
- security
- infosec
- jenkins
- cloud
---
having just finished a full draft of the [latest stalkerware article](/posts/fuckstalkerware-4/), i decided to wind down in the most "maia&trade;" way possible and, just like [when i discovered the no-fly list](/posts/how-to-hack-an-airline/), i started going through random jenkins servers on [zoomeye](https://zoomeye.org) to pass the time. there were a few mildly interesting targets, but nothing that really caught enough of my attention to stop and do any deeper research (i'll probably get back to some of these in the future, don't worry). that was until i clicked on a south korean microsoft azure server, still not expecting much until firefox hit me with a warning that the https certificate of the site i was accessing via its IP address is only valid for "\*.samsungcontinue.com". wait a sec. samsung? holy fuck is this samsung?
![a screenshot of the job configuration screen in jenkins; it shows that a repository is being cloned from the samsung ecode github](/img/posts/i-hacked-samsung/jenkin.jpg)
adrenaline immediately rushed through my entire body, if i can get just about anything out of this it would be massive. checking the project configurations i saw a connection to samsungs github enterprise instance and thanks to the anonymous admin privileges (as always) i could grab the github access token for the used bot account. using that to list all repositories that account has access to it became clear just how much samsung cloud stuff i was about to gain access to.
![screenshot of a terminal showing me using curl and jq to get a list of repositories from the samsung ecode github api](/img/posts/i-hacked-samsung/github-api.jpg)
![screenshot of a heart rate graph, showing a peak at around 1am with my heart rate averaging at 144bpm, the peak being 192bpm and the low being 96bpm](/img/posts/i-hacked-samsung/awesome-maia-heart-rate-leak.jpg)
with my heart rate rapidly raising all the way up to almost 200bpm and my hands shaking, i wanted to gain a better understanding of the actual impact: i cloned all the repositories, wrote a quick script (see below) to switch to each repo's most recently edited branch (the main branch was empty on most of them), and started going through the around 130 repositories to figure out what exactly i was looking at.
```bash
#!/bin/bash
# iterate over all repositories (subdirectories) in the organization directory
# if you are using this for your own usecase just modify the path here
for repo in SamsungCloud/*; do
# we use `git -C` here to run commands in each repository without having to manually cd in and out
# find last edited branch (including remote branches)
branch="$(git -C $repo branch -av --sort=committerdate --format='%(refname:short)' | tail -n1)"
# checkout that branch (note that for remote branches this will create a loose head,
# rather than a local branch referencing the origin)
git -C $repo checkout $branch
done
```
checking out folder after folder i found more and more [ansible](https://en.wikipedia.org/wiki/Ansible_(software)) modules, one for each samsung cloud service, as well as the [terraform](https://en.wikipedia.org/wiki/Terraform_(software)) configurations for much of samsung amazon aws network and source code for various in-house infrastructure and operations tools. while this isn't quite as big of a dataleak as i'd hoped for it's still pretty damn bad, it gives me (or a potential bad actor) a unique insight into the internals of samsungs backend infrastructure and tech stack. it is also only thanks to the jenkins server in question being so new (and barely set up) that i wasn't able to gain access to more data or move laterally—the server still wasn't at all integrated into the internal samsung cloud network—and with the hashicorp vault setup on the server being broken i wasn't even able to access the amazon s3 store containing built artifacts for every single samsung backend service. it would have however most likely been possible for me to backdoor the server and play the long game, waiting for the system to be fully set up, while retaining access even if it had been secured more properly in the meantime. with potential access to both repositories as well as the build process (it's [supply chain attack season after all](https://boehs.org/node/everything-i-know-about-the-xz-backdoor)) this would have likely allowed for backdoors in further Samsung Cloud infrastructure with widereaching consequences. as it stands though i just had a brief glance into the insides of a tech megacorp before reporting the issue so i could write about it here, learning that just like many of their peers samsungs backend primarily consists of [spring framework](https://en.wikipedia.org/wiki/Spring_Framework) apps hosted using [tomcat](https://en.wikipedia.org/wiki/Apache_Tomcat) and spread across an obscene number of different servers.
oh and before any of you get scared, no i am not becoming yet another shitty bug bounty influencer now, more in-depth investigative journalism is coming again very soon :p
## disclosure timeline
* **2024-02-09:** vulnerable jenkins server found, analysis started
* **2024-02-10:** disclosure email is sent directly to Samsung employees involved with the jenkins server
* **2024-02-14:** employee acknowledges the report, internally redirects it to Samsung Mobile Security
* **2024-02-14:** Samsung Mobile Security contacts me, urging me to re-report via their rewards program
* **2024-02-14:** more in-depth report sent to Samsung Mobile Security
* **2024-02-15:** Samsung security analysis begins
* **2024-02-20:** Samsung Mobile Security updates the report, confirming severity as *High*
* **2024-02-23:** {% footnoteref "samsung-early-access", "this did not influence the contents of this article and no changes were requested or made beyond removing mentions of the specific bounty reward amount" %}Samsung is provided with a draft of this article{% endfootnoteref %}
* **2024-03-04:** i am awarded a bounty by Samsung based on a not yet public server vulnerability bounty policy
* **2024-04-01:** this write-up is published and the issue publicly disclosed

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!
> "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,15 +60,15 @@ 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.
> "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.
> "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."
the write-up itself, hosted on files.kick.com using this vulnerability, is the proof of concept for this vuln. to showcase the loose cookie access control there is also a button which (when clicked on the files.kick.com version) displays all of your kick.com cookies, showcasing the potential for XSS and token stealing
@ -76,24 +76,24 @@ 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.
> "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.
> "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.
> Or you know, [self host your streams..](https://owncast.online/)
> Or you know, [self host your streams..](https://owncast.online/)"
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

@ -9,8 +9,6 @@ tags:
- politics
- hack
- far right
- osint
- social media
---
earlier this year, [the popular far right fediverse instance poast was hacked](https://www.dailydot.com/debug/leak-poast-kiwi-farms/) leaking user profiles with emails, posts and DMs. today i was sent a special little treat, [a singular html file](/files/posts/meet-the-shitpoasters/meet-the-shitpoasters.html) containing all the poa.st and bae.st profiles with linkedin profiles associated to their e-mail addresses, all their linkedin info, their top 5 worst posts as ranked by sentiment analysis and their DMs. i will leave proper in depth analysis of this data to extremism researchers and journalists, but a few interesting people i can find at a glance are:
@ -25,7 +23,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

@ -14,7 +14,7 @@ feature_alt: "a screenshot of a 4chan leak release post"
yesterday evening an anonymous 4chan user dumped a leak on the /g/ technology board, claiming to have completely owned risk visualization company [optimeyes](https://optimeyes.ai):
<blockquote class="greentext">
<blockquote>
<span class="greentext">> be cyber security risk assessment company</span></br>
<span class="greentext">> focus on intellectual property theft</span></br>
<span class="greentext">> dont secure ur own systems at all</span></br>

View File

@ -1,57 +0,0 @@
---
title: "EXCLUSIVE: second biggest russian insurance company hacked"
date: 2023-10-27
description: "unique insights into one of the biggest russian financial institutions"
feature_image: /img/posts/rosgosstrakh-hack/cover.jpg
feature_alt: "a glitchy edited photo of the rosgosstrakh headquarter with their logo in front of it"
tags:
- leak
- analysis
- osint
- politics
- russia
---
after taking a two month long hiatus (for mental health reasons, nothing to get into deeper here), i decided catch up again with some sources a few weeks ago. one of them started bringing up some massive hacks they had been doing in russia, making it clear they had financial motivations and planned on selling the data rather than leaking it publicly. this of course immediately piqued my interest and i tried to find a way to make a story happen anyways and after a bit of discussion we ended up striking a deal, i get exclusive access to the data for this piece but won't share it any further and they still get to sell it.
## the target
[rosgosstrakh (RGSL/росгосстрах)](https://en.wikipedia.org/wiki/Rosgosstrakh) is the second biggest russian insurance company, behind [SOGAZ](https://en.wikipedia.org/wiki/Sogaz) with an annual revenue of around 90 billion rubles ([2022](https://www.reuters.com/markets/companies/rgss.mm/financials/income-annual)). RGSL has been [subject to US sanctions](https://www.hstoday.us/subject-matter-areas/intelligence/new-sanctions-top-ten-russian-financial-institutions-now-under-u-s-restrictions/) since the start of the russian invasion of ukraine in february 2022. my source gained full access to their investment and life insurance department with data going back to 2010, giving them full access to ~3 million bank statements, data on 730k people/holders (around 80k of which with SNILS (russian ssn) and another 45k with full bank routing info), and all life insurance policies/contracts. they are also able to access all attachments to the former data, such as passports and scanned documents (i was only provided with a small selection of this data, but all of it is included in the purchasable dataset). the source further claims that they most likely have the ability to authorize and create bank transfers if they wanted to do so.
{% figure { src: '/img/posts/rosgosstrakh-hack/adinsure.jpg', alt: 'two screenshots of the adinsure software used by RGS', caption: 'two screenshots of the [adinsure](https://www.adacta-fintech.com/platform) software used by RGS, captured by the hackers during the attack' } %}
## analysis
![a screenshot of a json file containing some of the data on Anatoly Alexandrovich Safronov](/img/posts/rosgosstrakh-hack/json.jpg)
with access to an overwhelming 22gbs of plain json data i did what i always do when i get big datasets like this and first try to find interesting organizations or persons. in this case this was especially easy - public officials (or their direct relatives/spouses) are marked with `"isPublicOfficial": true`, making them super quick to find. i did this (and all my other searches) the lazy way, just searching over the directory with [ripgrep](https://github.com/BurntSushi/ripgrep) rather than indexing the data to a database, but it worked, finding a number of customers marked as public officials (it is highly likely there are way more officials in the dataset left unmarked due to how RGS's system is designed). it was now just a matter of using [OSINT](https://en.wikipedia.org/wiki/Open-source_intelligence) to link the provided data to existing people. the table below includes everyone out of those i was conclusively able to identify, with the data from this dataset and any publicly findable info to complete the picture.
| id | name | name (transliterated) | birth date | function | sanctioned | phone number | email | passport number | [INN](https://www.nalog.gov.ru/eng/exchinf/inn/) | documents | links | insurance coverage |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 724630 | Соболев Александр Михайлович | Sobolev Alexander Mikhaylovich | 1976-02-08 | Head of the Investigative Directorate of the [Investigative Committee of the Russian<br> Federation (SKR)](https://en.wikipedia.org/wiki/Investigative_Committee_of_Russia) for the Yaroslavl Oblast (Major General of Justice) | [yes](https://sanctions.nazk.gov.ua/en/sanction-person/6854/) | +7 (996) 136 19 76 | | 7820460001 | | [passport scan](/files/posts/rosgosstrakh-hack/documents/724630/Паспорт_Паспорт.pdf) | | critical illness insurance with coverage of 12mil rub,<br> disability insurance of 650k rub, secondary critical illness insurance of 650k rub |
| 300276 | Сафронов Анатолий Александрович | Safronov Anatoly Alexandrovich | 1959-12-09 | military helicopter pilot, hero of the russian federation, participated in the chechen war,<br> Deputy Plenipotentiary Representative of the President of the Russian Federation in the<br> Southern Federal District, russian state advisor | no | +7 (905) 768 58 57 | safronov13aa@mail.ru | 4507186232 | | [passport scan](/files/posts/rosgosstrakh-hack/documents/300276/Rostov_2023_03_02_19_13_13_147.pdf) | [wikipedia](https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D1%84%D1%80%D0%BE%D0%BD%D0%BE%D0%B2,_%D0%90%D0%BD%D0%B0%D1%82%D0%BE%D0%BB%D0%B8%D0%B9_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%BE%D0%B2%D0%B8%D1%87) [ufo.gov.ru official resources](http://ufo.gov.ru/polpred/zams/zam4/) | life insurance with coverage of around 7.5mil rub since march 2023 |
| 696346 | Торкунова Ирина Геннадиевна | Torkunova Irina Gennadievna | 1951-06-26 | wife of [Anatoly Torkunov](https://en.wikipedia.org/wiki/Anatoly_Torkunov) (rector of the [MGIMO](https://en.wikipedia.org/wiki/Moscow_State_Institute_of_International_Relations) and diplomat) | [Anatoly is sanctioned](https://sanctions.nazk.gov.ua/en/sanction-person/2807/) | +7 (903) 724 43 62 | | 4504301145 | 770405781300 | [passport scan](/files/posts/rosgosstrakh-hack/documents/696346/%D0%9F%D0%B0%D1%81%D0%BF%D0%BE%D1%80%D1%82_%D0%94%D0%A3%D0%9B_%D0%A2%D0%BE%D1%80%D0%BA%D1%83%D0%BD%D0%BE%D0%B2%D0%B0%20%D0%98.%D0%93._07.12.2021.pdf) | [property ownership](https://rublevka.proekt.media/person/torkunova-irina-gennadyevna/), [company registrations](https://www.rusprofile.ru/person/torkunova-ig-770405781300) | a life insurance worth over 15mil rub (18mil rub coverage), Anatoly is the beneficiary
| 371652 | Амочкин Константин Сергеевич | Amochkin Konstantin Sergeyevich | 1995-02-21 | 'Criminalistics Department Senior Lieutenant of Justice' in the Nizhny<br> Novgorod Oblast, [voted best criminal investigator in the region](https://nn-news.net/incident/2023/04/01/558253.html), [SKR agent](https://en.wikipedia.org/wiki/Investigative_Committee_of_Russia) | no | +7 (910) 796 97 11 | | 2214354822 | | - | [futsal player profile](https://futsal-nn.ru/player/2208779), [article about his visit<br> to schools (has an image of him)](https://studyvolga.com/news/2506/) | life insurance coverage over ~430k rub since 2019,<br> his mom (Амочкина Равия Сулеймановна / Amochkina Ravia Suleymanovna) is the beneficiary |
| 365615 | Меркулова Ольга Ивановна | Merkulova Olga Ivanovna | 1979-10-01 | [head of department at Voronezh State Technical University](https://cchgeu.ru/university/employees/4543/), wife of Меркулов<br> Дмитрий Викторовиц (Merkulov Dmitry Viktorovich), [who is a judge at the Southern<br> District Military Court in Rostov](https://base.garant.ru/320745360/), he is the beneficiary of her life insurance | no | +7 (928) 014 78 98 | las_to44ka@mail.ru | 6021058816 | 782094008038 | passport scan: [1](/files/posts/rosgosstrakh-hack/documents/365615/%D0%B7%D0%B0%D0%B2%D0%B5%D1%80%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9%20%D0%BF%D0%B0%D1%81%D0%BF%D0%BE%D1%80%D1%82_%D0%BF%D0%B0%D1%81%D0%BF%D0%BE%D1%80%D1%82%20%D1%81%D1%82%D1%80%D0%B0%D1%85%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F.pdf), [2](/files/posts/rosgosstrakh-hack/documents/365615/паспорт_страхователь.pdf);<br> beneficiary passport scan: [1](/files/posts/rosgosstrakh-hack/documents/365615/паспорт_выгодо-ль.pdf), [2](/files/posts/rosgosstrakh-hack/documents/365615/паспорт_паспорт.pdf) | | life insurance coverage of ~600k rub |
| 184779 | Топчилова Наталья Николаевна | Topchilova Natalya Nikolaevna | 1989-01-11 | [judge at the Central District Court of Novosibirsk](https://sudact.ru/regular/judge/6ydllhgw9IbV/) | no | +7 (951) 375 35 30 | vkv89@mail.ru | 5009708760 | | passport scan: [1](/files/posts/rosgosstrakh-hack/documents/184779/jpeg_OZ_2022_10_25_17_24_18_527-1.jpg), [2](/files/posts/rosgosstrakh-hack/documents/184779/jpeg_OZ_2022_10_25_17_24_18_527-2.jpg), [3](/files/posts/rosgosstrakh-hack/documents/184779/jpeg_OZ_2022_10_25_17_24_18_527-3.jpg) | | no insurance contract findable |
| 372532 | Куликов Борис Владимирович | Kulikov Boris Vladimirovich | 1976-02-28 | [judge at kamchatka oblast court](https://судьироссии.рф/sudii/view/id/24964/from/1) | no | +7 (914) 626 97 97 | gall-76@mail.ru | 3001084189 | | - | | life insurance with 1mil rub critical illness coverage |
i think it's quite interesting how even with so few people found we actually got some pretty big fish. i am publishing all their info publicly here in hopes of this being even more useful for other investigative journalists and researchers looking into russian government officials. this was quite a fun excersise in some more OSINT as well as my ability to decipher cyrillic :3.
let's get to some even meatier people. using the [molfar list of GRU operatives](https://molfar.com/en/gru) i searched the dataset by passport numbers, and BAAM, here we have 3 GRU agents of them:
| id | name | name (transliterated) | birth date | function | sanctioned | phone number | email | passport number | documents | insurance coverage |
|---|---|---|---|---|---|---|---|---|---|---|
| 498871 | Федосеев Алексей Константинович | Fedoseyev Alexey Konstantinovich | 1986-02-24 | unknown (posted at Siemens LLC according to Molfar) | no | - | - | 4508335107 | - | life insurance with ~1mil rub coverage,<br> beneficiary is AO UniCredit Bank |
| 479186 | Аверин Валерий Владимирович | Averin Valery Vladimirovich | 1980-03-05 | unknown (posted at Orgmarket LLC according to Molfar) | no | +7 (916) 221 53 91 | walerius@inbox.ru | 4504934427 | - | had life insurance with ~1.2mil rub coverage until 2018,<br> beneficiary was AO UniCredit Bank |
| 283673 | Фомивко Александр Федорович | Fomivko Alexander Fyodorovich | 1987-07-14 | unknown | no | +7 (985) 361 79 71 | old.atlas@yandex.ru | 0706926325 | - | has life insurance with ~2.3mil rub coverage since february 2023 |
there were unfortunately no attached documents for all three of them.
i didn't get much useful info out of contact details in this rather surface-level analysis and didn't yet have the time for a deeper dive, but i might do a follow up to this piece with some more analysis particularly of that data. however i decided to finally give [QGIS](https://qgis.org) a quick go and try to map out where customers are located, but even with just the 85k addresses that contain coordinates (just to see if geocoding the rest would be worth it) it already pretty much turned into a population map of russia, [which is of course already an xkcd punchline](https://xkcd.com/1138/). im still gonna put it here though because there still is a few small interesting takeaways.
![a map of russia with various dots on it showing where RGSL customers are located. the dots mostly line up with highly populated areas in russia](/img/posts/rosgosstrakh-hack/map.jpg)
as expected the customers are mostly spread out across the highly populated areas in south-western russia, but what's interesting is the not insignificant number of customers in crimea and the small number of customers in occupied mainland ukraine. i will probably also take a bit more of a look at some of those for a future update.
as the [sale thread](https://breachforums.is/Thread-Rosgosstrakh-700K-Customers-400GB) states my source attempted to negotiate with RGSL, but did not come to any agreement with them, meaning the dataset is now up for sale with an asking price of 50k usd in xmr. i reached out to RGSL for comment as i published this and will update if i hear anything back. as always feel free to [contact me](/contact) if you have any other data to publish or cover, have any fun vulns, or for journalistic inquiries.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -1,5 +0,0 @@
User-agent: GPTBot
Disallow: /
User-agent: Google-Extended
Disallow: /

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>{% if entry.data.coauthor %} and <span class="author by" id="author">{{ entry.data.coauthor.name }}</span>{% endif %}</span>
<span>by <span class="author by" id="author">{{ site.name }}</span></span>
{% if entry.data.tags %}
<span class="middot"></span>
<span>in