00x0不登录
0x0接口收集
前端
java
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/
大部分是接口,但有登录鉴权
这个我猜测是文章点赞取消的接口,但是做了鉴权处理


代码分析(没完全明白)
java
@ControllerBind(controllerKey = "/front/articlelike")
public class ArticleLikeController extends BaseProjectController {
/**
* 喜欢
*
* 2015年8月16日 下午4:20:10
* flyfox 369191470@qq.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;
}
java
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface ControllerBind {
String controllerKey();
String viewPath() default "";
}
java
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
//方法标签,这是一个普通方法(可能在某个自定义的 Routes 子类中,比如 AutoBindRoutes),用于执行自动绑定逻辑。
public void config() {
//ClassSearcher 是项目自带的工具类,用于在类路径和指定的 JAR 包中查找类。
List<Class<? 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() + ")");
}
}
}
java
//静态方法
public static <T> List<Class<? extends T>> findInClasspathAndJars(Class<T> clazz, List<String> includeJars) {
String path = PathUtils.rebuild(classPathUrl.getFile());
List<String> 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.html
0x1 框架信息
大部分对的

0x2 xss
有/过滤,并且<>不会渲染
感觉是原来有,但是被修复了。


代码分析(未完成)
java
@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的
Page<TbArticle> 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) {
Page<TbTags> taglist = new FrontCacheService().getTagsByFolder(new Paginator(1, 50), articles.getList()
.get(0).getFolderId());
setAttr("taglist", taglist.getList());
} else {
Page<TbTags> taglist = new FrontCacheService().getTags(new Paginator(1, 50), getSessionSite().getSiteId());
setAttr("taglist", taglist.getList());
}
// seo:title优化
setAttr(JFlyFoxUtils.TITLE_ATTR, tagName + " - 搜索 - " + getAttr(JFlyFoxUtils.TITLE_ATTR));
renderAuto(path + "search.html");
}
java
//过滤
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 ( ((i+2) < numChars) &&
(c=='%')) {
//截取转码转16进制
int v = Integer.parseInt(s.substring(i+1,i+3),16);
//如果<0
if (v < 0)
throw new IllegalArgumentException("URLDecoder: Illegal hex characters in escape (%) pattern - negative value");
bytes[pos++] = (byte) v;
//i+3
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);
}
}
java
public StringBuffer(int capacity) {
super(capacity);
}
java
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
0x3 SQL
http://localhost:8080/jfinal_cms/?orderType=4
看看有没有注入

代码分析
没有注入
java
public Page<TbArticle> 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 (orderType==1) { // 默认
fromSql +=" order by t.sort,t.create_time desc";
} else if (orderType==2){ // 最新
fromSql +=" order by t.create_time desc";
} else if (orderType==3){ // 精品
fromSql +=" order by (t.count_comment*10+t.count_view) desc";
} else if (orderType==4){ // 待回复的
fromSql +=" and t.count_comment = 0 order by t.create_time desc";
}
// 推荐文章列表
Page<TbArticle> articles = TbArticle.dao.paginateCache(cacheName, key, paginator, "select t.* ", fromSql, siteId);
return articles;
}
00x1 admin登录
0x0抓包
管理员编辑
java
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/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en-US;q=0.6,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://localhost:8080/jfinal_cms/home.html
Cookie: JSESSIONID=4B80C6600606346C89833707F6AF2CC6; Hm_lvt_1040d081eea13b44d84a4af639640d51=1774074337; Hm_lpvt_1040d081eea13b44d84a4af639640d51=1774099683; HMACCOUNT=CFD43E6B2F46D5DF; session_user="wgPmpe3hEuJWIL+I+kHtxqag1wutWsMhm6eaAgoJH0c="
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
管理员发布
java
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;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en-US;q=0.6,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-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: JSESSIONID=4B80C6600606346C89833707F6AF2CC6; Hm_lvt_1040d081eea13b44d84a4af639640d51=1774074337; Hm_lpvt_1040d081eea13b44d84a4af639640d51=1774099903; HMACCOUNT=CFD43E6B2F46D5DF; session_user="wgPmpe3hEuJWIL+I+kHtxqag1wutWsMhm6eaAgoJH0c="
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
search_header=&model.id=4249&model.folder_id=257&model.title=%E8%B5%84%E8%AE%AF%E7%AB%99%E4%BB%8B%E7%BB%8D&tags=%E8%B5%84%E8%AE%AF&tags_content=%E8%B5%84%E8%AE%AF&model.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%3Ca+href%3D%22http%3A%2F%2Fmtg.jflyfox.com%22+target%3D%22_blank%22+title%3D%22mtg.jflyfox.com%22%3Emtg.jflyfox.com%3C%2Fa%3E%3Cbr%2F%3E%3C%2Fp%3E
响应
java
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 12
Date: Sat, 21 Mar 2026 13:34:00 GMT
{"status":1}
管理员点赞

0x1 恶意加载
这里疑似有文件上传

代码分析
java
<tr>
<td class="right_td">头像地址:</td>
<td class="left_td"><input name="model.title_url"
value="${model.title_url!''}"></td>
</tr>
java
<div class="form-group">
<label for="title_url" class="col-sm-2 control-label">头像地址</label>
<div class="col-sm-10">
<input name="model.title_url" type="text" class="form-control" id="title_url"
value="${model.title_url!''}" placeholder="头像地址">
</div>
jsp
java
<form class="form-horizontal" name="form1" action="" method="post">
<input type="hidden" name="model.userid" value="${model.userid}" />
<div class="form-group text-center">
<div class="col-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 id="title_pic" alt="头像" width="64" height="64"
class="img_radius" src="${userPic}">
</div>
</div>