hahwul / dalfox

🌙🦊 Dalfox is a powerful open-source XSS scanner and utility focused on automation.
https://dalfox.hahwul.com
MIT License
3.58k stars 400 forks source link

[@Headless] No result/PoC on known target (OWASP Juice Shop) #240

Closed ChocolateOverflow closed 3 years ago

ChocolateOverflow commented 3 years ago

Question

When I tried dalfox on real site, I only ever got up to [I] Reflected PATH messages but never got a [PoC] result or an output file, so I'm testing it on OWASP Juice Shop. The test is as follows:

$ cat tmp
http://localhost:3000/#/search?q=FUZZ

$ dalfox file tmp -o dalfox.txt

    _..._
  .' .::::.   __   _   _    ___ _ __ __
 :  :::::::: |  \ / \ | |  | __/ \\ V /
 :  :::::::: | o ) o || |_ | _( o )) (
 '. '::::::' |__/|_n_||___||_| \_//_n_\
   '-.::''

Parameter Analysis and XSS Scanning tool based on golang
Finder Of XSS and Dal is the Korean pronunciation of moon. @hahwul

 🎯  Target                 tmp
 🏁  Method                 GET
 🖥   Worker                 100
 🔦  BAV                    true
 ⛏   Mining                 true (Gf-Patterns)
 🔬  Mining-DOM             true (mining from DOM)
 ⏱   Timeout                10
 📤  FollowRedirect         false
 🕰   Started at             2021-06-09 21:13:18.114339628 +0700 +07 m=+0.007974295

 >>>>>>>>>>>>>>>>>>>>>>>>>
[*] 🦊 Start scan [SID:0][0/1][0.00%%] / URL: http://localhost:3000/#/search?q=FUZZ
[I] Found 0 testing point in DOM Mining
[I] Content-Type is text/html; charset=UTF-8ter and static analysis 🔍
[I] X-Frame-Options is SAMEORIGIN
[I] Access-Control-Allow-Origin is *
[*] Finish Scan

$ ls
tmp

I've confirmed that the q parameter in the URL is vulnerable to XSS but dalfox is getting nothing. Am I doing something wrong?

Environment

github-actions[bot] commented 3 years ago

Thank you for your first issue report :D

hahwul commented 3 years ago

Hi @ChocolateOverflow First of all, thank you for the issue report!

I don't think there's a problem with your testing itself. I think I need to test this with a juice shop and check what it response. Dalfox tests based on reflection parameters. and I think can know the exact cause by looking at the action of juice shop 😁

ChocolateOverflow commented 3 years ago

The payload <img src=# onerror=javascript:alert(1)> definitely gets reflected and pops an alert.

hahwul commented 3 years ago

Hello again @ChocolateOverflow I checked now, juishop is SPA(Single Page Application) service, which is slightly different from normal web pages. The XSS you mentioned is a typical DOM XSS issue that is difficult to detect in Dalfox, which does not use a headless browser 😭

$ http http://localhost:8088/\#/search\?q\=asd%22%3E%3CifraMe%2Fsrc%3D%22jaAvScriPT:alert\(45\)%22%3E

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>OWASP Juice Shop</title>
  <meta name="description" content="Probably the most modern and sophisticated insecure web application">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link id="favicon" rel="icon" type="image/x-icon" href="assets/public/favicon_js.ico">
  <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css" />
  <script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
  <script>
    window.addEventListener("load", function(){
      window.cookieconsent.initialise({
        "palette": {
          "popup": { "background": "#546e7a", "text": "#ffffff" },
          "button": { "background": "#558b2f", "text": "#ffffff" }
        },
        "theme": "classic",
        "position": "bottom-right",
        "content": { "message": "This website uses fruit cookies to ensure you get the juiciest tracking experience.", "dismiss": "Me want it!", "link": "But me wait!", "href": "https://www.youtube.com/watch?v=9PnbKL3wuH4" }
      })});
  </script>
<link rel="stylesheet" href="styles.css"></head>
<body class="mat-app-background bluegrey-lightgreen-theme">
  <app-root></app-root>
<script src="runtime-es2015.js" type="module"></script><script src="runtime-es5.js" nomodule defer></script><script src="polyfills-es5.js" nomodule defer></script><script src="polyfills-es2015.js" type="module"></script><script src="vendor-es2015.js" type="module"></script><script src="vendor-es5.js" nomodule defer></script><script src="main-es2015.js" type="module"></script><script src="main-es5.js" nomodule defer></script></body>
</html>

To address these challenges, I considered using headless browsers, but did not apply because they use incredibly inefficient resources.

hahwul commented 3 years ago

@ChocolateOverflow First, I'll think about ways to solve it technically. it is certainly very weak for DOM-like XSS because there is a not using a headless browser.

If there's anything you don't understand, please reply 🤩

hahwul commented 3 years ago

Use headless browser only for DOM XSS

Test code

package main

import (
    "context"
    "log"
    "fmt"
    "time"

    "github.com/chromedp/chromedp"
    "github.com/chromedp/cdproto/page"
)

func main() {
    // create chrome instance
    ctx, cancel := chromedp.NewContext(
        context.Background(),
        chromedp.WithLogf(log.Printf),
    )
    defer cancel()

    // create a timeout
    ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
    defer cancel()

    // navigate to a page, wait for an element, click
    var example string

    chromedp.ListenTarget(ctx, func(ev interface{}) {
        if ev, ok := ev.(*page.EventJavascriptDialogOpening); ok {
            fmt.Println("closing alert:", ev.Message)
            go func() {
                if err := chromedp.Run(ctx,
                    page.HandleJavaScriptDialog(true),
                ); err != nil {
                    log.Fatal(err)
                }
            }()
        }
    })

    err := chromedp.Run(ctx,
        chromedp.Navigate(`https://xss-game.appspot.com/level1/frame?query=a%3CSvg%2Fonload%3Dalert%281%29+class%3Ddalfox%3E
`),
        // wait for footer element is visible (ie, page is loaded)
        chromedp.WaitVisible(`body > footer`),
    )
    if err != nil {
        log.Fatal(err)
    }

}
$ go build                 
$ ./gitasdfasdf           
closing alert: Congratulations, you executed an alert:

1
ChocolateOverflow commented 3 years ago

@hahwul Can you recommend a box dalfox would work on well? I've tried several applications so far and haven't got a single PoC.

hahwul commented 3 years ago

@ChocolateOverflow Please wait a little longer. I'll adding(working...) a function so that we can test hash-type queries(/page/#/search\?q\=asd), not ordinary queries.

hahwul commented 3 years ago

@ChocolateOverflow First, I applied it so that DOM-XSS can handle URL Fragment. I'll add same logic to other function the tonight. Perhaps further development is needed. Please refer to it!

$ ./dalfox url https://juice-shop.herokuapp.com/\#/search\?q\=aaa --headless
......
[*] 🦊 Start scan [SID:Single] / URL: https://juice-shop.herokuapp.com/#/search?q=aaa
[I] Found 0 testing point in DOM base parameter mining
[I] Content-Type is text/html; charset=UTF-8is 🔍 
[I] X-Frame-Options is SAMEORIGIN
[I] Access-Control-Allow-Origin is *
[V] Triggered XSS Payload (found dialog in headless)aram and waiting dom xss 
[POC][V][GET] https://juice-shop.herokuapp.com/#/search?q=%3Csvg/OnLoad=%22%60$%7Bprompt%601%60%7D%60%22%3E
hahwul commented 3 years ago

@ChocolateOverflow And I'll share a little bit of the road map I think. If there is no problem with the performance as much as possible, I would like to use headless for DOM XSS and inJS(in javascript area xss) XSS cases. Of course, most logic is based on the current DOM Parser, so there will be no rapid slowdown. I'll try my best and try to use it as a default value if possible. Thanks to you, I can see the clue of the most difficult problem from the beginning. Thank you.

hahwul commented 3 years ago

Speed test

Payloads

func getDOMXSSPayload() []string {
    payload := []string{
        "<svg/OnLoad=\"`${prompt`DALFOX_ALERT_VALUE`}`\">",
        "<img/src/onerror=.1|alert`DALFOX_ALERT_VALUE`>",
        "alert(DALFOX_ALERT_VALUE)",
        "prompt(DALFOX_ALERT_VALUE)",
        "confirm(DALFOX_ALERT_VALUE)",
    }
    return payload
}

Commands

$ cat 1.sh                                                                                                                                                               11:28:09 오후
pueue add "./dalfox url http://testphp.vulnweb.com/listproducts.php\?cat\=123 --headless"
pueue add "./dalfox url http://testphp.vulnweb.com/listproducts.php\?cat\=123\&a\=1 --headless"
pueue add "./dalfox url http://testphp.vulnweb.com/listproducts.php\?cat\=123\&a\=1\&b\=1 --headless"
pueue add "./dalfox url http://testphp.vulnweb.com/listproducts.php\?cat\=123\&a\=1\&b\=1\&c\=1 --headless"
pueue add "./dalfox url http://testphp.vulnweb.com/listproducts.php\?cat\=123\&a\=1\&b\=1\&c\=1\&d\=1 --headless"
pueue add "./dalfox url http://testphp.vulnweb.com/listproducts.php\?cat\=123\&a\=1\&b\=1\&c\=1\&d\=1\&e\=1 --headless"

$ ./1.sh

Output

1234 Add approximately one minute for one parameter

hahwul commented 3 years ago

DOM XSS Policy

InJS Policy

Conclusion

By default, use the headless browser (because of inJS) and adjust the number of payloads in DOM XSS. Instead, I'll add flags for deep check to dom xss.

Flags to be added

--skip-headless --deep-domxss

Flags to be removed

--headless (only dev version flag)

ChocolateOverflow commented 3 years ago

Should we add a --level flag similar to sqlmap? The lowest level would just run the basic reflection checks, whereas a higher level would add scans & checks for higher accuracy at some cost like the headless browser. Of course, fine-grained control of the scans would also be great.

hahwul commented 3 years ago

@ChocolateOverflow Well, I don't think need a level flags. I think the sqlmap's level and risk options is for safe the backend system more than the speed itself 🤔

it would be better to run the headless browser at Dalfox to a minimum. Anyway, dalfox's DOM Parser(common detection logic) is fast and accurate, with the exception of a few cases (DOM XSS, In javascript XSS). So reinforced those parts with the partial use of the headless browser.

Tested until the last commit, the speed is now much faster than the initial application of the headless browser, and it is not much different from the existing dalfox 🏁

Anyway, I going to use headless for this 2.4 version by default, but only for the parts that are really needed 😊

hahwul commented 3 years ago

Hyperfine

Case1 - 2param(1-reflect / 1-not-reflect)

diff: 1.26s bench1

Case2 - 20param(1-reflect / 19-not-reflect)

diff: 2.44s bench2

Found?

bbb

Conclusion

Even if we target about 20 parameters, there is only a difference of 2 seconds per scan. It's not much different from the previous one, so I think it's okay to include it as default.