6 min read

IRIS 비밀번호 오류로 인해 로그인이 안 될 때

IRIS가 준 임시비번에 특수문자가 없어서 정작 IRIS 로그인이 안 됐다. 프론트 검사 건너뛰고 세션 쿠키 받아서 브라우저에 직접 넣기까지.
IRIS 비밀번호 오류로 인해 로그인이 안 될 때

IRIS 비밀번호를 까먹었다. 비번 찾기 눌러서 임시비밀번호를 받았는데, 이걸로 로그인이 안 된다. 임시비번을 만들어준 게 IRIS 본인인데 정작 그 비번이 IRIS 로그인 규칙에 안 맞는 상황. 하도 어이가 없어서 좀 파봤고, 결국 파이썬으로 우회해서 들어갔다. 그 삽질 기록이다.

일단 비번을 까먹었다

비번 찾기로 임시비밀번호를 발급받았다. 메일로 온 임시비번을 그대로 쳤는데 로그인 버튼이 안 먹는다. 뭐가 문제인가 콘솔 열어보니 이게 떠 있었다.

"비밀번호는 영문·숫자·특수문자를 모두 포함해야 합니다."

웃긴 게, 그 임시비번을 뱉은 게 IRIS인데 정작 거기엔 특수문자가 없다. 즉 자기가 준 비번이 자기 로그인 검사를 통과 못 한다. 서버는 그 비번 받아줄 준비가 돼 있는데 프론트 자바스크립트가 폼 제출 자체를 막는 거다. 비번 바꾸려면 로그인부터 돼야 하는데, 그 로그인이 안 된다. 도돌이표.

그래서 방법은 하나였다. 특수문자 검사가 사는 곳(브라우저)을 그냥 건너뛰고 서버한테 직접 로그인 요청을 던지는 것.

로그인 요청부터 구경

서버한테 뭘 보내야 하는지 알아야 하니까, 개발자도구 Network 탭 켜고 login.do 요청을 봤다. 페이로드에서 눈에 띈 건 이 정도.

  • _csrf — 메인 페이지 HTML에 hidden으로 박혀 오는 토큰. 세션이랑 짝이다.
  • password — 평문이 아니라 base64로 감싸서 보낸다. 암호화는 아니고 그냥 인코딩.
  • kstTime, browser, device — 시간이랑 브라우저/OS 같은 로그 찍는 용도 필드들.

결국 /login.do에 폼 데이터 POST 한 방이 전부고, 특수문자 규칙은 프론트에만 있었다. 그럼 브라우저 빼고 똑같이 보내면 되잖아.

그럼 직접 보내자

파이썬 기본 라이브러리면 충분하다. 순서도 별거 없다. main.do 한번 긁어서 세션 쿠키랑 _csrf 챙기고, 비번을 base64로 바꿔서 login.do에 POST. 끝.

#!/usr/bin/env python3
import base64, re, sys, json, datetime, urllib.request, urllib.parse, http.cookiejar

USERNAME = "YOUR_ID"            # 본인 아이디
PASSWORD = "YOUR_PASSWORD"      # 메일로 받은 임시비밀번호 (특수문자 없음)
BASE     = "https://www.iris.go.kr"
UA = ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
      "(KHTML, like Gecko) Chrome/126.0 Safari/537.36")

jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
opener.addheaders = [("User-Agent", UA)]

def get(url):
    return opener.open(urllib.request.Request(url), timeout=30).read().decode("utf-8", "replace")

# 1) 메인 페이지에서 세션 쿠키 + _csrf 토큰 받기
html = get(BASE + "/main.do")
m = re.search(r'name="_csrf"\s+value="([^"]+)"', html)
if not m:
    sys.exit("CSRF 토큰을 못 찾음")
csrf = m.group(1)

# 2) 로그인 POST (비번은 프론트랑 똑같이 base64)
now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
form = {
    "_csrf": csrf, "referer": "", "tempYn": "N", "moveUrl": "",
    "username": USERNAME,
    "password": base64.b64encode(PASSWORD.encode()).decode(),
    "browser": "Google Chrome", "device": "Linux",
    "kstTime": now.strftime("%Y. %m. %d. %H:%M:%S"), "country": "",
}
data = urllib.parse.urlencode(form).encode()
req = urllib.request.Request(BASE + "/login.do", data=data, method="POST")
req.add_header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.add_header("Referer", BASE + "/main.do")
req.add_header("X-Requested-With", "XMLHttpRequest")
resp = opener.open(req, timeout=30)

# 3) 쌓인 세션 쿠키 뱉기
cookies = {c.name: c.value for c in jar}
print("; ".join(f"{k}={v}" for k, v in cookies.items()))

볼 건 두 줄이다. 비번을 base64.b64encode로 감싸서 프론트랑 형식 맞추는 거, 그리고 CookieJarmain.do에서 받은 세션 쿠키를 알아서 다음 login.do 요청에 붙여주는 거. 특수문자 검사하던 자바스크립트는 이 경로엔 애초에 없다.

쿠키

돌리면 로그인되고 세션 쿠키가 그냥 찍혀 나온다. 이거 통째로 curl에 물리면 로그인된 페이지도 그대로 긁힌다.

스크립트 돌린 결과. 세션 쿠키가 그대로 나온다 (값은 예시).
스크립트 돌린 결과. 세션 쿠키가 그대로 나온다 (값은 예시).

근데 난 페이지 긁으려던 게 아니었다. 그냥 평소 쓰던 크롬에서 로그인된 채로 들어가서 비번을 제대로 바꾸고 싶었을 뿐이다. 그래서 이 쿠키를 브라우저에 직접 넣기로 했다.

이 쿠키를 그냥 쓰던 크롬에 넣기

쿠키만 있으면 브라우저한테 "나 이미 로그인함"이라고 뻥칠 수 있다. 크롬 개발자도구로 직접 넣어보자. 파이어폭스도 Storage 탭에서 거의 똑같다.

1. iris.go.kr 켜고 F12

https://www.iris.go.kr 들어가서 F12 누르고 위쪽 Application 탭으로 간다. 쿠키는 그 사이트 페이지가 떠 있는 상태에서 넣어야 먹는다. 딴 페이지에서 넣으면 안 된다.

개발자도구 Application 탭 → Cookies. 지금 이 사이트가 가진 쿠키가 표로 뜬다.
개발자도구 Application 탭 → Cookies. 지금 이 사이트가 가진 쿠키가 표로 뜬다.

2. Cookies에서 도메인 고르기

왼쪽에서 Storage → Cookies → https://www.iris.go.kr 누르면 오른쪽에 쿠키가 쭉 뜬다. Name / Value / Domain / Path / Expires / HttpOnly / Secure 이런 열들. 여기서 값을 바꾼다.

3. Value 칸 더블클릭해서 갈아끼우기

JSESSIONID 줄의 Value 칸을 더블클릭하면 고칠 수 있다. 아까 스크립트가 뱉은 값으로 통째로 바꾸고 엔터. WMONID 같은 거 있으면 그것도 똑같이. 표에 그 쿠키가 아예 없으면 위에 눌러서 새로 만들고 Name·Value 채운 다음 Domain.iris.go.kr, Path/로 두면 대충 다 먹는다.

Value 칸 더블클릭 → 붙여넣기 → 엔터. Domain은 .iris.go.kr, Path는 / 로.
Value 칸 더블클릭 → 붙여넣기 → 엔터. Domain은 .iris.go.kr, Path는 / 로.

4. 새로고침

F5 누르면 방금 넣은 쿠키를 서버가 보고 "어 로그인 돼 있네" 하고 들여보내 준다. 이제 그냥 평소처럼 쓰면 된다.

JSESSIONID처럼 HttpOnly 붙은 쿠키는 콘솔에서 document.cookie로는 절대 안 들어간다. 안 먹힌다고 삽질하지 말고, 위처럼 개발자도구 Application 탭에서 직접 고쳐야 한다.