Skip to content

Latest commit

Β 

History

History
95 lines (74 loc) Β· 3.35 KB

File metadata and controls

95 lines (74 loc) Β· 3.35 KB

JAVAμ—μ„œμ˜ μ•ˆμ „ν•˜μ§€ μ•Šμ€ μ½”λ“œ

😒 μ™ΈλΆ€ μž…λ ₯이 μΏ ν‚€ 유효 κΈ°κ°„ 섀정에 κ·ΈλŒ€λ‘œ μ‚¬μš©λ¨

javax.servlet.http.Cookie.setMaxAge λ©”μ†Œλ“œ ν˜ΈμΆœμ— μ™ΈλΆ€μ˜ μž…λ ₯이 μΏ ν‚€μ˜ 유효 μ‹œν•œ 섀정에 κ·ΈλŒ€λ‘œ μ‚¬μš©λ˜μ–΄ ν”„λ‘œκ·Έλž¨μ˜ 취약점이 μ•ΌκΈ°λœλ‹€.

public void makeCookie(ServletRequest request) {
    String maxAge = request.getParameter("maxAge");
    if (maxAge.matches("[0-9]+")) {
        String sessionID = request.getParameter("sessionID");
        if (sessionID.matches("[A-Z=0-9a-z]+")) {
            Cookie c = new Cookie("sessionID", sessionID);
            // μ™ΈλΆ€ μž…λ ₯이 μΏ ν‚€ μœ νš¨μ‹œν•œ 섀정에 κ·ΈλŒ€λ‘œ μ‚¬μš©λ¨!
            c.setMaxAge(Integer.parseInt(maxAge));
        }
    }
}

μ•ˆμ „ν•œ μ½”λ“œ

μ‚¬μš©μžκ°€ μš”μ²­ν•œ κ°’μœΌλ‘œ μΏ ν‚€μ˜ 유효 기간을 μ„€μ •ν•˜κΈ° 전에 μ‚¬μš©μž μš”μ²­μ„ κ²€μ¦ν•˜λŠ” λ‘œμ§μ„ μž‘μ„±ν•˜μ—¬ λ©”μ†Œλ“œ 호좜 전에 ν˜ΈμΆœν•œλ‹€.

public void makeCookie(ServletRequest request) {
    String maxAge = request.getParameter("maxAge");

    if (maxAge == null || "".equals(maxAge)) return;
    // λ¬΄κΈ°ν•œμ˜ κΈ°ν•œ μ„€μ • 방지
    if (maxAge.matches("[0-9]+")) {
        String sessionID = request.getParameter("sessionID");
        if (maxAge == null || "".equals(maxAge)) return;
        // λ¬΄κΈ°ν•œ κΈ°ν•œ μ„€μ • 방지
        if (sessionID.matches("[A-Z=0-9a-z]+")) {
            Cookie c = new Cookie("sessionID", sessionID);
            int t = Integer.parseInt(maxAge);
            if (t > 3600) { t = 3600; }
            // 3600초 μ΄ˆκ³Όν•˜λ©΄ 3600초둜 μ„€μ •
            c.setMaxAge(t);
        }
    }
}

μœ„ μ½”λ“œμ—μ„œλŠ” μ•žμ„  μ½”λ“œμ™€ 달리 1. λ¬΄κΈ°ν•œμΌ κ²½μš°μ—λŠ” κ·Έλƒ₯ return을 ν•΄ μ€€λ‹€κ±°λ‚˜, 2. 일정 κΈ°κ°„ 이상(μœ„ μ½”λ“œμ—μ„œλŠ” 3600초)일 κ²½μš°μ—λŠ” μžμ—°μŠ€λŸ½κ²Œ μ‚¬μš©μž 지정 μ΅œλŒ“κ°’μœΌλ‘œ λ°”κΎΈμ–΄ μ£Όλ©° 취약점을 μ œκ±°ν–ˆλ‹€.


😒 μΏ ν‚€ 유효 μ‹œκ°„ 섀정이 μƒμˆ«κ°’μ΄ 됨

javax.servlet.http.Cookie.setMaxAge λ©”μ†Œλ“œ ν˜ΈμΆœμ— μΏ ν‚€μ˜ 유효 κΈ°κ°„ 섀정을 μƒμˆ«κ°’μœΌλ‘œ μ‚¬μš©ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ˜ 취약점을 야기함.

...
Cookie idCookie = new Cookie("id", userId);
Cookie passwordCookie = new Cookie("password", password);

idCookie.setMaxAge(60*60); // λ„‰λ„‰ν•˜κ²Œ μΏ ν‚€ 지속 μ‹œκ°„ μ„€μ •
passwordCookie.setMaxAge(60*60);
...

μ•ˆμ „ν•œ μ½”λ“œ

setMaxAge값을 음수둜 μ„€μ •ν•˜λ©΄ λΈŒλΌμš°μ €κ°€ λ–  μžˆλŠ” λ™μ•ˆμ—λ§Œ μž‘λ™ν•œλ‹€. 이λ₯Ό μ΄μš©ν•˜μ—¬, λ‘œκ·Έμ•„μ›ƒ μ΄μ™Έμ˜ μ–΄λ–€ 행동을 해도 음수둜 μ„€μ •λ˜κ²Œ ν•˜μ˜€λ‹€. λ‘œκ·Έμ•„μ›ƒ μ‹œμ—λŠ” μ¦‰μ‹œ μΏ ν‚€κ°€ μ‚­μ œλœλ‹€.

...
if (command.equals(LOGIN_CMD)) {
    ...
    Cookie idCookie = new Cookie("id", userId);
    Cookie passwordCookie = new Cookie("password", password);

    idCookie.setMaxAge(-60 * 2); // λ„‰λ„‰ν•˜κ²Œ μΏ ν‚€ 지속 μ‹œκ°„ μ„€μ •
    passwordCookie.setMaxAge(-60 * 2);
}

...

if (command.equals(LOGOUT_CMD)) {
    ...
    idCookie.setMaxAge(0); // λ‘œκ·Έμ•„μ›ƒ μ‹œ μΏ ν‚€ λ°”λ‘œ μ‚­μ œ
    passwordCookie.setMaxAge(0);
}

...

if (command.equals(OTHER_ACTION_CMD)) {
    ...
    idCookie.setMaxAge(-60 * 2); // μ‚¬μš©μžκ°€ 계속 μ‚¬μš©ν•΄μ•Όλ§Œ μΏ ν‚€ 갱신됨
    passwordCookie.setMaxAge(-60 * 2);
}