fix CVE-2023-39318 and CVE-2023-39319
This commit is contained in:
parent
6075b8d074
commit
2332a50120
267
0050-Backport-html-template-support-HTML-like-comments-in.patch
Normal file
267
0050-Backport-html-template-support-HTML-like-comments-in.patch
Normal file
@ -0,0 +1,267 @@
|
||||
From fc0e2bd566a8e8777acc824211f6027184840a49 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Fri, 4 Aug 2023 03:24:13 +0800
|
||||
Subject: [PATCH 1/2] [Backport] html/template: support HTML-like comments in
|
||||
script contexts
|
||||
|
||||
Reference: https://open.codehub.huawei.com/OpenSourceCenter/golang/go/merge_requests/89
|
||||
Conflict: NA
|
||||
|
||||
Per Appendix B.1.1 of the ECMAScript specification, support HTML-like
|
||||
comments in script contexts. Also per section 12.5, support hashbang
|
||||
comments. This brings our parsing in-line with how browsers treat these
|
||||
comment types.
|
||||
|
||||
Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
|
||||
reporting this issue.
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
Fixes #62196
|
||||
Fixes #62395
|
||||
Fixes CVE-2023-39318
|
||||
|
||||
Change-Id: Id512702c5de3ae46cf648e268cb10e1eb392a181
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976593
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014620
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/526098
|
||||
Run-TryBot: Cherry Mui <cherryyz@google.com>
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
src/html/template/context.go | 6 ++-
|
||||
src/html/template/escape.go | 5 +-
|
||||
src/html/template/escape_test.go | 10 ++++
|
||||
src/html/template/state_string.go | 26 +++++-----
|
||||
src/html/template/transition.go | 80 ++++++++++++++++++++-----------
|
||||
5 files changed, 84 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/src/html/template/context.go b/src/html/template/context.go
|
||||
index a67b5a7871..472b5a9772 100644
|
||||
--- a/src/html/template/context.go
|
||||
+++ b/src/html/template/context.go
|
||||
@@ -124,6 +124,10 @@ const (
|
||||
stateJSBlockCmt
|
||||
// stateJSLineCmt occurs inside a JavaScript // line comment.
|
||||
stateJSLineCmt
|
||||
+ // stateJSHTMLOpenCmt occurs inside a JavaScript <!-- HTML-like comment.
|
||||
+ stateJSHTMLOpenCmt
|
||||
+ // stateJSHTMLCloseCmt occurs inside a JavaScript --> HTML-like comment.
|
||||
+ stateJSHTMLCloseCmt
|
||||
// stateCSS occurs inside a <style> element or style attribute.
|
||||
stateCSS
|
||||
// stateCSSDqStr occurs inside a CSS double quoted string.
|
||||
@@ -151,7 +155,7 @@ const (
|
||||
// authors & maintainers, not for end-users or machines.
|
||||
func isComment(s state) bool {
|
||||
switch s {
|
||||
- case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
|
||||
+ case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt, stateCSSBlockCmt, stateCSSLineCmt:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
diff --git a/src/html/template/escape.go b/src/html/template/escape.go
|
||||
index bdccc65a57..3249c67008 100644
|
||||
--- a/src/html/template/escape.go
|
||||
+++ b/src/html/template/escape.go
|
||||
@@ -700,9 +700,12 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
|
||||
if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
|
||||
// Preserve the portion between written and the comment start.
|
||||
cs := i1 - 2
|
||||
- if c1.state == stateHTMLCmt {
|
||||
+ if c1.state == stateHTMLCmt || c1.state == stateJSHTMLOpenCmt {
|
||||
// "<!--" instead of "/*" or "//"
|
||||
cs -= 2
|
||||
+ } else if c1.state == stateJSHTMLCloseCmt {
|
||||
+ // "-->" instead of "/*" or "//"
|
||||
+ cs -= 1
|
||||
}
|
||||
b.Write(s[written:cs])
|
||||
written = i1
|
||||
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
|
||||
index 3e17aee8f2..e38888a13f 100644
|
||||
--- a/src/html/template/escape_test.go
|
||||
+++ b/src/html/template/escape_test.go
|
||||
@@ -503,6 +503,16 @@ func TestEscape(t *testing.T) {
|
||||
"<script>var a/*b*///c\nd</script>",
|
||||
"<script>var a \nd</script>",
|
||||
},
|
||||
+ {
|
||||
+ "JS HTML-like comments",
|
||||
+ "<script>before <!-- beep\nbetween\nbefore-->boop\n</script>",
|
||||
+ "<script>before \nbetween\nbefore\n</script>",
|
||||
+ },
|
||||
+ {
|
||||
+ "JS hashbang comment",
|
||||
+ "<script>#! beep\n</script>",
|
||||
+ "<script>\n</script>",
|
||||
+ },
|
||||
{
|
||||
"CSS comments",
|
||||
"<style>p// paragraph\n" +
|
||||
diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
|
||||
index 6fb1a6eeb0..be7a920511 100644
|
||||
--- a/src/html/template/state_string.go
|
||||
+++ b/src/html/template/state_string.go
|
||||
@@ -25,21 +25,23 @@ func _() {
|
||||
_ = x[stateJSRegexp-14]
|
||||
_ = x[stateJSBlockCmt-15]
|
||||
_ = x[stateJSLineCmt-16]
|
||||
- _ = x[stateCSS-17]
|
||||
- _ = x[stateCSSDqStr-18]
|
||||
- _ = x[stateCSSSqStr-19]
|
||||
- _ = x[stateCSSDqURL-20]
|
||||
- _ = x[stateCSSSqURL-21]
|
||||
- _ = x[stateCSSURL-22]
|
||||
- _ = x[stateCSSBlockCmt-23]
|
||||
- _ = x[stateCSSLineCmt-24]
|
||||
- _ = x[stateError-25]
|
||||
- _ = x[stateDead-26]
|
||||
+ _ = x[stateJSHTMLOpenCmt-17]
|
||||
+ _ = x[stateJSHTMLCloseCmt-18]
|
||||
+ _ = x[stateCSS-19]
|
||||
+ _ = x[stateCSSDqStr-20]
|
||||
+ _ = x[stateCSSSqStr-21]
|
||||
+ _ = x[stateCSSDqURL-22]
|
||||
+ _ = x[stateCSSSqURL-23]
|
||||
+ _ = x[stateCSSURL-24]
|
||||
+ _ = x[stateCSSBlockCmt-25]
|
||||
+ _ = x[stateCSSLineCmt-26]
|
||||
+ _ = x[stateError-27]
|
||||
+ _ = x[stateDead-28]
|
||||
}
|
||||
|
||||
-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
|
||||
+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
|
||||
|
||||
-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
|
||||
+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354}
|
||||
|
||||
func (i state) String() string {
|
||||
if i >= state(len(_state_index)-1) {
|
||||
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
|
||||
index 92eb351906..12aa4c41fe 100644
|
||||
--- a/src/html/template/transition.go
|
||||
+++ b/src/html/template/transition.go
|
||||
@@ -14,32 +14,34 @@ import (
|
||||
// the updated context and the number of bytes consumed from the front of the
|
||||
// input.
|
||||
var transitionFunc = [...]func(context, []byte) (context, int){
|
||||
- stateText: tText,
|
||||
- stateTag: tTag,
|
||||
- stateAttrName: tAttrName,
|
||||
- stateAfterName: tAfterName,
|
||||
- stateBeforeValue: tBeforeValue,
|
||||
- stateHTMLCmt: tHTMLCmt,
|
||||
- stateRCDATA: tSpecialTagEnd,
|
||||
- stateAttr: tAttr,
|
||||
- stateURL: tURL,
|
||||
- stateSrcset: tURL,
|
||||
- stateJS: tJS,
|
||||
- stateJSDqStr: tJSDelimited,
|
||||
- stateJSSqStr: tJSDelimited,
|
||||
- stateJSBqStr: tJSDelimited,
|
||||
- stateJSRegexp: tJSDelimited,
|
||||
- stateJSBlockCmt: tBlockCmt,
|
||||
- stateJSLineCmt: tLineCmt,
|
||||
- stateCSS: tCSS,
|
||||
- stateCSSDqStr: tCSSStr,
|
||||
- stateCSSSqStr: tCSSStr,
|
||||
- stateCSSDqURL: tCSSStr,
|
||||
- stateCSSSqURL: tCSSStr,
|
||||
- stateCSSURL: tCSSStr,
|
||||
- stateCSSBlockCmt: tBlockCmt,
|
||||
- stateCSSLineCmt: tLineCmt,
|
||||
- stateError: tError,
|
||||
+ stateText: tText,
|
||||
+ stateTag: tTag,
|
||||
+ stateAttrName: tAttrName,
|
||||
+ stateAfterName: tAfterName,
|
||||
+ stateBeforeValue: tBeforeValue,
|
||||
+ stateHTMLCmt: tHTMLCmt,
|
||||
+ stateRCDATA: tSpecialTagEnd,
|
||||
+ stateAttr: tAttr,
|
||||
+ stateURL: tURL,
|
||||
+ stateSrcset: tURL,
|
||||
+ stateJS: tJS,
|
||||
+ stateJSDqStr: tJSDelimited,
|
||||
+ stateJSSqStr: tJSDelimited,
|
||||
+ stateJSBqStr: tJSDelimited,
|
||||
+ stateJSRegexp: tJSDelimited,
|
||||
+ stateJSBlockCmt: tBlockCmt,
|
||||
+ stateJSLineCmt: tLineCmt,
|
||||
+ stateJSHTMLOpenCmt: tLineCmt,
|
||||
+ stateJSHTMLCloseCmt: tLineCmt,
|
||||
+ stateCSS: tCSS,
|
||||
+ stateCSSDqStr: tCSSStr,
|
||||
+ stateCSSSqStr: tCSSStr,
|
||||
+ stateCSSDqURL: tCSSStr,
|
||||
+ stateCSSSqURL: tCSSStr,
|
||||
+ stateCSSURL: tCSSStr,
|
||||
+ stateCSSBlockCmt: tBlockCmt,
|
||||
+ stateCSSLineCmt: tLineCmt,
|
||||
+ stateError: tError,
|
||||
}
|
||||
|
||||
var commentStart = []byte("<!--")
|
||||
@@ -263,7 +265,7 @@ func tURL(c context, s []byte) (context, int) {
|
||||
|
||||
// tJS is the context transition function for the JS state.
|
||||
func tJS(c context, s []byte) (context, int) {
|
||||
- i := bytes.IndexAny(s, "\"`'/")
|
||||
+ i := bytes.IndexAny(s, "\"`'/<-#")
|
||||
if i == -1 {
|
||||
// Entire input is non string, comment, regexp tokens.
|
||||
c.jsCtx = nextJSCtx(s, c.jsCtx)
|
||||
@@ -293,6 +295,26 @@ func tJS(c context, s []byte) (context, int) {
|
||||
err: errorf(ErrSlashAmbig, nil, 0, "'/' could start a division or regexp: %.32q", s[i:]),
|
||||
}, len(s)
|
||||
}
|
||||
+ // ECMAScript supports HTML style comments for legacy reasons, see Appendix
|
||||
+ // B.1.1 "HTML-like Comments". The handling of these comments is somewhat
|
||||
+ // confusing. Multi-line comments are not supported, i.e. anything on lines
|
||||
+ // between the opening and closing tokens is not considered a comment, but
|
||||
+ // anything following the opening or closing token, on the same line, is
|
||||
+ // ignored. As such we simply treat any line prefixed with "<!--" or "-->"
|
||||
+ // as if it were actually prefixed with "//" and move on.
|
||||
+ case '<':
|
||||
+ if i+3 < len(s) && bytes.Equal(commentStart, s[i:i+4]) {
|
||||
+ c.state, i = stateJSHTMLOpenCmt, i+3
|
||||
+ }
|
||||
+ case '-':
|
||||
+ if i+2 < len(s) && bytes.Equal(commentEnd, s[i:i+3]) {
|
||||
+ c.state, i = stateJSHTMLCloseCmt, i+2
|
||||
+ }
|
||||
+ // ECMAScript also supports "hashbang" comment lines, see Section 12.5.
|
||||
+ case '#':
|
||||
+ if i+1 < len(s) && s[i+1] == '!' {
|
||||
+ c.state, i = stateJSLineCmt, i+1
|
||||
+ }
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
@@ -372,12 +394,12 @@ func tBlockCmt(c context, s []byte) (context, int) {
|
||||
return c, i + 2
|
||||
}
|
||||
|
||||
-// tLineCmt is the context transition function for //comment states.
|
||||
+// tLineCmt is the context transition function for //comment states, and the JS HTML-like comment state.
|
||||
func tLineCmt(c context, s []byte) (context, int) {
|
||||
var lineTerminators string
|
||||
var endState state
|
||||
switch c.state {
|
||||
- case stateJSLineCmt:
|
||||
+ case stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt:
|
||||
lineTerminators, endState = "\n\r\u2028\u2029", stateJS
|
||||
case stateCSSLineCmt:
|
||||
lineTerminators, endState = "\n\f\r", stateCSS
|
||||
--
|
||||
2.33.0
|
||||
259
0051-Backport-html-template-properly-handle-special-tags-.patch
Normal file
259
0051-Backport-html-template-properly-handle-special-tags-.patch
Normal file
@ -0,0 +1,259 @@
|
||||
From 015ed76f8637206669be945cb7d1c4315b5a0110 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Thu, 3 Aug 2023 12:28:28 -0700
|
||||
Subject: [PATCH 2/2] [Backport] html/template: properly handle special tags
|
||||
within the script context
|
||||
|
||||
Reference: https://open.codehub.huawei.com/OpenSourceCenter/golang/go/merge_requests/94
|
||||
Conflict: NA
|
||||
|
||||
The HTML specification has incredibly complex rules for how to handle
|
||||
"<!--", "<script", and "</script" when they appear within literals in
|
||||
the script context. Rather than attempting to apply these restrictions
|
||||
(which require a significantly more complex state machine) we apply
|
||||
the workaround suggested in section 4.12.1.3 of the HTML specification [1].
|
||||
|
||||
More precisely, when "<!--", "<script", and "</script" appear within
|
||||
literals (strings and regular expressions, ignoring comments since we
|
||||
already elide their content) we replace the "<" with "\x3C". This avoids
|
||||
the unintuitive behavior that using these tags within literals can cause,
|
||||
by simply preventing the rendered content from triggering it. This may
|
||||
break some correct usages of these tags, but on balance is more likely
|
||||
to prevent XSS attacks where users are unknowingly either closing or not
|
||||
closing the script blocks where they think they are.
|
||||
|
||||
Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
|
||||
reporting this issue.
|
||||
|
||||
Note: The upstream does not submit this change to go1.17 according to the rules of MinorReleases.
|
||||
Corego3.x are based on go1.17.8. Therefore, it need to submit the change to corego3.x.
|
||||
|
||||
Edited-by: machangwang m00509938
|
||||
|
||||
Fixes #62197
|
||||
Fixes #62397
|
||||
Fixes CVE-2023-39319
|
||||
|
||||
[1] https://html.spec.whatwg.org/#restrictions-for-contents-of-script-elements
|
||||
|
||||
Change-Id: Iab57b0532694827e3eddf57a7497ba1fab1746dc
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976594
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Run-TryBot: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014621
|
||||
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/526099
|
||||
TryBot-Result: Gopher Robot <gobot@golang.org>
|
||||
Run-TryBot: Cherry Mui <cherryyz@google.com>
|
||||
|
||||
Signed-off-by: Ma Chang Wang machangwang@huawei.com
|
||||
---
|
||||
src/go/build/deps_test.go | 6 ++--
|
||||
src/html/template/context.go | 14 ++++++++++
|
||||
src/html/template/escape.go | 26 ++++++++++++++++++
|
||||
src/html/template/escape_test.go | 47 +++++++++++++++++++++++++++++++-
|
||||
src/html/template/transition.go | 15 ++++++++++
|
||||
5 files changed, 104 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
|
||||
index 610fba2da9..e56cd587ff 100644
|
||||
--- a/src/go/build/deps_test.go
|
||||
+++ b/src/go/build/deps_test.go
|
||||
@@ -255,15 +255,15 @@ var depsRules = `
|
||||
< text/template
|
||||
< internal/lazytemplate;
|
||||
|
||||
- encoding/json, html, text/template
|
||||
- < html/template;
|
||||
-
|
||||
# regexp
|
||||
FMT
|
||||
< regexp/syntax
|
||||
< regexp
|
||||
< internal/lazyregexp;
|
||||
|
||||
+ encoding/json, html, text/template, regexp
|
||||
+ < html/template;
|
||||
+
|
||||
# suffix array
|
||||
encoding/binary, regexp
|
||||
< index/suffixarray;
|
||||
diff --git a/src/html/template/context.go b/src/html/template/context.go
|
||||
index 472b5a9772..8c3cc4709e 100644
|
||||
--- a/src/html/template/context.go
|
||||
+++ b/src/html/template/context.go
|
||||
@@ -170,6 +170,20 @@ func isInTag(s state) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
+// isInScriptLiteral returns true if s is one of the literal states within a
|
||||
+// <script> tag, and as such occurances of "<!--", "<script", and "</script"
|
||||
+// need to be treated specially.
|
||||
+func isInScriptLiteral(s state) bool {
|
||||
+ // Ignore the comment states (stateJSBlockCmt, stateJSLineCmt,
|
||||
+ // stateJSHTMLOpenCmt, stateJSHTMLCloseCmt) because their content is already
|
||||
+ // omitted from the output.
|
||||
+ switch s {
|
||||
+ case stateJSDqStr, stateJSSqStr, stateJSBqStr, stateJSRegexp:
|
||||
+ return true
|
||||
+ }
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
// delim is the delimiter that will end the current HTML attribute.
|
||||
type delim uint8
|
||||
|
||||
diff --git a/src/html/template/escape.go b/src/html/template/escape.go
|
||||
index 3249c67008..b0085ceccc 100644
|
||||
--- a/src/html/template/escape.go
|
||||
+++ b/src/html/template/escape.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"html"
|
||||
"internal/godebug"
|
||||
"io"
|
||||
+ "regexp"
|
||||
"text/template"
|
||||
"text/template/parse"
|
||||
)
|
||||
@@ -652,6 +653,26 @@ var delimEnds = [...]string{
|
||||
delimSpaceOrTagEnd: " \t\n\f\r>",
|
||||
}
|
||||
|
||||
+var (
|
||||
+ // Per WHATWG HTML specification, section 4.12.1.3, there are extremely
|
||||
+ // complicated rules for how to handle the set of opening tags <!--,
|
||||
+ // <script, and </script when they appear in JS literals (i.e. strings,
|
||||
+ // regexs, and comments). The specification suggests a simple solution,
|
||||
+ // rather than implementing the arcane ABNF, which involves simply escaping
|
||||
+ // the opening bracket with \x3C. We use the below regex for this, since it
|
||||
+ // makes doing the case-insensitive find-replace much simpler.
|
||||
+ specialScriptTagRE = regexp.MustCompile("(?i)<(script|/script|!--)")
|
||||
+ specialScriptTagReplacement = []byte("\\x3C$1")
|
||||
+)
|
||||
+
|
||||
+func containsSpecialScriptTag(s []byte) bool {
|
||||
+ return specialScriptTagRE.Match(s)
|
||||
+}
|
||||
+
|
||||
+func escapeSpecialScriptTags(s []byte) []byte {
|
||||
+ return specialScriptTagRE.ReplaceAll(s, specialScriptTagReplacement)
|
||||
+}
|
||||
+
|
||||
var doctypeBytes = []byte("<!DOCTYPE")
|
||||
|
||||
// escapeText escapes a text template node.
|
||||
@@ -710,6 +731,11 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
|
||||
b.Write(s[written:cs])
|
||||
written = i1
|
||||
}
|
||||
+ if isInScriptLiteral(c.state) && containsSpecialScriptTag(s[i:i1]) {
|
||||
+ b.Write(s[written:i])
|
||||
+ b.Write(escapeSpecialScriptTags(s[i:i1]))
|
||||
+ written = i1
|
||||
+ }
|
||||
if i == i1 && c.state == c1.state {
|
||||
panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
|
||||
}
|
||||
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
|
||||
index e38888a13f..2f9f4c21f0 100644
|
||||
--- a/src/html/template/escape_test.go
|
||||
+++ b/src/html/template/escape_test.go
|
||||
@@ -513,6 +513,21 @@ func TestEscape(t *testing.T) {
|
||||
"<script>#! beep\n</script>",
|
||||
"<script>\n</script>",
|
||||
},
|
||||
+ {
|
||||
+ "Special tags in <script> string literals",
|
||||
+ `<script>var a = "asd < 123 <!-- 456 < fgh <script jkl < 789 </script"</script>`,
|
||||
+ `<script>var a = "asd < 123 \x3C!-- 456 < fgh \x3Cscript jkl < 789 \x3C/script"</script>`,
|
||||
+ },
|
||||
+ {
|
||||
+ "Special tags in <script> string literals (mixed case)",
|
||||
+ `<script>var a = "<!-- <ScripT </ScripT"</script>`,
|
||||
+ `<script>var a = "\x3C!-- \x3CScripT \x3C/ScripT"</script>`,
|
||||
+ },
|
||||
+ {
|
||||
+ "Special tags in <script> regex literals (mixed case)",
|
||||
+ `<script>var a = /<!-- <ScripT </ScripT/</script>`,
|
||||
+ `<script>var a = /\x3C!-- \x3CScripT \x3C/ScripT/</script>`,
|
||||
+ },
|
||||
{
|
||||
"CSS comments",
|
||||
"<style>p// paragraph\n" +
|
||||
@@ -1509,8 +1524,38 @@ func TestEscapeText(t *testing.T) {
|
||||
context{state: stateJS, element: elementScript},
|
||||
},
|
||||
{
|
||||
+ // <script and </script tags are escaped, so </script> should not
|
||||
+ // cause us to exit the JS state.
|
||||
`<script>document.write("<script>alert(1)</script>");`,
|
||||
- context{state: stateText},
|
||||
+ context{state: stateJS, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>`,
|
||||
+ context{state: stateJSDqStr, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>alert(1)</script>`,
|
||||
+ context{state: stateJSDqStr, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>alert(1)<!--`,
|
||||
+ context{state: stateJSDqStr, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<script>alert(1)</Script>");`,
|
||||
+ context{state: stateJS, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>document.write("<!--");`,
|
||||
+ context{state: stateJS, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>let a = /</script`,
|
||||
+ context{state: stateJSRegexp, element: elementScript},
|
||||
+ },
|
||||
+ {
|
||||
+ `<script>let a = /</script/`,
|
||||
+ context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp},
|
||||
},
|
||||
{
|
||||
`<script type="text/template">`,
|
||||
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
|
||||
index 12aa4c41fe..3d2a37cdd9 100644
|
||||
--- a/src/html/template/transition.go
|
||||
+++ b/src/html/template/transition.go
|
||||
@@ -214,6 +214,11 @@ var (
|
||||
// element states.
|
||||
func tSpecialTagEnd(c context, s []byte) (context, int) {
|
||||
if c.element != elementNone {
|
||||
+ // script end tags ("</script") within script literals are ignored, so that
|
||||
+ // we can properly escape them.
|
||||
+ if c.element == elementScript && (isInScriptLiteral(c.state) || isComment(c.state)) {
|
||||
+ return c, len(s)
|
||||
+ }
|
||||
if i := indexTagEnd(s, specialTagEndMarkers[c.element]); i != -1 {
|
||||
return context{}, i
|
||||
}
|
||||
@@ -353,6 +358,16 @@ func tJSDelimited(c context, s []byte) (context, int) {
|
||||
inCharset = true
|
||||
case ']':
|
||||
inCharset = false
|
||||
+ case '/':
|
||||
+ // If "</script" appears in a regex literal, the '/' should not
|
||||
+ // close the regex literal, and it will later be escaped to
|
||||
+ // "\x3C/script" in escapeText.
|
||||
+ if i > 0 && i+7 <= len(s) && bytes.Compare(bytes.ToLower(s[i-1:i+7]), []byte("</script")) == 0 {
|
||||
+ i++
|
||||
+ } else if !inCharset {
|
||||
+ c.state, c.jsCtx = stateJS, jsCtxDivOp
|
||||
+ return c, i + 1
|
||||
+ }
|
||||
default:
|
||||
// end delimiter
|
||||
if !inCharset {
|
||||
--
|
||||
2.33.0
|
||||
10
golang.spec
10
golang.spec
@ -63,7 +63,7 @@
|
||||
|
||||
Name: golang
|
||||
Version: 1.17.3
|
||||
Release: 22
|
||||
Release: 23
|
||||
Summary: The Go Programming Language
|
||||
License: BSD and Public Domain
|
||||
URL: https://golang.org/
|
||||
@ -199,6 +199,8 @@ Patch6046: 0046-Backport-cmd-go-cmd-cgo-in-_cgo_flags-use-one-line-p.patch
|
||||
Patch6047: 0047-Backport-net-http-validate-Host-header-before-sendin.patch
|
||||
Patch6048: 0048-Backport-net-http-permit-requests-with-invalid-Host-headers.patch
|
||||
Patch6049: 0049-Backport-crypto-tls-restrict-RSA-keys-in-certificates-to-8192.patch
|
||||
Patch6050: 0050-Backport-html-template-support-HTML-like-comments-in.patch
|
||||
Patch6051: 0051-Backport-html-template-properly-handle-special-tags-.patch
|
||||
|
||||
ExclusiveArch: %{golang_arches}
|
||||
|
||||
@ -437,6 +439,12 @@ fi
|
||||
%files devel -f go-tests.list -f go-misc.list -f go-src.list
|
||||
|
||||
%changelog
|
||||
* Mon Sep 25 2023 luoyujie <luoyujie5@huawei.com> - 1.17.3-23
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-39318,CVE-2023-39319
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2023-39318 and CVE-2023-39319
|
||||
|
||||
* Fri Aug 25 2023 luoyujie <luoyujie5@huawei.com> - 1.17.3-22
|
||||
- Type:CVE
|
||||
- CVE:CVE-2023-29409
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user