From 8315806eb80511bc61ecd9e8e56a54c9a916e871 Mon Sep 17 00:00:00 2001 From: bmohanr-techie Date: Wed, 27 Jul 2022 12:20:25 -0700 Subject: [PATCH] CVE-2022-33113 - Jfinal CMS v5.1.0 allows attackers to execute arbitrary web scripts or HTML via a crafted payload injected into the keyword text field under the publish blog module. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Steps to reproduce: As per the info found in vulnerability: There is a stored XSS vulnerability in JFinal_cms 's publish blog module. An attacker can insert malicious XSS code into the Keyword field. When the user views the content of the article in the foreground, the malicious XSS code is triggered successfully. payload: onmouseover='alert(document.cookie)' --------- Commit: The fix here is to ensure that the input strings from the portal is sanitized properly to get rid of the html strings/tags. Here, we are making use of Apache common-lang's StringEscapeUtils APIs - escapeHtml() and unescapeHtml(). escapeHtml(): Escapes the characters in a String using HTML entities. For example: bread & butter becomes: "bread" & "butter". unescapeHtml(): Unescapes a string containing entity escapes to a string containing the actual Unicode characters corresponding to the escapes. For example, the string <Français> will become . --------- Fixed in AlertController and PersonController classes in com.jflyfox.modules.front.controller package. Also, HtmlUtils class will now expose two utility methods - escapeHtml() and unescapeHtml(), which can be used if required else where. The changes are added here to make use of the escapeHtml() and unescapeHtml() in HtmlUtils class for strings specified in Topic and Keyword fields. --------- Verified that the XSS vulnerability is no more applicable for Topic and Keyword fields. Verified the fix in Chrome, Mozilla and Firefox browsers. --- .../front/controller/ArticleController.java | 15 +++++++++ .../front/controller/PersonController.java | 33 +++++++++++++++---- .../com/jflyfox/util/extend/HtmlUtils.java | 24 ++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/jflyfox/modules/front/controller/ArticleController.java b/src/main/java/com/jflyfox/modules/front/controller/ArticleController.java index 6c004c5..4e5d84a 100644 --- a/src/main/java/com/jflyfox/modules/front/controller/ArticleController.java +++ b/src/main/java/com/jflyfox/modules/front/controller/ArticleController.java @@ -16,6 +16,7 @@ import com.jflyfox.modules.front.interceptor.FrontInterceptor; import com.jflyfox.modules.front.service.FrontCacheService; import com.jflyfox.util.StrUtils; +import com.jflyfox.util.extend.HtmlUtils; /** * 文章管理 @@ -61,6 +62,12 @@ public void index() { new FrontCacheService().addArticleCount(article); } + // Fix for CVE-2022-33113... + // HtmlUtils.escapeHtml() is applied for content and title... + // This utility function helps to escape the characters in a String using HTML entities + if (article.getTitle().equals(HtmlUtils.unescapeHtml(article.getTitle()))) { + article.setTitle(HtmlUtils.escapeHtml(article.getTitle())); + } setAttr("item", article); // seo:title优化 @@ -70,6 +77,14 @@ public void index() { // List taglist = new FrontCacheService().getTagsByArticle(articleId); List taglist = TbTags.dao.find("select * from tb_tags " // + "where article_id = ? order by create_time desc ", articleId); + // Fix for CVE-2022-33113... + // HtmlUtils.escapeHtml() is applied for all keywords retrieved... + // This utility function helps to escape the characters in a String using HTML entities + for(TbTags tag: taglist) { + if (tag.getTagname().equals(HtmlUtils.unescapeHtml(tag.getTagname()))) { + tag.setTagname(HtmlUtils.escapeHtml(tag.getTagname())); + } + } setAttr("taglist", taglist); // 评论 diff --git a/src/main/java/com/jflyfox/modules/front/controller/PersonController.java b/src/main/java/com/jflyfox/modules/front/controller/PersonController.java index b439a5b..9363c0c 100644 --- a/src/main/java/com/jflyfox/modules/front/controller/PersonController.java +++ b/src/main/java/com/jflyfox/modules/front/controller/PersonController.java @@ -56,7 +56,7 @@ public void index() { + " where " + getPublicWhere() // + " and t.create_id = ? and tf.site_id = ? " // + " order by t.sort,t.create_time desc", user.getUserid(), getSessionSite().getSiteId()); - setAttr("page", articles); + setAttr("page", escapeHtmlInArticles(articles)); // 显示50个标签 if (articles.getTotalRow() > 0) { @@ -95,7 +95,7 @@ public void article() { + " where " + getPublicWhere() // + " and t.create_id = ? and tf.site_id = ? " // + " order by t.sort,t.create_time desc", user.getUserid(), getSessionSite().getSiteId()); - setAttr("page", articles); + setAttr("page", escapeHtmlInArticles(articles)); // 显示50个标签 if (articles.getTotalRow() > 0) { @@ -135,7 +135,7 @@ public void articlelike() { + " left join tb_articlelike al on al.article_id = t.id" + " where " + getPublicWhere() // + " and al.create_id = ? and tf.site_id = ? " // + " order by t.sort,t.create_time desc", user.getUserid(), getSessionSite().getSiteId()); - setAttr("page", articles); + setAttr("page", escapeHtmlInArticles(articles)); // 显示50个标签 if (articles.getTotalRow() > 0) { @@ -258,9 +258,13 @@ public void saveblog() { content = JFlyFoxUtils.delScriptTag(content); title = HtmlUtils.delHTMLTag(title); tags = HtmlUtils.delHTMLTag(tags); - model.setContent(content); - model.setTitle(title); - + + // Fix for CVE-2022-33113... + // HtmlUtils.escapeHtml() is applied for title and tags variable... + // This utility function helps to escape the characters in a String using HTML entities + title = HtmlUtils.escapeHtml(title); + tags = HtmlUtils.escapeHtml(tags); + // 这里没有必要提示太精准~因为前台有验证~绕过的都不是好人哦 if (content == null || HtmlUtils.delHTMLTag(content).length() > 2000 // || title == null || title.length() > 200 // @@ -459,7 +463,7 @@ public void view() { + " where " + getPublicWhere() // + " and t.create_id = ? and tf.site_id = ? " // + " order by t.sort,t.create_time desc", userid, getSessionSite().getSiteId()); - setAttr("page", articles); + setAttr("page", escapeHtmlInArticles(articles)); // 显示50个标签 if (articles.getTotalRow() > 0) { @@ -478,6 +482,21 @@ public void view() { } + protected Page escapeHtmlInArticles(Page articles) { + // Fix for CVE-2022-33113... + // HtmlUtils.escapeHtml() is applied for title of all article elements... + // This utility function helps to escape the characters in a String using HTML entities + if (articles.getTotalRow() > 0) { + for (TbArticle article : articles.getList()) { + //for now, we have applied escape HTML only for title field... to be extended for other fields if required in future + if (article.getTitle().equals(HtmlUtils.unescapeHtml(article.getTitle()))) { + article.setTitle(HtmlUtils.escapeHtml(article.getTitle())); + } + } + } + return articles; + } + protected Page tags() { return new FrontCacheService().getTags(new Paginator(1, 50), getSessionSite().getSiteId()); } diff --git a/src/main/java/com/jflyfox/util/extend/HtmlUtils.java b/src/main/java/com/jflyfox/util/extend/HtmlUtils.java index 2982214..03de415 100644 --- a/src/main/java/com/jflyfox/util/extend/HtmlUtils.java +++ b/src/main/java/com/jflyfox/util/extend/HtmlUtils.java @@ -20,6 +20,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang.StringEscapeUtils; + /** * html处理 * @@ -124,4 +126,26 @@ public static String delSpecialCode(String content) { return content; } + /** + * Escapes the characters in a String using HTML entities + * For example: "bread" & "butter" becomes: "bread" & "butter". + * + * @param plainHtmlString (the String to escape, may be null) + * @return a new escaped String, null if null string input + */ + public static String escapeHtml(String plainHtmlString) { + return StringEscapeUtils.escapeHtml(plainHtmlString); + } + + /** + * Unescapes a string containing entity escapes to a string containing the actual Unicode characters corresponding to the escapes. + * For example, the string "<Français>" will become "". + * + * @param escapedHtmlString (the String to unescape, may be null) + * @return a new unescaped String, null if null string input + */ + public static String unescapeHtml(String escapedHtmlString) { + return StringEscapeUtils.unescapeHtml(escapedHtmlString); + } + }