Skip to content

Commit

Permalink
add text for textarea injection, refactor transform mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitris committed May 1, 2015
1 parent 202deaa commit d445d60
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 172 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
bin
63 changes: 11 additions & 52 deletions custom.go
Expand Up @@ -32,7 +32,7 @@ func CustomMap() (mp map[string]func(http.ResponseWriter, *http.Request) *LabRes
mp["/xss/reflect/rs1"] = XssRs
mp["/xss/reflect/post1"] = XssPost
mp["/xss/reflect/backslash1"] = XssBackslash
mp["/xss/reflect/raw1_fp"] = NoQuotesNoScript

return mp
}

Expand Down Expand Up @@ -62,6 +62,12 @@ func FilterMap() (mp map[string][]filter) {
mp["/xss/reflect/oneclick1"] = []filter{QuotesOff, TagsOff}
mp["/misc/escapeexample_nogt"] = []filter{GreaterThanOff}
mp["/misc/escapeexample_nogt_noquotes"] = []filter{QuotesOff, GreaterThanOff}
mp["/xss/reflect/raw1_fp"] = []filter{QuotesOff, ScriptOff}

mp["/xss/reflect/textarea1"] = []filter{TagsOffUntilTextareaClose}
mp["/xss/reflect/textarea2"] = []filter{NoOp}
mp["/xss/reflect/textarea1_fp"] = []filter{TextareaCloseOff}
mp["/xss/reflect/textarea2_fp"] = []filter{TextareaSafe}
return
}

Expand Down Expand Up @@ -226,53 +232,6 @@ func XssInRedirectFp(w http.ResponseWriter, r *http.Request) *LabResp {
return &LabResp{Err: nil, Code: http.StatusOK}
}

// NoScript removes open and closing script tags
func NoScript(w http.ResponseWriter, r *http.Request) *LabResp {
var input InData
rawParams := make(map[string][]string)
ParseRawQuery(rawParams, r.URL.RawQuery)
inputRaw, ok := rawParams["in"]
if ok && len(inputRaw) > 0 {
input.InRaw = inputRaw[0]
unesc, err := url.QueryUnescape(input.InRaw)
if err != nil {
log.Printf("Error in NoScript / QueryUnescape: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
input.In = StripScript(unesc)
}
err := DoTemplate(w, r.URL.Path, &input)
if err != nil {
log.Printf("Error in DoTemplate: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
return &LabResp{Err: nil, Code: http.StatusOK}
}

// NoQuotesNoScript removes open and closing script tags as well as all quotes
func NoQuotesNoScript(w http.ResponseWriter, r *http.Request) *LabResp {
var input InData
rawParams := make(map[string][]string)
ParseRawQuery(rawParams, r.URL.RawQuery)
inputRaw, ok := rawParams["in"]
if ok && len(inputRaw) > 0 {
input.InRaw = inputRaw[0]
unesc, err := url.QueryUnescape(input.InRaw)
if err != nil {
log.Printf("Error in NoScript / QueryUnescape: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
unesc = NewTransformer(QuotesOff).Transform(unesc)
input.In = StripScript(unesc)
}
err := DoTemplate(w, r.URL.Path, &input)
if err != nil {
log.Printf("Error in DoTemplate: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
return &LabResp{Err: nil, Code: http.StatusOK}
}

// XssEnc escapes quotes with backslash but does not escape backslash itself
// allowing injection of an unescaped double quote
func XssEnc(w http.ResponseWriter, r *http.Request) *LabResp {
Expand All @@ -288,7 +247,7 @@ func XssEnc(w http.ResponseWriter, r *http.Request) *LabResp {
log.Printf("Error in XssEnc2 / QueryUnescape: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
input.In = NewTransformer(TagsOff, DoubleQuotesBackslashEscape).Transform(unesc)
input.In = Transform(unesc, TagsOff, DoubleQuotesBackslashEscape)
}
err := DoTemplate(w, r.URL.Path, input)
if err != nil {
Expand All @@ -311,7 +270,7 @@ func XssEncFp(w http.ResponseWriter, r *http.Request) *LabResp {
log.Printf("Error in XssEnc2 / QueryUnescape: %s\n", err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
input.In = NewTransformer(TagsOff, QuotesOff).Transform(unesc)
input.In = Transform(unesc, TagsOff, QuotesOff)
}
err := DoTemplate(w, r.URL.Path, input)
if err != nil {
Expand All @@ -336,7 +295,7 @@ func XssDoubq(w http.ResponseWriter, r *http.Request) *LabResp {
fmt.Printf("ERROR in the first url.QueryUnescape on %s\n", inputRaw[0])
return &LabResp{Err: nil, Code: http.StatusBadRequest}
}
unesc1 = NewTransformer(TagsOff, QuotesOff).Transform(unesc1)
unesc1 = Transform(unesc1, TagsOff, QuotesOff)
unesc, err := url.QueryUnescape(unesc1)
if err != nil {
fmt.Printf("ERROR in the second url.QueryUnescape on %s\n", unesc1)
Expand All @@ -360,7 +319,7 @@ func XssBackslash(w http.ResponseWriter, r *http.Request) *LabResp {
inputRaw, ok := rawParams["in"]
if ok && len(inputRaw) > 0 {
input.InRaw = inputRaw[0]
input.In = NewTransformer(TagsOff, QuotesOff).Transform(input.InRaw)
input.In = Transform(input.InRaw, TagsOff, QuotesOff)
input.In = UnescapeUnicode(input.In)
}
err := DoTemplate(w, r.URL.Path, input)
Expand Down
35 changes: 21 additions & 14 deletions filters.go
Expand Up @@ -8,22 +8,29 @@ type filter int16

// constants for the most common filters
const (
Invalid filter = iota
QuotesOff
QuotesCook
DoubleQuotesOff
DoubleQuotesCook
Invalid filter = iota
BackslashEscape // escape \ with a \
DoubleQuotesBackslashEscape
SingleQuotesOff
SingleQuotesCook
TagsOff
TagsCook
GreaterThanOff
DoubleQuotesCook
DoubleQuotesOff
GreaterThanCook
LessThanOff
GreaterThanOff
LessThanCook
SpacesOff
SpacesCook
LessThanOff
NoOp
ParensOff
BackslashEscape // escape \ with a \
QuotesCook
QuotesOff
SingleQuotesCook
SingleQuotesOff
SpacesCook
SpacesOff
ScriptOff
TagCharsOff
TagsCook
TagsOff
TagsOffExceptTextareaClose
TagsOffUntilTextareaClose
TextareaCloseOff
TextareaSafe
)
3 changes: 1 addition & 2 deletions process.go
Expand Up @@ -130,8 +130,7 @@ func HandleFilterBased(w http.ResponseWriter, r *http.Request, filters []filter)
log.Printf("Error in %s: %s\n", r.URL.Path, err)
return &LabResp{Err: nil, Code: http.StatusInternalServerError}
}
tr := NewTransformer(filters...)
input.In = tr.Transform(unesc)
input.In = Transform(unesc, filters...)
}
err := DoTemplate(w, r.URL.Path, &input)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions templates/index.html
Expand Up @@ -17,6 +17,14 @@ <h2>Available tests:</h2>
<A href="xss/reflect/basic?in=2change">xss/reflect/basic?in=2change</A> - similar to the above, no quotes needed in the injection. Echo of unfiltered input in a "normal" HTML context (not between tags, etc.). The example shows the minimal Webseclab template consisting of just &#x7b;&#x7b;.In&#x7d;&#x7d; &quot;moustache&quot; placeholder. PoE: /xss/reflect/basic?in=&lt;script&gt;alert(/HACKED/)&lt;/script&gt; or /xss/reflect/basic?in=&lt;img src=foo onerror=alert(12345)&gt;
<li>
<A href="xss/reflect/post1">xss/reflect/post1</A> - Javascript echoed from the POST parameters. (Splash page: <A href="xss/reflect/post1_splash">xss/reflect/post1_splash</A>)
<li>
<A href="xss/reflect/textarea1?in=foo1">xss/reflect/textarea1?in=foo1</A> - Javascript echoed in the textarea element (textarea closing tag required to trigger).
<li>
<A href="xss/reflect/textarea2?in=foo2">xss/reflect/textarea2?in=foo2</A> - Javascript echoed in the textarea element (textarea closing tag required to trigger, all tags prior to the closing textarea are filtered).
<li>
<A href="xss/reflect/textarea1_fp?in=fp1">xss/reflect/textarea1_fp?in=fp1</A> - False Positive issue on injecting into the textarea block.
<li>
<A href="xss/reflect/textarea2_fp?in=fp2">xss/reflect/textarea2_fp?in=fp2</A> - False Positive issue on injecting into the textarea block.
<li>
<A href="xss/reflect/doubq1?in=change_me2">xss/reflect/doubq1?in=changeme2</A> - Double-quoted injection echoed unescaped. PoE: /xss/reflect/doubq1?in=%253Cscript%253Ealert%28%252FXSS%252F%29%253C%252Fscript%253E

Expand Down
15 changes: 15 additions & 0 deletions templates/xss/reflect/textarea1
@@ -0,0 +1,15 @@
{{ define "title" }}Reflected XSS in textarea (textarea1){{end}}

{{template "header" }}

<H2>Textarea injection test</H2>
This test requires a closing textarea tag to break out of the field context and trigger a subsequent exploit.
<p>
<FORM>
<textarea name="in" rows="5" cols="60">{{.In}}</textarea>
<p>
<INPUT type="Submit">
</FORM>
<p>Random padding to invite scanners not to skip me:
<b>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt </b>
{{template "footer"}}
15 changes: 15 additions & 0 deletions templates/xss/reflect/textarea1_fp
@@ -0,0 +1,15 @@
{{ define "title" }}Reflected XSS in textarea (textarea_fp1){{end}}

{{template "header" }}

<H2>Textarea injection test (False Positive)</H2>
This test requires a closing textarea tag to break out of the field context and trigger a subsequent exploit.
<p>
<FORM>
<textarea name="in" rows="5" cols="60">{{.In}}</textarea>
<p>
<INPUT type="Submit">
</FORM>
<p>Random padding to invite scanners not to skip me: <BR>
<i>ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </i>
{{template "footer"}}
14 changes: 14 additions & 0 deletions templates/xss/reflect/textarea2
@@ -0,0 +1,14 @@
{{ define "title" }}Reflected XSS in textarea (textarea1){{end}}

{{template "header" }}

<H2>Textarea injection test</H2>
This test requires a closing textarea tag to break out of the field context and trigger a subsequent exploit.
<p>
<FORM>
<textarea name="in" rows="5" cols="60">{{.In}}</textarea>
<p>
<INPUT type="Submit">
</FORM>
<br>Random padding to invite scanners not to skip me:
{{template "footer"}}
16 changes: 16 additions & 0 deletions templates/xss/reflect/textarea2_fp
@@ -0,0 +1,16 @@
{{ define "title" }}Reflected XSS in textarea (textareafp2){{end}}

{{template "header" }}

<H2>Textarea injection test (False Posisitve)</H2>
This test requires a closing textarea tag to break out of the field context and trigger a subsequent exploit.
<p>
<FORM>
<textarea name="in" rows="5" cols="60">{{.In}}</textarea>
<p>
<INPUT type="Submit">
</FORM>

Random padding: <BR>
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
{{template "footer"}}

0 comments on commit d445d60

Please sign in to comment.