Skip to content

Commit

Permalink
Merge branch 'dev' into github
Browse files Browse the repository at this point in the history
  • Loading branch information
ignis-sec committed Jul 5, 2020
2 parents f25c654 + d309c09 commit 7ca2779
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 31 deletions.
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Don't worry, just modify your wordlist to use `puff()` instead of `alert()` in



Running from source:
**Running from source:**
```
node puff.js -w xss.txt -u "http://your.url?message=FUZZ"
Expand All @@ -79,7 +79,7 @@ node puff.js -w xss.txt -u "http://your.url?message=FUZZ" -t 25
node puff.js -w xss.txt -u "http://your.url?message=FUZZ" -d
```

installed via npm:
**installed via npm:**
```
puff -w xss.txt -u "http://your.url?message=FUZZ"
Expand All @@ -88,6 +88,42 @@ puff -w xss.txt -u "http://your.url?message=FUZZ" -t 25
puff -w xss.txt -u "http://your.url?message=FUZZ" -d
```



**Running with stdin fuzzing mode:**
```
cat urls.txt | node puff.js -w .\wordlist-examples\events.txt
cat urls.txt | puff -w .\wordlist-examples\events.txt
```
Where urls.txt is
```
http://example.com?query=FUZZ
https://another.com/page/#FUZZ
```


**Running with stdin single payload mode:**
```
cat urls.txt | node puff.js -w .\wordlist-examples\events.txt
cat urls.txt | puff -w .\wordlist-examples\events.txt
```

Where urls.txt is
```
http://example.com?query=<script>alert()</script>
http://example.com?query=javascript:alert()
https://another.com/page/#<script>alert()</script>
```






---

<p align="center">
Expand Down
4 changes: 2 additions & 2 deletions callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ class TriggerHandler{
})

//xss windows tend to get load looped, but not sure if needed
//thread.evaluate(() => window.stop());
thread.evaluate(() => window.stop());
}

catchLoadFailure(thread){
this.outputHandler.write(`${bstart}[${thread.status}] [FAILURE] ${thread.pld} ${colstop}`, 5000)
this.outputHandler.write(`${bstart} [${thread.status}] [FAILURE] ${thread.pld} ${colstop}`, 5000)
this.outputHandler.bLastOutputImportant=true
}

Expand Down
75 changes: 75 additions & 0 deletions fuzzers/SinglePayloadFuzzer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

const {fail,succ,warn,info,gstart,bstart,ystart,rstart,colstop} = require('../pretty.js')
const fs = require('fs')
function replaceKeyword(url,pld){
pld = pld.replace(/ /g, '%20')
var t=url;
t = t.replace(/FUZZ/g,pld.replace(/\n|\r/g,''))
return t;

}


class SinglePayloadFuzzer{
/*
* Fuzzer for when both wordlist and url parameter is supplied.
* Read url from the parameter, and read
*
*/
constructor(url,cbhandler, threadHandler, terminator, wordlist, verbose, multi=false){
this.url = url
this.wlistFpointer=0;
this.cbHandler=cbhandler
this.terminator = terminator
this.verbose = verbose
this.threadHandler = threadHandler;
this.wordlist = wordlist;
this.multi = multi;

}


async loadNextUrl(thread){
/*
* Load next url from from the wordlist
*/
thread.url = this.url
thread.pld = ''
await this.processURL(thread,thread.url)
thread.close()
}


async processURL(thread, url){
/*
* Process url, visit, try to trigger events etc.
*/
try{
thread.goto(thread.url)

//capture window response
const response = await thread.waitForNavigation();

//acquire possible redirect chain
var chain = (response.request().redirectChain())

//get http response
thread.status = response.status();

//if there was a redirect chain, output it. If not, its a normal response
if(chain.length){
thread.wasHTTPRedirect = true;
this.cbHandler.catchRedirect(thread, chain)
}else{
this.cbHandler.catchNormal(thread)
}
}catch(e){
//Not properly implemented yet, dom-errors, http timeouts
this.cbHandler.catchLoadFailure(thread)
}
}
}

module.exports = {
SinglePayloadFuzzer:SinglePayloadFuzzer
}
30 changes: 22 additions & 8 deletions SingleUrlFuzzer.js → fuzzers/SingleUrlFuzzer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

const {fail,succ,warn,info,gstart,bstart,ystart,rstart,colstop} = require('./pretty.js')
const {fail,succ,warn,info,gstart,bstart,ystart,rstart,colstop} = require('../pretty.js')
const fs = require('fs')
function replaceKeyword(url,pld){
pld = pld.replace(/ /g, '%20')
Expand All @@ -16,14 +16,15 @@ class SingleUrlFuzzer{
* Read url from the parameter, and read
*
*/
constructor(url,cbhandler, threadHandler, terminator, wordlist, verbose){
constructor(url,cbhandler, threadHandler, terminator, wordlist, verbose, multi=false){
this.url = url
this.wlistFpointer=0;
this.cbHandler=cbhandler
this.terminator = terminator
this.verbose = verbose
this.threadHandler = threadHandler;
this.wordlist = wordlist;
this.multi = multi;

//read wordlist
if(this.verbose) console.log(`${warn} Reading Wordlist`)
Expand All @@ -42,11 +43,13 @@ class SingleUrlFuzzer{
/*
* Acquire next url from wordlist
*/

var line = this.wlistContent[this.wlistFpointer];
this.wlistFpointer+=1
return this.wlistContent[this.wlistFpointer];
return line
}

async checkFinished(){
checkFinished(){
/*
* Check if wordlist finished
*/
Expand All @@ -59,25 +62,36 @@ class SingleUrlFuzzer{
outputHandler.deleteLastLine()
console.log("Thread finished")
}

this.threadHandler.workerCount-=1;
//Only terminate program if all the threads have finished, so it doesn't lose the progress on those pending requests.
if(this.terminator.terminatedCount==threadHandler.workerCount){
if(this.threadHandler.workerCount==0){
//TODO, timeout possible idle/stuck threads and terminate
if(this.verbose){
outputHandler.deleteLastLine()
outputHandler.write('Last url checked, waiting for all threads to finish')
}

this.terminator.terminate()
if(this.multi){
console.log('')
}else{
this.terminator.terminate()
}
}
return true;
}
return false;
}

async loadNextUrl(thread){
/*
* Load next url from from the wordlist
*/
this.checkFinished()
if(this.checkFinished()){
try{
await thread.close()
}catch(e){};
return;
}
var line = await this.acquire()
thread.url = await replaceKeyword(this.url, line)
thread.pld = line
Expand Down
137 changes: 137 additions & 0 deletions fuzzers/StdinFuzzer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

const {fail,succ,warn,info,gstart,bstart,ystart,rstart,colstop} = require('../pretty.js')

function replaceKeyword(url,pld){
pld = pld.replace(/ /g, '%20')
var t=url;
t = t.replace(/FUZZ/g,pld.replace(/\n|\r/g,''))
return t;

}


class SingleUrlFuzzer{
/*
* Fuzzer for when both wordlist and url parameter is supplied.
* Read url from the parameter, and read
*
*/
constructor(url,cbhandler, threadHandler, terminator, wordlist, verbose, multi=false){
this.url = url
this.wlistFpointer=0;
this.cbHandler=cbhandler
this.terminator = terminator
this.verbose = verbose
this.threadHandler = threadHandler;
this.wordlist = wordlist;
this.multi = multi;

//read wordlist
if(this.verbose) console.log(`${warn} Reading Wordlist`)
try{
this.wlistContent = fs.readFileSync(wordlist).toString().split("\n")
}catch(e){
console.log(`${fail} Wordlist file was not found`)
console.log(e)
process.exit(1)
}
if(this.verbose) console.log(`${succ} Wordlist loaded, ${this.wlistContent.length} lines.`)

}

async acquire(){
/*
* Acquire next url from stdin
*/

var line = this.wlistContent[this.wlistFpointer];
this.wlistFpointer+=1
return line
}

checkFinished(){
/*
* Check if wordlist finished
*/

//if this thread is done
if(this.wlistFpointer>=this.wlistContent.length){
this.terminator.terminatedCount+=1
this.wlistFpointer+=1
if(this.verbose){
outputHandler.deleteLastLine()
console.log("Thread finished")
}
this.threadHandler.workerCount-=1;
//Only terminate program if all the threads have finished, so it doesn't lose the progress on those pending requests.
if(this.threadHandler.workerCount==0){
//TODO, timeout possible idle/stuck threads and terminate
if(this.verbose){
outputHandler.deleteLastLine()
outputHandler.write('Last url checked, waiting for all threads to finish')
}

if(this.multi){
console.log('')
}else{
this.terminator.terminate()
}
}
return true;
}
return false;
}

async loadNextUrl(thread){
/*
* Load next url from from the wordlist
*/
if(this.checkFinished()){
try{
await thread.close()
}catch(e){};
return;
}
var line = await this.acquire()
thread.url = await replaceKeyword(this.url, line)
thread.pld = line
this.processURL(thread,thread.url)
}


async processURL(thread, url){
/*
* Process url, visit, try to trigger events etc.
*/
try{
thread.goto(thread.url)

//capture window response
const response = await thread.waitForNavigation();

//acquire possible redirect chain
var chain = (response.request().redirectChain())

//get http response
thread.status = response.status();

//if there was a redirect chain, output it. If not, its a normal response
if(chain.length){
thread.wasHTTPRedirect = true;
this.cbHandler.catchRedirect(thread, chain)
}else{
this.cbHandler.catchNormal(thread)
}
}catch(e){
//Not properly implemented yet, dom-errors, http timeouts
this.cbHandler.catchLoadFailure(thread)
}

//recurses
this.loadNextUrl(thread)
}
}

module.exports = {
SingleUrlFuzzer:SingleUrlFuzzer
}
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puff-fuzz",
"version": "0.1.0",
"version": "0.1.1",
"description": "Simple Clientside vulnerability/xss fuzzer",
"main": "puff.js",
"repository": "https://github.com/FlameOfIgnis/puff",
Expand Down
Loading

0 comments on commit 7ca2779

Please sign in to comment.