首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Struts2 登錄繞過漏洞分析:Spring Prototype 作用域導致的安全隱患

     編輯:Java 綜合教學

問題現象

用戶登錄 → 點擊註銷 → Session 清空 → **在地址欄直接輸入 Action URL 卻能直接進入歡迎頁**,繞過了表單提交驗證。

代碼還原

Struts 配置

<action name="checkUser" class="checkUserAction" method="execute">
    <result name="login">/login.jsp</result>
    <result name="success">/home.jsp</result>
</action>
<action name="quitUser" class="checkUserAction" method="quitUser">
    <result name="success">/login.jsp</result>
</action>

Spring Bean 定義

<bean id="administrator" class="pojo.Administrator" />  <!-- 缺省 singleton -->
<bean id="checkUserAction" class="action.checkUserAction" scope="prototype">
    <property name="adminer" ref="administrator"/>
    <property name="adminUserService" ref="adminUserServiceImpl"/>
</bean>

Action 代碼

public class checkUserAction extends ActionSupport implements ModelDriven<Administrator> {
    private Administrator adminer; // 模型驅動屬性
    private AdminUserService adminUserService;

    public String execute() {
        String result = adminUserService.findAdministrator(adminer);
        if (!"success".equals(result)) { /* 錯誤提示 */ return "login"; }
        ActionContext.getContext().getSession().put("adminUser", adminer);
        return result;
    }

    public String quitUser() {
        ActionContext.getContext().getSession().clear();
        return "success";
    }
    // getter/setter 省略
}

根因深度剖析

  1. checkUserAction 為 prototype,每次請求創建新實例 ✓
  2. 但其屬性 adminer(Administrator)引用的是 **單例 Bean** administrator ✗
  3. 首次登錄成功時,表單數據被模型驅動注入到這個**共享的單例 adminer** 中
  4. 註銷僅清空 Session,**未清理單例 adminer 內的殘留數據**
  5. 後續直接訪問 /checkUser,Struts 再次創建新 Action,注入同一個「髒數據」adminer,驗證直接通過

驗證證據

  • 使用 <s:debug/> 查看值棧:每次請求後 Session 中 adminUser 不變
  • 抓包確認:直接訪問 Action 時無表單數據提交
  • 模型驅動源碼:僅在 Action 執行**前**將表單數據壓入值棧,執行後不清理

修復方案

將 Administrator 亦改為 prototype 作用域,確保每次請求獲得全新實例:

<bean id="administrator" class="pojo.Administrator" scope="prototype" />

最佳實踐建議

  1. 模型驅動屬性必須與 Action 同生命周期:Action 是 prototype,模型也要是 prototype
  2. 避免在單例 Bean 中持有請求級狀態:線程安全、數據隔離雙重風險
  3. 攔截器做二次校驗:在攔截器中檢查 Session 是否存在有效用戶,而非單靠 Action 邏輯
  4. 註銷時清理模型對象:ModelDriven 接口無生命周期回調,需手動置空或改用參數注入
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved