방문자가 하루 스무 명 남짓인 블로그입니다. 그런데 사용자 목록을 열어보니 가입자가 54만 명이었습니다.
정리하는 개발자 워니즈입니다. 이 글에서는 어쩌다 이렇게 됐는지와, 같은 상태인지 3분 안에 확인하는 방법을 다룹니다.
결론부터 말씀드리면 회원가입이 열려 있는지부터 확인하세요. 워드프레스는 설정 하나로 누구나 가입할 수 있게 되고, 그 상태를 몇 년씩 모르고 지나가는 경우가 많습니다.

왜 이게 문제인가
가입한 계정 대부분은 구독자 권한입니다. 글을 쓰지도, 설정을 바꾸지도 못합니다. 그래서 눈에 띄는 사고가 안 나고, 그게 오히려 문제를 오래 살려둡니다.
회원가입 설정은 워드프레스 공식 문서의 일반 설정 안내에도 한 줄로만 적혀 있어서, 켜져 있는지조차 모르고 지나가기 쉽습니다.
문제는 세 가지입니다. 첫째, 데이터베이스가 계속 부풀어 사용자 관련 조회가 느려집니다. 둘째, 로그인 화면과 가입 화면이 계속 두들겨 맞으면서 서버 자원을 씁니다. 셋째, 나중에 플러그인 취약점이 하나라도 생기면 이미 안에 들어와 있는 계정들이 발판이 됩니다.
1. 회원가입자 수를 3분 안에 세는 법
관리자 화면의 사용자 목록은 계정이 많으면 잘 열리지 않습니다. 저도 목록을 부르다가 사이트가 잠깐 먹통이 됐습니다. 숫자만 필요하다면 응답 헤더를 보는 편이 훨씬 가볍습니다.
curl -s -D- -o /dev/null -u '아이디:앱비밀번호' \
'https://example.com/wp-json/wp/v2/users?per_page=1&context=edit' \
| grep -i 'x-wp-total'
X-WP-Total 값이 전체 회원가입자 수입니다. 목록을 실제로 받아오지 않기 때문에 부하가 거의 없습니다.
이 방법을 쓰게 된 이유가 있습니다. 처음에는 명령줄 도구로 사용자 목록을 불렀는데, 54만 행을 읽느라 데이터베이스가 응답을 못 하면서 사이트가 1~2분간 먹통이 됐습니다. 작은 서버일수록 숫자만 필요할 때는 목록을 부르지 않는 편이 안전합니다.
2. 권한이 올라간 계정이 있는지 확인
숫자보다 먼저 볼 것은 권한입니다. 구독자만 잔뜩 있는 것과 관리자가 늘어난 것은 완전히 다른 상황입니다.
for r in administrator editor author contributor; do
echo -n "$r: "
curl -s -D- -o /dev/null -u '아이디:앱비밀번호' \
"https://example.com/wp-json/wp/v2/users?per_page=1&context=edit&roles=$r" \
| grep -i 'x-wp-total'
done
제 경우 결과가 이랬습니다.
| 권한 | 계정 수 |
|---|---|
| 관리자 | 2 |
| 편집자 | 0 |
| 작성자 | 2 |
| 기여자 | 0 |
| 구독자 | 545,374 |
관리자와 작성자는 예전부터 있던 계정이었고, 늘어난 건 전부 구독자였습니다. 권한 상승은 없었다는 뜻이라 그나마 다행이었습니다.
계정 이름에 규칙이 보이는 경우가 많습니다. 제 경우 특정 문자열 뒤에 숫자만 바뀌는 형태가 반복됐고, 가장 오래된 것이 3년 전이었습니다. 그때부터 계속 쌓이고 있었던 겁니다.
3. 회원가입을 막기 전에 확인할 것 하나
가입을 끄는 건 한 줄이지만, 끄기 전에 댓글 설정을 먼저 봐야 합니다.
wp option get comment_registration
이 값이 1이면 댓글을 쓰려면 로그인이 필요한 상태입니다. 이때 가입을 막으면 새 방문자가 댓글을 아예 못 답니다. 저는 0인 걸 확인하고 껐습니다.
wp option get users_can_register # 1 이면 열려 있음
wp option update users_can_register 0
관리자 화면에서는 설정 → 일반 → 누구나 등록할 수 있음 체크를 해제하면 됩니다.
끈 다음에는 실제로 막히는지 확인합니다.
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' \
'https://example.com/wp-login.php?action=register'
302와 함께 registration=disabled가 나오면 정상입니다. 저는 이 조치 뒤 반나절 동안 가입자 수가 한 명도 늘지 않은 것까지 확인했습니다.
4. 이미 쌓인 계정은 어떻게 할까
저는 아직 지우지 않았습니다. 54만 건을 한 번에 지우면 작은 서버는 버티지 못합니다. 지운다면 순서는 이렇습니다.
- 데이터베이스를 먼저 통째로 백업합니다. 이 단계는 건너뛰지 마세요.
- 남길 계정 ID를 먼저 확정합니다. 관리자와 작성자는 빼놓아야 합니다.
- 한 번에 다 지우지 말고 1,000건 단위로 나눠 돌립니다.
- 계정을 지운 뒤 남는 사용자 메타 데이터도 함께 정리합니다.
급하지 않다면 회원가입을 막아 더 늘지 않게 해두는 것만으로도 절반은 해결입니다. 이미 있는 계정은 권한이 없으면 당장 위험을 만들지 않습니다.
덧붙이자면 이 점검은 혼자 오지 않았습니다. 같은 날 코어 파일을 검증하다가 원본에 없어야 할 파일 하나도 함께 나왔습니다. 방치된 회원가입과 방치된 파일은 원인이 같습니다. 한 번도 안 들여다봤다는 것입니다.
회원가입 관련해 자주 묻는 것
Q. 가입을 막으면 댓글도 못 다나요?<br>댓글에 로그인을 요구하도록 설정한 경우에만 그렇습니다. 위 3번의 comment_registration 값을 먼저 확인하세요. 기본값은 로그인 없이 댓글이 가능한 상태입니다.
Q. 구독자 권한이면 위험하지 않은 것 아닌가요?<br>당장은 그렇습니다. 다만 로그인한 사용자만 접근할 수 있는 기능에 취약점이 생기면 이야기가 달라집니다. 담장 밖이 아니라 마당 안에 서 있는 상태라고 보시면 됩니다.
Q. 회원가입을 막으면 기존 계정은 어떻게 되나요?<br>그대로 남습니다. 새로 가입하는 경로만 닫히는 것이라 이미 있는 계정의 로그인이나 권한에는 영향이 없습니다.
Q. 언제부터 이렇게 됐는지 알 수 있나요?<br>사용자 목록을 가입일 오름차순으로 정렬해 가장 오래된 스팸 계정을 보면 대략 나옵니다. 저는 3년 전 특정 날짜부터 패턴이 시작돼 있었습니다.
정리
- 워드프레스는 설정 하나로 누구나 가입 가능한 상태가 되고, 티가 안 나서 오래 방치됩니다.
- 가입자 수는
X-WP-Total헤더로 3분이면 셉니다. 사용자 목록을 열지 마세요. - 숫자보다 권한별 분포를 먼저 보세요. 구독자만 늘었다면 침해는 아닙니다.
- 끄기 전에
comment_registration을 확인해 댓글이 막히지 않는지 봅니다. - 이미 쌓인 계정 삭제는 급하지 않습니다. 더 늘지 않게 막는 게 먼저입니다.
오늘 하나만 하신다면, 설정에서 누구나 등록할 수 있음이 켜져 있는지만 확인해 보세요.
함께 읽으면 좋은 글
- [블로그운영] 코어 파일 검증, 있으면 안 되는 파일이 하나 나왔습니다, 코어 파일 검증에서 없어야 할 파일이 나온 기록
- [블로그운영] 내부 링크 평균 3개, 그런데 글 45%가 고아였습니다, 내부 링크를 세어보니 45%가 고아였던 전수 조사
- [블로그운영] 제 블로그 글 절반 이상이 구글 색인에 없었습니다, 글 절반이 구글 색인에 없던 이야기