jfinal_cms-v5.1.0 审计黑盒
00x0不登录0x0接口收集前端front/article/ front/articlelike/no/ front/articlelike/yes/ front/comment/count front/comment/del front/comment/save front/person/delblog/ front/regist/save front/tags/大部分是接口但有登录鉴权这个我猜测是文章点赞取消的接口但是做了鉴权处理代码分析没完全明白ControllerBind(controllerKey /front/articlelike) public class ArticleLikeController extends BaseProjectController { /** * 喜欢 * * 2015年8月16日 下午4:20:10 * flyfox 369191470qq.com */ public void yes() { //获取get后面的id //框架会自动创建实例getParaToInt() Integer articleId getParaToInt(); //创建一个json实例 JSONObject json new JSONObject(); //放入操作 json.put(status, 2);// 失败 //鉴权处理 SysUser user (SysUser) getSessionUser(); //如果没有登录 if (user null) { json.put(msg, 没有登录不能操作); //读取返回 renderJson(json.toJSONString()); return; } //如果没有id if (articleId null || articleId 0) { json.put(msg, 操作异常); renderJson(json.toJSONString()); return; }Inherited Retention(RetentionPolicy.RUNTIME) Target({ ElementType.TYPE }) public interface ControllerBind { String controllerKey(); String viewPath() default ; }Override SuppressWarnings({ rawtypes, unchecked }) //方法标签这是一个普通方法可能在某个自定义的 Routes 子类中比如 AutoBindRoutes用于执行自动绑定逻辑。 public void config() { //ClassSearcher 是项目自带的工具类用于在类路径和指定的 JAR 包中查找类。 ListClass? extends Controller controllerClasses ClassSearcher.findInClasspathAndJars(Controller.class, includeJars); ControllerBind controllerBind null; //for遍历扫描所有controller子类 for (Class controller : controllerClasses) { //排除指定的类可选 if (excludeClasses.contains(controller)) { continue; } //获取注释controllerBind (ControllerBind)controller.getAnnotation(ControllerBind.class) controllerBind (ControllerBind) controller.getAnnotation(ControllerBind.class); //检查controllerBind是否为空 //通过反射获取该类上标注的 ControllerBind 注解实例。如果没有标注controllerBind 为 null。 if (controllerBind null) { //检查全局开关 if (!autoScan) { continue; } //判断类名是否以suffix结尾 if (!controller.getSimpleName().endsWith(suffix)) { logger.debug(routes.add controller.getName() is suffix not suffix); continue; } this.add(controllerKey(controller), controller); logger.debug(routes.add( controllerKey(controller) , controller.getName() )); } else if (StrKit.isBlank(controllerBind.viewPath())) { this.add(controllerBind.controllerKey(), controller); logger.debug(routes.add( controllerBind.controllerKey() , controller.getName() )); } else { this.add(controllerBind.controllerKey(), controller, controllerBind.viewPath()); logger.debug(routes.add( controllerBind.controllerKey() , controller , controllerBind.viewPath() )); } } }//静态方法 public static T ListClass? extends T findInClasspathAndJars(ClassT clazz, ListString includeJars) { String path PathUtils.rebuild(classPathUrl.getFile()); ListString classFileList findFiles(path, *.class); String libPath PathUtils.rebuild(lib); classFileList.addAll(findjarFiles(libPath, includeJars)); return extraction(clazz, classFileList); }7跳转首页收集http://localhost:8080/jfinal_cms/admin/ http://localhost:8080/jfinal_cms/login/ http://localhost:8080/jfinal_cms http://localhost:8080/jfinal_cms/front/regist.html0x1 框架信息大部分对的0x2 xss有/过滤并且不会渲染感觉是原来有但是被修复了。代码分析未完成ControllerBind(controllerKey /front/tags) public class TagsController extends BaseProjectController { public static final String path /tags/; Before(FrontInterceptor.class) public void index() { //获取get后面的值 String tagName getPara(); try { //如果空的就默认 tagName (tagName null ? : tagName); // tagName URLDecoder.decode(tagName, UTF-8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 去除标签 tagName HtmlUtils.delHTMLTag(tagName); // 更新tag tagName HtmlUtils.delSpecialCode(tagName); setAttr(tagName, tagName); // 数据列表,只查询展示的和类型为11,12的 PageTbArticle articles TbArticle.dao.paginate(getPaginator(), select a.*, // from (select distinct t.* from tb_article t // left join tb_folder tf on tf.id t.folder_id // left join tb_tags tag on tag.article_id t.id // where (tag.tagname like ? or t.title like ?) // and t.status 1 and t.type in (11,12) // 查询状态为显示类型是预览和正常的文章 and tf.site_id getSessionSite().getSiteId() // order by t.sort,t.create_time desc ) a, % tagName %, % tagName %); setAttr(page, articles); // 显示50个标签 if (articles.getTotalRow() 0) { PageTbTags taglist new FrontCacheService().getTagsByFolder(new Paginator(1, 50), articles.getList() .get(0).getFolderId()); setAttr(taglist, taglist.getList()); } else { PageTbTags taglist new FrontCacheService().getTags(new Paginator(1, 50), getSessionSite().getSiteId()); setAttr(taglist, taglist.getList()); } // seotitle优化 setAttr(JFlyFoxUtils.TITLE_ATTR, tagName - 搜索 - getAttr(JFlyFoxUtils.TITLE_ATTR)); renderAuto(path search.html); }//过滤 public static String decode(String s, String enc) throws UnsupportedEncodingException{ //默认设置开关 boolean needToChange false; 获取get编码长度 int numChars s.length(); //判断长度是否大于500是/2不是原来创建相应长度数组 StringBuffer sb new StringBuffer(numChars 500 ? numChars / 2 : numChars); int i 0; if (enc.length() 0) {//检查有没有utf8 throw new UnsupportedEncodingException (URLDecoder: empty string enc parameter); } char c; byte[] bytes null; //装进去 while (i numChars) { //获取字符 c s.charAt(i); switch (c) { case : //转化空格 sb.append( ); i; //打开开关 needToChange true; //跳出判断 break; //%处理 case %: try { //如果数组是空的第一次 if (bytes null){ //创建一个数组-i/3 //编码占用3个字符 bytes new byte[(numChars-i)/3];} int pos 0; //判断get长度是不是到了末尾 while ( ((i2) numChars) (c%)) { //截取转码转16进制 int v Integer.parseInt(s.substring(i1,i3),16); //如果0 if (v 0) throw new IllegalArgumentException(URLDecoder: Illegal hex characters in escape (%) pattern - negative value); bytes[pos] (byte) v; //i3 i 3; //末尾 if (i numChars) c s.charAt(i); } if ((i numChars) (c%)) throw new IllegalArgumentException( URLDecoder: Incomplete trailing escape (%) pattern); sb.append(new String(bytes, 0, pos, enc)); } catch (NumberFormatException e) { throw new IllegalArgumentException( URLDecoder: Illegal hex characters in escape (%) pattern - e.getMessage()); } needToChange true; break; default: sb.append(c); i; break; } } //返回 return (needToChange? sb.toString() : s); } }public StringBuffer(int capacity) { super(capacity); }AbstractStringBuilder(int capacity) { value new char[capacity]; }0x3 SQLhttp://localhost:8080/jfinal_cms/?orderType4看看有没有注入代码分析没有注入public PageTbArticle getArticleByOrder(Paginator paginator, int siteId, int orderType) { String key (articleOrder_ paginator.getPageNo() _ paginator.getPageSize() _ siteId _ orderType); String fromSql from tb_article t // left join tb_folder tf on tf.id t.folder_id // where getPublicWhere() // and tf.site_id ? ; if (orderType1) { // 默认 fromSql order by t.sort,t.create_time desc; } else if (orderType2){ // 最新 fromSql order by t.create_time desc; } else if (orderType3){ // 精品 fromSql order by (t.count_comment*10t.count_view) desc; } else if (orderType4){ // 待回复的 fromSql and t.count_comment 0 order by t.create_time desc; } // 推荐文章列表 PageTbArticle articles TbArticle.dao.paginateCache(cacheName, key, paginator, select t.* , fromSql, siteId); return articles; }00x1 admin登录0x0抓包管理员编辑GET /jfinal_cms/front/person/editblog/4249 HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0 Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8 Accept-Language: zh-CN,zh;q0.9,zh-TW;q0.8,zh-HK;q0.7,en-US;q0.6,en;q0.5 Accept-Encoding: gzip, deflate, br Connection: keep-alive Referer: http://localhost:8080/jfinal_cms/home.html Cookie: JSESSIONID4B80C6600606346C89833707F6AF2CC6; Hm_lvt_1040d081eea13b44d84a4af639640d511774074337; Hm_lpvt_1040d081eea13b44d84a4af639640d511774099683; HMACCOUNTCFD43E6B2F46D5DF; session_userwgPmpe3hEuJWILIkHtxqag1wutWsMhm6eaAgoJH0c Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 Priority: u0, i管理员发布POST /jfinal_cms/front/person/saveblog/4249 HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0 Accept: */* Accept-Language: zh-CN,zh;q0.9,zh-TW;q0.8,zh-HK;q0.7,en-US;q0.6,en;q0.5 Accept-Encoding: gzip, deflate, br Content-Type: application/x-www-form-urlencoded; charsetUTF-8 X-Requested-With: XMLHttpRequest Content-Length: 2609 Origin: http://localhost:8080 Connection: keep-alive Referer: http://localhost:8080/jfinal_cms/front/person/editblog/4249 Cookie: JSESSIONID4B80C6600606346C89833707F6AF2CC6; Hm_lvt_1040d081eea13b44d84a4af639640d511774074337; Hm_lpvt_1040d081eea13b44d84a4af639640d511774099903; HMACCOUNTCFD43E6B2F46D5DF; session_userwgPmpe3hEuJWILIkHtxqag1wutWsMhm6eaAgoJH0c Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Priority: u0 search_headermodel.id4249model.folder_id257model.title%E8%B5%84%E8%AE%AF%E7%AB%99%E4%BB%8B%E7%BB%8Dtags%E8%B5%84%E8%AE%AFtags_content%E8%B5%84%E8%AE%AFmodel.content%3Cp%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%E8%B5%84%E8%AE%AF%E6%98%AF%E7%94%A8%E6%88%B7%E5%9B%A0%E4%B8%BA%E5%8F%8A%E6%97%B6%E5%9C%B0%E8%8E%B7%E5%BE%97%E5%AE%83%E5%B9%B6%E5%88%A9%E7%94%A8%E5%AE%83%E8%80%8C%E8%83%BD%E5%A4%9F%E5%9C%A8%E7%9B%B8%E5%AF%B9%E7%9F%AD%E7%9A%84%E6%97%B6%E9%97%B4%E5%86%85%E7%BB%99%E8%87%AA%E5%B7%B1%E5%B8%A6%E6%9D%A5%E4%BB%B7%E5%80%BC%E7%9A%84%E4%BF%A1%E6%81%AF%EF%BC%8C%E8%B5%84%E8%AE%AF%E6%9C%89%E6%97%B6%E6%95%88%E6%80%A7%E5%92%8C%E5%9C%B0%E5%9F%9F%E6%80%A7%EF%BC%8C%E5%AE%83%E5%BF%85%E9%A1%BB%E8%A2%AB%E6%B6%88%E8%B4%B9%E8%80%85%E5%88%A9%E7%94%A8%E3%80%82%E5%B9%B6%E4%B8%94%E2%80%9C%E6%8F%90%E4%BE%9B%EF%BC%8D%E4%BD%BF%E7%94%A8%EF%BC%88%E9%98%85%E8%AF%BB%E6%88%96%E5%88%A9%E7%94%A8%EF%BC%89%EF%BC%8D%E5%8F%8D%E9%A6%88%E2%80%9D%E4%B9%8B%E9%97%B4%E8%83%BD%E5%A4%9F%E5%BD%A2%E6%88%90%E4%B8%80%E4%B8%AA%E9%95%BF%E6%9C%9F%E7%A8%B3%E5%AE%9A%E7%9A%84CS%E9%93%BE%EF%BC%8C%E5%85%B7%E6%9C%89%E8%BF%99%E4%BA%9B%E7%89%B9%E7%82%B9%E6%89%8D%E5%8F%AF%E4%BB%A5%E7%A7%B0%E4%B9%8B%E4%B8%BA%E8%B5%84%E8%AE%AF%E3%80%82%E4%BB%8E%E4%B8%A5%E6%A0%BC%E7%9A%84%E6%84%8F%E4%B9%89%E4%B8%8A%E8%AE%B2%EF%BC%8C%E6%96%B0%E9%97%BB%E6%98%AF%E4%B8%80%E7%A7%8D%E8%B5%84%E8%AE%AF%E3%80%82%E8%B5%84%E8%AE%AF%E6%98%AF%E4%B8%80%E7%A7%8D%E4%BF%A1%E6%81%AF%EF%BC%8C%E6%B6%B5%E7%9B%96%E7%9A%84%E4%B8%8D%E5%8F%AA%E6%98%AF%E6%96%B0%E9%97%BB%EF%BC%8C%E8%BF%98%E5%8F%AF%E4%BB%A5%E5%8C%85%E6%8B%AC%E5%85%B6%E4%BB%96%E5%AA%92%E4%BB%8B%E3%80%82%E5%A6%82%E4%BA%B2%E4%B8%B4%E4%B8%93%E5%AE%B6%E8%AE%B2%E5%BA%A7%E7%AD%89%E7%AD%89%EF%BC%9B%E6%96%B0%E9%97%BB%E7%9A%84%E7%9B%AE%E6%A0%87%E5%8F%97%E4%BC%97%E7%9B%B8%E5%AF%B9%E5%AE%BD%E6%B3%9B%EF%BC%8C%E6%B2%A1%E6%9C%89%E4%B8%A5%E6%A0%BC%E7%9A%84%E5%8F%97%E4%BC%97%E5%88%92%E5%88%86%EF%BC%8C%E5%AD%A6%E8%AF%AD%E8%A8%80%E7%9A%84%E4%BA%BA%E5%8F%AF%E4%BB%A5%E5%8E%BB%E9%98%85%E8%AF%BB%E7%A7%91%E6%8A%80%E6%96%B0%E9%97%BB%E3%80%82%E5%AD%A6%E6%8A%80%E6%9C%AF%E7%9A%84%E4%B9%9F%E5%AE%8C%E5%85%A8%E5%8F%AF%E4%BB%A5%E5%8E%BB%E9%98%85%E8%AF%BB%E6%96%87%E5%AD%A6%E6%96%B0%E9%97%BB%EF%BC%8C%E8%80%8C%E8%B5%84%E8%AE%AF%E7%9A%84%E5%8F%97%E4%BC%97%E7%9A%84%E7%9B%AE%E6%A0%87%E6%80%A7%E7%9B%B8%E5%AF%B9%E6%AF%94%E8%BE%83%E5%BC%BA%E3%80%82%3C%2Fp%3E%3Cp%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%E6%9C%AC%E7%AB%99%E8%B5%84%E8%AE%AF%E7%BD%91%E7%AB%99%E5%9C%B0%E5%9D%80%EF%BC%9A%3Cahref%3D%22http%3A%2F%2Fmtg.jflyfox.com%22target%3D%22_blank%22title%3D%22mtg.jflyfox.com%22%3Emtg.jflyfox.com%3C%2Fa%3E%3Cbr%2F%3E%3C%2Fp%3E响应HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: application/json;charsetUTF-8 Content-Length: 12 Date: Sat, 21 Mar 2026 13:34:00 GMT {status:1}管理员点赞0x1 恶意加载这里疑似有文件上传代码分析tr td classright_td头像地址/td td classleft_tdinput namemodel.title_url value${model.title_url!}/td /trdiv classform-group label fortitle_url classcol-sm-2 control-label头像地址/label div classcol-sm-10 input namemodel.title_url typetext classform-control idtitle_url value${model.title_url!} placeholder头像地址 /divjspform classform-horizontal nameform1 action methodpost input typehidden namemodel.userid value${model.userid} / div classform-group text-center div classcol-sm-offset-2 col-sm-10 % var userPic model.title_url; if(isEmpty(userPic)){ userPic BASE_PATH static/images/user/user.png; } else if(!strutil.startWith(userPic , http)) { userPic ASE_PATH userPic; } % img idtitle_pic alt头像 width64 height64 classimg_radius src${userPic} /div /div0x2 sql00x2 用户登录