스포츠활동 ㅌㅌ머니 인센티브 자동 출석체크 어플

국민체력100 (KSPO) 웹사이트 API 분석 보고서

분석 대상: https://nfa.kspo.or.kr

분석 목적: 튼튼머니 스포츠활동 인증(출석체크) 프로세스 역공학

1. 사이트 개요

국민체력100은 대한민국 국민체육진흥공단(KSPO)이 운영하는 국민 체력 관리 플랫폼입니다.

"튼튼머니"는 체육시설 방문 시 QR 코드를 스캔하여 출석체크하면 포인트가 적립되는 인센티브 프로그램입니다.

1.1 서비스 흐름 (공식)

사용자 → 체육시설 방문 → QR 코드 스캔 → 로그인 → 출석체크(포인트 적립) ↓ (30분 이상 운동 후) 퇴장 시 QR 재스캔 → 2차 인증

1.2 발견된 핵심 URL 구조

구분

URL

메소드

설명

로그인 페이지

/member/login/memberLogin.kspo

GET

CSRF 토큰(csSignature) 발급

로그인 API

/member/login/memberLoginActJs.kspo

POST

AJAX 로그인 + 출석체크

포인트 확인

/spoint/isNotPointsAccumulationPeriodJs.kspo

POST

인센티브 적립 기간 확인

2. 인증 프로세스 상세 분석

2.1 Step 1: 로그인 페이지 접근 (CSRF 토큰 취득)

요청:

GET https://nfa.kspo.or.kr/member/login/memberLogin.kspo ?standGrpCd=04 &refTb=SPORTS_FACILITY_VISIT &spoFaciSn={시설번호}

핵심 파라미터:

파라미터

설명

standGrpCd

04

표준그룹코드 (고정값)

refTb

SPORTS_FACILITY_VISIT

참조테이블 (스포츠시설 방문)

spoFaciSn

정수

스포츠시설 일련번호 (핵심 식별자)

응답에서 추출:

<input type="hidden" name="csSignature" value="XXXXXXXXXX...">
  • csSignature: CSRF 방지 토큰, 세션마다 새로 발급

  • 유효시간: 약 5~10분 (세션 의존)

2.2 Step 2: AJAX 로그인 (출석체크 실행)

요청:

POST https://nfa.kspo.or.kr/member/login/memberLoginActJs.kspo Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Referer: https://nfa.kspo.or.kr/member/login/memberLogin.kspo?standGrpCd=04&refTb=SPORTS_FACILITY_VISIT&spoFaciSn={시설번호}

POST Body:

membId={사용자ID} &membPwd={비밀번호} &csSignature={CSRF토큰} &returnUrl=

2.3 Step 3: 응답 코드 분석

응답 형식 (JSON):

{ "msgCd": "INF_LOGIN_103", "msgNm": "스포츠활동 인증 후 인센티브 적립 완료!", "returnUrl": "" }

발견된 응답 코드 전체 목록:

코드

분류

의미

동작

INF_LOGIN_101

✅ 성공

정상 로그인 완료

세션 생성

INF_LOGIN_103

✅ 성공

스포츠활동 인증 + 인센티브 적립

포인트 적립됨

INF_COMM_103

✅ 성공

정상 적립 완료

포인트 적립됨

ERR_LOGIN_117

❌ 실패

ID/PW 불일치

재시도 필요

ERR_LOGIN_104

🔒 잠금

비밀번호 5회 오류

비밀번호 찾기 필요

ERR_LOGIN_107

💤 휴면

휴면계정

계정 복구 필요

ERR_LOGIN_108

🔄 통합

회원 통합 필요

사이트에서 처리

ERR_LOGIN_109

⚠️ 초과

주 1회 초과 참여

다음 주까지 대기

ERR_SPOINT_105

ℹ️ 안내

스포츠활동 인증 안내

정보 메시지

ERR_SPOINT_107

🏢 시설오류

적립 불가 시설

spoFaciSn 확인

ERR_SPOINT_110

✅ 완료

오늘 이미 체크인 완료

중복 방지

ERR_SPOINT_111

🚫 종료

인센티브 사업 종료

서비스 종료

3. QR 코드 분석

3.1 QR 코드 URL 구조

https://nfa.kspo.or.kr/member/login/memberLogin.kspo ?standGrpCd=04 &refTb=SPORTS_FACILITY_VISIT &spoFaciSn=

3.2 핵심 발견

  1. QR 코드 = 로그인 URL: QR은 단순히 spoFaciSn이 포함된 로그인 페이지 URL

  2. 시설 식별: spoFaciSn 파라미터가 유일한 시설 식별자

  3. 2단계 프로세스: QR 문서에는 "30분 이상 운동 후 퇴장 시 QR 재스캔" 명시

  • 1차: 입장 시 QR 스캔 → 출석체크

  • 2차: 30분 후 퇴장 시 QR 재스캔 → 포인트 확정

3.3 spoFaciSn 구조

  • 형식: 1~4자리 정수 (1 ~ 9999+)

  • 유효한 번호: 약 2,446개 (전수 조사 결과)

  • 번호와 시설의 관계: 1:1 매핑 (하나의 번호 = 하나의 시설)

  • 조회 불가: 공개 API로 spoFaciSn → 시설명 역조회 불가능

4. 보안 분석

4.1 적용된 보안 메커니즘

보안 기능

구현 방식

우회 가능성

CSRF 방지

csSignature 토큰

매 요청 시 새로 취득하면 우회

세션 관리

JSESSIONID 쿠키

쿠키 유지로 관리

AJAX 검증

X-Requested-With 헤더

헤더 추가로 우회

Referer 검증

Referer 헤더 체크

올바른 Referer 설정으로 우회

중복 방지

ERR_SPOINT_110 응답

서버 측 1일 1회 제한

주 1회 제한

ERR_LOGIN_109 응답

서버 측 제한, 우회 불가


5. 시설 데이터 분석

5.1 데이터 수집 결과

전국 체육시설 데이터를 크롤링하여 수집한 결과:

  • 총 시설 수: 약 2,446개

  • 데이터 필드: 시설명(nm), 주소(addr), 시도(sd), 시군구(sgg), 전화번호(tel), 등록번호(sn)

  • 지역 분포: 전국 17개 시·도

5.2 spoFaciSn vs 등록번호

주의: 시설 검색 API에서 반환되는 sn(등록번호)과 QR 코드의 spoFaciSn은 다른 번호 체계입니다.

구분

spoFaciSn

등록번호(sn)

출처

QR 코드 URL

시설 검색 API

용도

출석체크 식별

시설 관리 식별

매핑

역조회 불가

공개 조회 가능

6. API 호출 시퀀스 다이어그램

클라이언트 KSPO 서버 │ │ │── GET /memberLogin.kspo ──────────────>│ │ ?spoFaciSn= │ │<── HTML (csSignature 포함) ────────────│ │ │ │── POST /memberLoginActJs.kspo ────────>│ │ membId, membPwd, csSignature │ │ Referer: ...spoFaciSn= │ │<── JSON { msgCd, msgNm } ─────────────│ │ │ │ ┌─ [30분 대기] ──────────┐ │ │ │ │ │── GET /memberLogin.kspo ──>│──────────>│ │ (새 csSignature 취득) │ │ │<── HTML ───────────────────│──────────│ │ │ │ │── POST /memberLoginActJs ──│──────────>│ │ (2차 출석체크) │ │ │<── JSON { msgCd } ────────│──────────│ └────────────────────────────┘ │

7. 전수 탐색 (Brute-Force) 분석

7.1 방법론

사용자가 시설의 spoFaciSn을 모를 때, 유효한 번호 목록(2,446개)을 모두 시도하여 찾는 방식:

1. csSignature 1회 취득

2. 각 spoFaciSn에 대해 로그인 POST 요청

3. 응답 코드로 시설 판별:

- INF_LOGIN_103/INF_COMM_103 → 적립 성공 = 올바른 시설!

- ERR_SPOINT_110 → 이미 체크인 완료 (구분 불가)

- ERR_SPOINT_107 → 잘못된 시설

7.2 성능 최적화

최적화 기법

효과

csSignature 1회 취득 재사용

GET 요청 2,445개 절약

병렬 배치 처리 (5~20개 동시)

속도 5~20배 향상

발견 즉시 중단

불필요한 요청 차단

csSignature 만료 자동 갱신

연속 에러 방지

예상 소요 시간: 약 3~10분 (네트워크 상태 및 동시 요청 수에 따라 다름)

8. 기술적 제약사항

  1. csSignature 만료: 약 5~10분 후 만료, 갱신 필요

  2. 세션 관리: JSESSIONID 쿠키 유지 필수

  3. 동일 세션 제한: 같은 세션에서 반복 로그인 시 일부 요청 실패 가능

  4. HTTPS 필수: HTTP → HTTPS 리다이렉트 적용

  5. 모바일 User-Agent: 모바일 UA 설정 시 안정적 응답

9. 법적 고지

⚠️ 이 분석은 교육 및 연구 목적으로만 작성되었습니다.

  • 자동 출석체크는 서비스 이용약관에 위반될 수 있습니다.

  • 실제 시설을 방문하지 않고 사용하는 것은 부정 사용에 해당할 수 있습니다.

  • 이 문서의 정보를 사용하여 발생하는 결과에 대해 작성자는 책임지지 않습니다.

이것은 실제로 적용이 되는 곳입니다.

어쨰서인지 빨리 달는 이유가 이거임 ㅋㅋ

======================================================================

튼튼머니 적립시설 목록

수집:

총 3,186개

======================================================================

──────────────────────────────────────────────────

[] 1개

──────────────────────────────────────────────────

[강원] 63개

──────────────────────────────────────────────────

[경기] 798개

──────────────────────────────────────────────────

[경남] 198개

──────────────────────────────────────────────────

[경북] 81개

──────────────────────────────────────────────────

[광주] 103개

──────────────────────────────────────────────────

[대구] 105개

──────────────────────────────────────────────────

[대전] 103개

──────────────────────────────────────────────────

[부산] 221개

──────────────────────────────────────────────────

[서울] 961개

──────────────────────────────────────────────────

[세종] 31개

──────────────────────────────────────────────────

[울산] 56개

──────────────────────────────────────────────────

[인천] 148개

──────────────────────────────────────────────────

[전남] 60개

──────────────────────────────────────────────────

[전북] 69개

──────────────────────────────────────────────────

[제주] 24개

──────────────────────────────────────────────────

[충남] 92개

──────────────────────────────────────────────────

[충북] 72개

재신청 및 세부적인 이유 리스트들 극히일부

QR유출 재신청 시설 우선승인

QR유출 재신청 우선승인"

QR유출 재신청 우선승인"

QR코드 유출 시설 재신청 우선승인"

QR코드 유출 정지시설 재신청 우선승인"

적립시설 신규승인(25.12.10)

전남지역 우선승인"

적립시설 신규승인(25.12.09)

적립시설 승인(6/13)

경북지역 우선승인"

제주지역 우선승인"

조회결과 카카오톡채널로 모집신청 받고있으며 수영프로그램 운영중 신규시설승인(26.3.25)"

사업자등록증 확인 및 대표자 오타 수정 ()"

해당 주소지로 인터넷 검색 결과 실외골프연습장 정상 운영 확인 및

적립시설 신규승인(26.03.25)"

(2547) 사업자등록번호 휴폐업 조회 결과 폐업시설 확인

(6636) 사업자등록증 확인 및 적립시설 신규승인(26.03.25)"

파트너스시설 재승인(25.11.24)"

대충 구조는 이럼

https://pixeldrain.com/u/3zV2YL1s

사실 이거 만들고 피드백하고 리버싱하느라 글좀못썻음

다음꺼는 알리코인 자동 출책을 만들생각인데

이게 좀 상당히 어렵네요


원본: 네이버 블로그

댓글