DOMLogger++

Kévin (Mizu)

Pentester at Bsecure

CTF Player @Rhackgondins

Bug Hunter

https://mizu.re

@kevin_mizu

What is a sink? 🚰

A sink is a potentially dangerous JavaScript function or DOM object that can cause undesirable effects if attacker-controlled data is passed to it.

 

Source: portswigger.net

Element.innerHTML

eval()

Function()

Iframe.srcdoc

Element.outerHTML

document.location.href

jQuery.globalEval

What is DOMLogger++?

A browser extension that allows you to monitor, intercept, and debug JavaScript sinks based on customizable configurations.

List of sinks
(config)

🌐

Target websites

🚰

Sink is used

🗃️

Information logged

Why creating it?

When DOM Invaders exists...

  • Free solution and opensource
  • Available on Chromium and Firefox
  • Ability to customize everything
  • Logs kept when navigating to another page

DOM Invaders is an incredible extension; I just wanted something that fit my needs

How does it looks like?

How does it looks like?

New devtools

menu

How does it looks like?

New devtools

menu

Sink information

How does it looks like?

New devtools

menu

Customizable

filter

Sink information

How does it looks like?

New devtools

menu

Customizable

filter

Search bar

Sink information

How does it looks like?

New devtools

menu

Customizable

filter

Reload the page with a debugger

Search bar

Sink information

Usage examples

(New features from version 1.0.4)

Example 1

Reflected pathname in single quotes

Example 1

/0123456789abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ!$%&'()*+,-.:;=@[]_|~

Not URL encoded pathname chars

Reflected pathname in single quotes

Example 1

Reflected pathname in single quotes

Example 1

Reflected pathname in single quotes

{
  "hooks": {
    "REFLECTED": {
      "attribute": [
        "document.documentElement.innerHTML"
      ]
    }
  },
  "config": {
    "REFLECTED": {
      "match": [
        "exec:return `'${document.location.pathname}'`"
      ]
}}}

Example 2

<div id="elem"></div>
<div id="elem2"></div>
<script src="/purify.min.js"></script>
<script>
    elem.innerHTML = DOMPurify.sanitize(
        (new URLSearchParams(location.search)).get("user-input")
    );
    // ...
    elem2.innerHTML = document.getElementById("elem-X").dataset.get("attr-X");
</script>

Imagine that everything occurs in a minified JS file in two different places

Sanitized input with query selector

Example 2

{
  "hooks": {
    "REQUIRED": {
      "attribute": [ "set:Element.prototype.innerHTML" ]
    },
    "TARGET": {
      "function": [ "document.getElementById" ]
  },
  "config": {
    "REQUIRED": { "match": [ "canary-name" ] },
    "TARGET": { "requiredHooks": [ "REQUIRED" ] }
}}

Sanitized input with query selector

Bonus 🎁

Rhackgondins team ❤

The end

https://github.com/kevin-mizu/domloggerpp

DOMLogger++ | BreizhCTF2024

By Kévin (Mizu)

DOMLogger++ | BreizhCTF2024

  • 115