XSS 실습 환경 구축 방법 정리(docker + selenium)
http://cifrar.cju.ac.kr:25577
완성된 문제 사이트
우암 콜센터
cifrar.cju.ac.kr:25577
개요
이걸 왜 만들게 됐냐면 동아리에서 웹 해킹 강의를 해줘야 해서 충북 고교 해킹 캠프도 있었고 이때까지 만든 내용을 정리하고자 새롭게 만들어보았다.
목표는 셀레니움을 써서 직접 어드민 봇을 내부적으로 구현하는 것, 그리고 가장 간단한 XSS 실습 템플릿을 만들어서 계속 필터링을 강화하는 식으로 심화 문제를 양산하기 위해서이다.
우선 전체적인 프로젝트 구조는 다음과 같다.
이게 윈도우에서는 그냥 만들면 돼서 별 문제가 없었다. 문제는 이걸 리눅스 Ubuntu Server에서 돌려야 한다는 골 때리는 상황이다.
워게임은 24시간 접속 가능해야 하기 때문에.. 집에 있는 데스크톱으로 24시간 열어놓을 수는 없다.
기초적인 로그인/회원가입/글 작성/ 댓글 작성 기능을 가진 사이트를 만들고 각 게시글에 관리자 호출 이라는 버튼을 넣어서 해당 버튼을 누르면 어드민 봇이 자신의 브라우저 쿠키에 플래그를 넣고 해당 게시글을 읽는다. 그럼 그 게시글에 악성 스크립트에 의해 어드민 봇이 가지고 있는 쿠키를 제삼자의 c2로 보낼 수 있는 것이 XSS의 핵심이다.
여기서 내부망의 IP를 알고, 해당 IP로만 접근 가능한 내부 사이트가 존재한다면 SSRF를 통해 해당 내부망 데이터를 탈취 할 수도 있다.
출처 : https://beaglesecurity.com/blog/article/server-side-request-forgery-attack.html
대충 이런 형식이다.
그럼 이 개념을 공부하기 위한 사이트를 어떻게 만드냐
리눅스에서 셀레니움 쓰기
일단 24시간 안정적인 운영을 위해 도커를 쓸 예정인데, 셀레니움을 쓰기 위해서는 google-chrome이라는 라이브러리와 chromedriver라고 하는 라이브러리 2개가 모두 같은 버전으로 깔려 있어야 한다.
내가 리눅스 서버에서 크롬으로 웹 서핑을 할 리는 없으니까 사실 아무버전이나 깔아도 되는데, 114인가 그 이후로는 연결하는 방식이 달라졌다. 그래서 삽질 끝에 그냥 낮은 버전의 드라이버를 직접 찾아 다운로드하는 방식으로 Dockerfile을 구성했다.
# Python 3.9 슬림 버전 이미지를 기반으로 사용
FROM python:3.9-slim
# 필수 패키지 설치
RUN apt-get update && apt-get install -y \
wget \
unzip \
gnupg \
curl \
libxss1 \
libappindicator1 \
libgconf-2-4 \
fonts-liberation \
libasound2 \
libnspr4 \
libnss3 \
libx11-xcb1 \
libxtst6 \
lsb-release \
xdg-utils \
libgbm1 \
libnss3 \
libatk-bridge2.0-0 \
libgtk-3-0 \
libx11-xcb1 \
libxcb-dri3-0 \
libappindicator3-1 \
libgdk-pixbuf2.0-0 \
&& apt-get clean
# 구글 크롬 80.0.3987.106 버전 다운로드 및 설치
RUN wget https://mirror.cs.uchicago.edu/google-chrome/pool/main/g/google-chrome-stable/google-chrome-stable_80.0.3987.106-1_amd64.deb && \
dpkg -i google-chrome-stable_80.0.3987.106-1_amd64.deb && \
apt-get install -f && \
rm google-chrome-stable_80.0.3987.106-1_amd64.deb
# 크로미움 드라이버 80.0.3987.106 버전 다운로드 및 설치
RUN wget https://chromedriver.storage.googleapis.com/80.0.3987.106/chromedriver_linux64.zip && \
unzip chromedriver_linux64.zip && \
mv chromedriver /usr/local/bin/ && \
rm chromedriver_linux64.zip
# 애플리케이션 추가
WORKDIR /app
COPY . .
# Python 패키지 설치
RUN pip install --no-cache-dir -r /app/requirements.txt
# Flask 애플리케이션 실행
CMD ["python", "app.py"]
이러면 이제 docker 안에서 셀레니움을 자유롭게 쓸 수 있다.
이렇게 만들면 끝인줄 알았는데 좀 더 설정을 해줘야 한다.
alert() 처리
xss의 기본인 <script>alert(1)</script>이런 페이로드를 테스트 삼아 많이 넣어보긴 하는데, 셀레니움은 이걸 따로 처리를 안 해주면 에러가 난다.
# Alert 처리
try:
alert = driver.switch_to.alert
alert.accept()
except NoAlertPresentException:
print("Alert이 없습니다.")
이렇게 alert이 뜨면 확인을 눌러주는 코드도 추가해야 한다.
headless 모드
그리고 우분투 서버는 기본적으로 GUI가 없기 때문에, 기본옵션들을 비활성화 해줘야 한다.
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
# 크롬 드라이버 경로 설정
driver_path = '/usr/bin/chromedriver'
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=options)
app.logger.info("드라이버가 연결되었습니다.")
이렇게 해주지 않으면 역시 작동하지 않는다.
페이지 랜더링 대기
# 페이지 로드 완료까지 대기
WebDriverWait(driver, 10).until(
lambda driver: driver.execute_script("return document.readyState") == "complete"
)
app.logger.info("로그인 페이지 로드 완료")
그리고 웹 요청과 실제 크롬 브라우저에 랜더링 되는 시간의 차이가 존재하기 때문에 내부의 DOM이 로딩 되지 않고 다음 페이지로 넘어가는 문제가 있다. 그래서 저렇게 로딩 상태가 complete가 될 때까지 대기하는 로직을 추가해야 한다.
우암던전 시리즈 문제 파일 저장소 : https://github.com/Seo-Faper/hackingcamp
GitHub - Seo-Faper/hackingcamp
Contribute to Seo-Faper/hackingcamp development by creating an account on GitHub.
github.com