Back

Zip Slip

๐Ÿ” Introduction

ZIP Slip์€ Path traversal(directory traversal) ๊ตฌ๋ฌธ์ด ํฌํ•จ๋œ Archive ํŒŒ์ผ(zip, tar, jar, etc..)์„ extractํ•  ๋–„ ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ณต๊ฒฉ์ž๊ฐ€ ์˜๋„ํ•œ ๊ฒฝ๋กœ๋กœ ์›ํ•˜๋Š” ํŒŒ์ผ์„ ์ด๋™์‹œํ‚ค๋Š” ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ Unarchive ๊ด€๋ จํ•ด์„œ ์•ˆ์ „ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋‹ค๋ฉด ํฌ๊ฒŒ ์˜ํ–ฅ๋ฐ›์ง€ ์•Š์ง€๋งŒ, ์ผ๋ถ€ ์–ธ์–ด๋Š” ์ด๋Ÿฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ถ€์žฌ๋กœ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ž‘์„ฑํ•œ Code snippet ์œผ๋กœ extract ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฌํ•œ ๊ณต๊ฒฉ์— ๋Œ€ํ•œ ๋Œ€์‘์ด ์ฝ”๋“œ์ธ ๊ฒฝ์šฐ ๊ณต๊ฒฉ์ž๊ฐ€ ์‰ฝ๊ฒŒ ์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ ๋“ฑ์œผ๋กœ ์›ํ•˜๋Š” ํŒŒ์ผ์„ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

e.g

โ”œโ”€โ”€ dir1
โ”‚ย ย  โ”œโ”€โ”€ file1.txt
โ”‚ย ย  โ”œโ”€โ”€ file2.txt
โ”œโ”€โ”€ ../../../../../../evil.sh

์–ด๋–ป๊ฒŒ ๋ณด๋ฉด OOXML XXE์™€ ์œ ์‚ฌํ•œ ๋ถ€๋ถ„๋„ ์žˆ๋„ค์š”.

๐Ÿ—ก Offensive techniques

Detect

Archive๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋“  ๊ตฌ๊ฐ„์—์„œ๋Š” ํ…Œ์ŠคํŠธํ•ด๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠน์ • ์š”์ฒญ ๋“ฑ์„ ์ด์šฉํ•ด ์„œ๋น„์Šค์— ์••์ถ• ํŒŒ์ผ ํ˜•ํƒœ๋กœ ์—…๋กœ๋“œํ•˜์—ฌ ์ฒ˜๋ฆฌ๋˜๊ฑฐ๋‚˜, ๋‹ค๋ฅธ ํŒŒ๋ผ๋ฏธํ„ฐ ์ •๋ณด๋“ค์ด ์กฐํ•ฉ๋˜์„œ ZIP๊ณผ ๊ฐ™์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๊ฒฝ์šฐ ์œ ํšจํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ์‰ฝ๊ฒŒ ์‹๋ณ„ํ•˜๊ธฐ ์ดํ•ด์„œ๋Š” Path traversal๊ณผ ๊ฐ™์ด ๋‹จ์ˆœํ•œ ๊ฒฝ๋กœ๋ฅผ ์šฐ์„  ์ง€์ •ํ•˜์—ฌ extract ๋˜๋Š”์ง€ ์ฒดํฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

ZIP

./normal.jpg
../inject.jpg
../ZIP_NAME/inject2.jpg

Check

/normal.jpg (200)
/inject.jpg (404)
/inject2.jpg (200) => ์ทจ์•ฝ

Exploitation

์‹ค์ œ ๊ณต๊ฒฉ์€ ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด์„œ ์‹œ์Šคํ…œ์˜ ์ค‘์š” ํŒŒ์ผ์„ ๋ฎ์–ด์“ฐ๊ฑฐ๋‚˜, ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ๋กœ ํŒŒ์ผ์„ ์ด๋™์‹œ์ผœ RCE๋ฅผ ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

../../../../../../../../tmp/evil.sh

๋ฌผ๋ก  ์ด ๊ฒฝ์šฐ ์‹คํ–‰ ๊ถŒํ•œ์ด ์žˆ๋Š” ๋””๋ ‰ํ† ๋ฆฌ๋ฅด ์ •ํ™•ํ•˜๊ฒŒ ์•Œ์•„์•ผํ•˜๊ณ , ์–ด๋–ค ์กฐ๊ฑด์œผ๋กœ ์ธํ•ด ์‹คํ–‰์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด์™ธ์—๋„ ๋‹ค๋ฅธ ์ทจ์•ฝ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ๋Š” ๋ธŒ๋ฆฟ์ง€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Bypass protection

์ ‘๊ทผ ๊ฒฝ๋กœ์— ๋Œ€ํ•ด ๊ถŒํ•œ ๊ธฐ๋ฐ˜์œผ๋กœ Limit์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ์šฐํšŒํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ Path traversal๊ณผ ๋™์ผํ•˜๊ฒŒ ๋ฌธ์ž์—ด ๊ธฐ๋ฐ˜์œผ๋กœ ์ฒดํฌํ•˜๋Š” ๋กœ์ง์ธ ๊ฒฝ์šฐ Path traversal์˜ bypass ํŒจํ„ด์„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

https://www.hahwul.com/cullinan/path-traversal/#bypass-protection

๐Ÿ›ก Defensive techniques

Extract ์‹œ path๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋Œ€์‘์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ extract ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์˜ ๊ถŒํ•œ์„ ์ด์šฉํ•ด์„œ ์ตœ๋Œ€ writeํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„๋ฅผ ๋ช…์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋„ ๊ณต๊ฒฉ์„ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Example

golang ์ฝ”๋“œ๋กœ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Vuln code

func (rarFormat) Read(input io.Reader, dest string) {
  rr := rardecode.NewReader(input, "")
  for {
    header := rr.Next()
    writeNewFile(filepath.Join(dest, header.Name), rr, header.Mode())
  }
}

Validation code

func sanitizeExtractPath(filePath string, destination string) error {
 destpath := filepath.Join(destination, filePath)
 if !strings.HasPrefix(destpath, filepath.Clean(destination) + string(os.PathSeparator)) {
   return fmt.Errorf("%s: illegal file path", filePath)
  }
  return nil
}

๐Ÿ•น Tools

๐Ÿ“Œ References

Licensed under CC BY-NC-SA 4.0