diff --git a/src/lib/components/navbar.svelte b/src/lib/components/navbar.svelte index 5a72f40..579347f 100644 --- a/src/lib/components/navbar.svelte +++ b/src/lib/components/navbar.svelte @@ -36,6 +36,7 @@
+
diff --git a/src/lib/layouts/post.svelte b/src/lib/layouts/post.svelte index fd17b14..1fe5a77 100644 --- a/src/lib/layouts/post.svelte +++ b/src/lib/layouts/post.svelte @@ -18,6 +18,11 @@ export let categories; export let bigThumbnail; export let thumbnail; + + export let data; + + let isPost = data.url.includes("/posts/"); + $: isPost = data.url.includes("/posts/"); let dt = DateTime.fromISO(date); $: dt = DateTime.fromISO(date); @@ -50,14 +55,19 @@
- Posts / + {#if isPost} + Posts / + {:else} + Notes / + {/if}

{title}

-
- Written {dt.toRelativeCalendar()} ({dt.toLocaleString(DateTime.DATE_FULL)}) +
+ {#if date} + Written {dt.toRelativeCalendar()} ({dt.toLocaleString(DateTime.DATE_FULL)}) + {/if} {#if dtu} Updated {dtu.toRelativeCalendar()} ({dtu.toLocaleString(DateTime.DATE_FULL)}) {/if} -
@@ -65,7 +75,7 @@ repo="danbulant/design" issue-term="pathname" label="comment" - theme="github-{$darkmode ? "dark" : "light"}" + theme="github-dark" crossorigin="anonymous" async> @@ -166,7 +176,7 @@ @apply rounded-lg bg-dark-400/03 p-1 transition-colors duration-300; } :global(body .post-layout ul) { - @apply list-disc list-inside; + @apply list-disc mx-4; } :global(body .post-layout ul li) { @apply my-0.5; diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index 67c016c..b1c9821 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -29,7 +29,7 @@

I'm sorry for that. If this is a repeated problem, try contacting me (me@danbulant.eu)

-
+
diff --git a/src/routes/+page.js b/src/routes/+page.js index aefa6e2..fe8bee9 100644 --- a/src/routes/+page.js +++ b/src/routes/+page.js @@ -1,7 +1,5 @@ /** @type {import('./$types').PageLoad} */ export async function load({ fetch }) { - return { - posts: await fetch("/api/posts.json").then(t => t.json()) - }; + return await fetch("/api/posts.json").then(t => t.json()) } \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 668db7b..87c98fd 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -47,9 +47,12 @@
diff --git a/src/routes/api/posts.json/+server.js b/src/routes/api/posts.json/+server.js index 36b7850..27f588f 100644 --- a/src/routes/api/posts.json/+server.js +++ b/src/routes/api/posts.json/+server.js @@ -1,11 +1,8 @@ -/** - * @type {import("@sveltejs/kit").RequestHandler} - */ -export async function GET(req) { - const allPostFiles = import.meta.glob('../../posts/**/*.md'); +import { json } from "@sveltejs/kit"; - const allPosts = (await Promise.all( - Object.entries(allPostFiles).map(async ([path, resolver]) => { +function loadAll(files) { + return Promise.all( + Object.entries(files).map(async ([path, resolver]) => { const { metadata } = await resolver(); let postPath = path.slice(2, -3); if(postPath.endsWith('/+page')) postPath = postPath.slice(0, -6); @@ -14,17 +11,27 @@ export async function GET(req) { path: postPath, }; }) - )).filter(t => !t.draft); + ) +} + +/** + * @type {import("@sveltejs/kit").RequestHandler} + */ +export async function GET(req) { + const allPostFiles = import.meta.glob('../../posts/**/*.md'); + const allNotesFiles = import.meta.glob('../../notes/**/*.md'); + + const allPosts = (await loadAll(allPostFiles)).filter(t => !t.draft); + const allNotes = (await loadAll(allNotesFiles)); allPosts.sort((a, b) => { return new Date(b.date) - new Date(a.date) }); - return new Response(JSON.stringify(allPosts.filter(t => new Date(t.date) < Date.now())), { - headers: { - 'Content-Type': 'application/json' - } - }); + return json({ + posts: allPosts.filter(t => new Date(t.date) < Date.now()), + notes: allNotes + }) } export const prerender = true; diff --git a/src/routes/notes/+page.js b/src/routes/notes/+page.js new file mode 100644 index 0000000..396922f --- /dev/null +++ b/src/routes/notes/+page.js @@ -0,0 +1,11 @@ +import { error } from '@sveltejs/kit'; + +/** @type {import('./$types').PageLoad} */ +export async function load({ fetch }) { + const response = await fetch("/api/posts.json"); + if(!response.ok) { + throw error(response.statusText, response.status); + } + + return response.json(); +} \ No newline at end of file diff --git a/src/routes/notes/+page.svelte b/src/routes/notes/+page.svelte new file mode 100644 index 0000000..5745125 --- /dev/null +++ b/src/routes/notes/+page.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/routes/notes/crypto/+page.md b/src/routes/notes/crypto/+page.md new file mode 100644 index 0000000..e1c4ea6 --- /dev/null +++ b/src/routes/notes/crypto/+page.md @@ -0,0 +1,24 @@ +--- +title: Crypto challenges and analysis +tags: [security] +date: 2025-03-29 +--- + +I'm not much of a crypto guy so there won't be that many separate notes. + +## Transposition + +- letter counts will be similar to real language (how often a letter shows up in the text) +- you can use letter count table to solve these challenges + +## S box + +Substition box. Used in diagrams for more advanced ciphers, used for mixing up data (so that data in byte 1 moves to byte 7 and so on) + +## DES + +56bit key (chosen not to make it too secure). + +## 3DES + +Trides, encrypts, decrypts and encrypts again. If a single key is provided, try it for all 3 (becomes just slower DES). \ No newline at end of file diff --git a/src/routes/notes/file-analysis/+page.md b/src/routes/notes/file-analysis/+page.md new file mode 100644 index 0000000..47ed3b0 --- /dev/null +++ b/src/routes/notes/file-analysis/+page.md @@ -0,0 +1,18 @@ +--- +title: File analysis tools + enumeration +tags: [security] +date: 2025-03-29 +--- + +- `file` shows filetype. +- `binwalk` finds file headers inside of file. Can be used to extract data from corrupted disk images. +- `7z` can extract almost anything. +- `foremost` data recovery tool. +- `volatility` for RAM analysis (mainly windows). + +- `ffuf` (web) fuzzer +- `hydra` credential stuffer +- `sqlmap` for automatic SQL injection exploiting +- `linPEAS`, `linEnum`, `lse`, `find` for finding executables. + - `find -perm 4000` to filter by perm (4000 suid, 2000 guid, sum for both) + - `find -user root` to filter by user \ No newline at end of file diff --git a/src/routes/notes/mimikatz-on-linux/+page.md b/src/routes/notes/mimikatz-on-linux/+page.md new file mode 100644 index 0000000..640c440 --- /dev/null +++ b/src/routes/notes/mimikatz-on-linux/+page.md @@ -0,0 +1,15 @@ +--- +title: Mimikatz on linux +tags: [security] +date: 2025-03-29 +--- + +*pypykatz* is a Python library to parse credentials from Windows Security. Pypykatz is portable, unlike mimikatz which requires windows to run. + +SUID is the users secure id. Usually the name of their folder in AppData (S-1-5-21-...). Certain password hashes (I think SHA1) can be used instead of plaintext, see pypykatz/mimikatz docs. + +```bash +pypykatz dpapi prekey password -o prekeys +pypykatz dpapi masterkey -o masterkeys +pypykatz dpapi chrome --logindata --cookies +``` diff --git a/src/routes/notes/mysql2/+page.md b/src/routes/notes/mysql2/+page.md new file mode 100644 index 0000000..5324a2b --- /dev/null +++ b/src/routes/notes/mysql2/+page.md @@ -0,0 +1,37 @@ +--- +title: MySQL, express, and the importance of types +tags: [security, javascript] +date: 2025-03-29 +--- + +TLDR object serialization via [sqlstring](https://www.npmjs.com/package/sqlstring), vulnerable if user input is not primitive (e.g. unchecked object). + +```js +const app = express() +const db = await mysql.createConnection({ ... }) + +app.get("/", (req, res) => { + // unsafety here :) + let users = await db.query("SELECT * FROM table WHERE name = ?", [req.query.name]) + res.json(users) +}) +``` + +*There's no way to prevent this, says only language where this regularly happens* + +SQL Injection is bad! Use a library to prevent SQL Injection! + +Nowhere in [MySQL2 docs](https://sidorares.github.io/node-mysql2/docs) does it mention that objects are serialized into SQL (Note that this may have changed - this is more of a guide for testing vulns / ctf challenges than a bug report, this is not new research). Via dependencies, you can find it uses [sqlstring](https://www.npmjs.com/package/sqlstring). That does mention that it does object serialization: + +```js +var post = {id: 1, title: 'Hello MySQL'}; +var sql = SqlString.format('INSERT INTO posts SET ?', post); +console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL' +``` + +But wait! Query is surely just string? +No + +Express parses query string like `name[obj]=val`. And MySQL accepts `1 = 1 = 1`. Also, people often allow both urlencoded and json as input, even if their pages use urlencoded forms, so try submitting a JSON body with a similar payload. + +This is based on [previous research](https://flatt.tech/research/posts/finding-an-unseen-sql-injection-by-bypassing-escape-functions-in-mysqljs-mysql/) and solving a CTF challenge. I get reminded of it every few months by reading another project which uses mysql2 and express. I do not support using express from a technical view - it is full of surpises, took really long to get promises support (so long that most libraries based on express still don't support it), and is actually the slowest of the commonly used frameworks. diff --git a/src/routes/notes/pkg-unpacker/+page.md b/src/routes/notes/pkg-unpacker/+page.md new file mode 100644 index 0000000..0b50cee --- /dev/null +++ b/src/routes/notes/pkg-unpacker/+page.md @@ -0,0 +1,11 @@ +--- +title: Unpacking packed nodejs +tags: [cybersec] +date: 2025-03-29 +--- + +Use [pkg unpacker](https://github.com/LockBlock-dev/pkg-unpacker). Some applications are compiled with (now deprecated) [vercel/pkg](https://github.com/vercel/pkg). Those work by embedding packed code into nodejs statically compiled executable. This tool unpacks those files into separate files for readability. + +Note that pkg has support for v8 bytecode only mode (afaik it's used by default for dependencies, but apps in the wild have it disabled for their source code too), and that is very difficult to reliable reverse engineer - the bytecode is not stable between releases, and there isn't a ton of tools for analysing different versions, and they often rely on compiling parts of chromium/v8. + +As for node SEA, the recommended alternative for pkg, use `strings -t x` (`-t x` for hexadecimal offsets, `-t d` for decimal) and find the text in your favorite hex editor. It is not the default there to have v8 bytecode only. \ No newline at end of file diff --git a/src/routes/notes/write-your-knowledge/+page.md b/src/routes/notes/write-your-knowledge/+page.md new file mode 100644 index 0000000..25b1c60 --- /dev/null +++ b/src/routes/notes/write-your-knowledge/+page.md @@ -0,0 +1,11 @@ +--- +title: "Micronotes: Write your knowledge" +tags: [general] +date: 2025-03-29 +--- + +You won't remember everything. Use micro notes if lazy. Publish them should you wish to share (you should!), don't if you do not. But write your knowledge. + +This is my collection of notes, mainly for tech purposes, like solving programming issues, CTF write-ups and more. Majority of them won't bring anything new to the world, though they were once new to me, and I don't wish to have to research them all again, I want to research new ideas instead. + +Perhaps I'll rewrite some of those notes into full fledged posts. For now, these remain just short, dense notes. This is a call to make your own hacktricks. \ No newline at end of file diff --git a/src/routes/posts/+page.js b/src/routes/posts/+page.js index 8a1e26f..396922f 100644 --- a/src/routes/posts/+page.js +++ b/src/routes/posts/+page.js @@ -1,9 +1,11 @@ +import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageLoad} */ export async function load({ fetch }) { const response = await fetch("/api/posts.json"); + if(!response.ok) { + throw error(response.statusText, response.status); + } - return { - posts: response.ok && (await response.json()) - }; + return response.json(); } \ No newline at end of file diff --git a/src/routes/posts/+page.svelte b/src/routes/posts/+page.svelte index 0db4274..80108e7 100644 --- a/src/routes/posts/+page.svelte +++ b/src/routes/posts/+page.svelte @@ -1,108 +1,11 @@ - - Blog - Daniel Bulant - - - - - - - - - - - - -
-

Posts

- -
-

- Posts - - - RSS icon - RSS - - -

- - {#if !selectedTags.length || selectedTags.find(tag => posts[0].categories.includes(tag))} - - -
- {/if} - - - {#each filteredPosts as post (post.title)} -
- -
- {/each} -
-
- - \ No newline at end of file + diff --git a/src/routes/posts/posts.svelte b/src/routes/posts/posts.svelte new file mode 100644 index 0000000..2bd569f --- /dev/null +++ b/src/routes/posts/posts.svelte @@ -0,0 +1,146 @@ + + + + {postsActive ? 'Blog' : 'Notes'} - Daniel Bulant + + + + + + + + + + + + +
+
+
postsActive = true}>Posts
+
postsActive = false}>Notes
+
+ +
+

+ Posts + + + RSS icon + RSS + + +

+ + {#if !selectedTags.length || selectedTags.find(tag => posts[0].categories.includes(tag))} + + +
+ {/if} + + + {#each filteredPosts as post (post.title)} +
+ +
+ {/each} +
+ +
+

Notes

+

Collection of short notes, write-ups and not-yet-posts.

+ + +
+
+ + \ No newline at end of file