πŸ•ΉοΈ 6. 파일 μ—…λ‘œλ“œ

πŸ•ΉοΈ λͺ¨μ˜ν•΄ν‚Ή μ²΄ν—˜ 도전

πŸ•ΉοΈ λͺ¨μ˜ν•΄ν‚Ή μ²΄ν—˜ λ”°λΌν•˜κΈ° β–ΆSTEP_1) 'κΈ€μ“°κΈ°' λ²„νŠΌ 클릭

STEP_2) μž„μ˜μ˜ κ²Œμ‹œκΈ€ λ‚΄μš© μž‘μ„± 및 JSP μ›Ή μ‰˜ 파일 μ—…λ‘œλ“œ ν›„ 'κΈ€ μ—…λ‘œλ“œ' λ²„νŠΌ 클릭

STEP_3) νŒμ—… 창을 톡해 μ •μƒμ μœΌλ‘œ κ²Œμ‹œκΈ€ μ—…λ‘œλ“œ λ˜μ—ˆμŒμ„ 확인

STEP_4) μ—…λ‘œλ“œ 된 κ²Œμ‹œκΈ€ 쑰회

STEP_5) λΈŒλΌμš°μ € 개발자 도ꡬ(F12)λ₯Ό 톡해 μ²¨λΆ€λœ 파일의 URL 정보 확인

STEP_6) cmd νŒŒλΌλ―Έν„° 데이터 κ°’(λ¦¬λˆ…μŠ€ λͺ…λ Ήμ–΄ ls)을 ν¬ν•¨ν•˜μ—¬ νšλ“ν•œ URL μ •λ³΄λ‘œ μ ‘κ·Ό μ‹œλ„

STEP_7) μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜λŠ” 것을 확인

STEP_8) cmd νŒŒλΌλ―Έν„° 데이터 κ°’μœΌλ‘œ 'flag.txt' νŒŒμΌμ„ μ°ΎλŠ” λͺ…λ Ήμ–΄(find / -name flag.txt)λ₯Ό ν¬ν•¨ν•˜μ—¬ μš”μ²­ μ‹œ ν•΄λ‹Ή 파일의 μœ„μΉ˜ 정보 확인 κ°€λŠ₯

STEP_9) cmd νŒŒλΌλ―Έν„° 데이터 κ°’μœΌλ‘œ 'flag.txt' 파일 쑰회 λͺ…λ Ήμ–΄(cat /경둜/flag.txt)λ₯Ό ν¬ν•¨ν•˜μ—¬ μš”μ²­ μ‹œ FLAG κ°’ 확인 κ°€λŠ₯


O νŒŒμΌ μ—…λ‘œλ“œ κΈ°λŠ₯을 μ΄μš©ν•˜μ—¬ μ‹œμŠ€ν…œ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•  수 μžˆλŠ” μ„œλ²„ μ‚¬μ΄λ“œ 슀크립트 및 μ›Ή ν”„λ‘œκ·Έλž¨ λ“± μ•…μ˜μ μΈ νŒŒμΌμ„ μ—…λ‘œλ“œ ν•  수 μžˆλŠ” 취약점


O 근거 자료

☞ μ£Όμš”μ •λ³΄ν†΅μ‹ κΈ°λ°˜μ‹œμ„€ 기술적 취약점 뢄석 평가 상세 κ°€μ΄λ“œ(p.707)


O νŒλ‹¨ κΈ°μ€€

μ–‘ν˜Έμ—…λ‘œλ“œ λ˜λŠ” νŒŒμΌμ— λŒ€ν•œ ν™•μž₯자 검증이 μ΄λ£¨μ–΄μ§€λŠ” 경우
μ·¨μ•½μ—…λ‘œλ“œ λ˜λŠ” νŒŒμΌμ— λŒ€ν•œ ν™•μž₯자 검증이 이루어지지 μ•ŠλŠ” 경우


O 점검 방법

- 슀크립트 파일 (ASP, JSP, PHP, ASPX λ“±)μ—…λ‘œλ“œ μ‹œλ„

: μ‚¬μš©μž κ²Œμ‹œνŒμ— 파일 첨뢀 κΈ°λŠ₯을 톡해 Server Side Script파일 μ—…λ‘œλ“œκ°€ κ°€λŠ₯ν•œμ§€ 확인

: μ—…λ‘œλ“œ 된 Server Side Script파일이 λΈŒλΌμš°μ € μ£Όμ†Œ μ°½μ—μ„œ 싀행이 κ°€λŠ₯ν•œμ§€ 확인

: μ—…λ‘œλ“œ 파일 ν™•μž₯자 우회 기법 μ‚¬μš©

: ν™•μž₯자 λŒ€μ†Œλ¬Έμž λ³€κ²½ (ex: jsp → JsP,JSp)

: ν™•μž₯자 λ³€κ²½ (ex: jsp → jspx, jsv, jsw λ“± / asp → cer, asaλ“± / php → php3, cgiλ“±)

: 쒅단 λ¬Έμžμ—΄ μΆ”κ°€ (Linux : .jsp → .jsp.jpg / Windows : .asp → .asp;.jpg) 은 URL λ””μ½”λ”© ν›„ μ‚½μž…


O 쑰치 방법

- μ„œλΉ„μŠ€λ₯Ό μœ„ν•΄ ν—ˆμš©λ˜λŠ” 파일의 ν™•μž₯자 μ™Έμ˜ νŒŒμΌμ€ μ—…λ‘œλ“œκ°€ λΆˆκ°€λŠ₯ν•˜λ„λ‘ κ΅¬ν˜„

: avi, exe λ“±μ˜ λ™μ˜μƒ, μ‹€ν–‰ 파일 λ“± μ•…μ„±μ½”λ“œκ°€ 포함될 수 μžˆλŠ” μ½˜ν…μΈ λ₯Ό μ—…λ‘œλ“œ ν•˜μ§€ λͺ»ν•˜λ„둝 필터링 적용

- 파일 μ—…λ‘œλ“œ κΈ°λŠ₯이 μžˆλŠ” λͺ¨λ“  곳에 μ„œλ²„ μ‚¬μ΄λ“œ 슀크립트 파일의 μ—…λ‘œλ“œ 및 μ‹€ν–‰ κΈˆμ§€

μ—…λ‘œλ“œ 디렉터리λ₯Ό μ›Ή 디렉터리 μ™ΈλΆ€λ‘œ μ„€μ • 

: μ›Ή 디렉터리 내에 μžˆμ–΄μ•Ό ν•˜λŠ” 경우 ν•΄λ‹Ή μ—…λ‘œλ“œ λ””λ ‰ν„°λ¦¬μ—μ„œ μ„œλ²„ μ‚¬μ΄λ“œ 슀크립트 μ‹€ν–‰ 속성 제거

- μ‚¬μš©μžλ‘œλΆ€ν„° 경둜 κ°’ μž…λ ₯ λ°›μ•„ μ²˜λ¦¬ν•˜λŠ” 경우 κ²½λ‘œκ°€ λ³€μ‘°λ˜μ§€ μ•Šκ²Œ 검증 둜직 κ΅¬ν˜„

: "../", "..\"λ“±κ³Ό 같은 λ¬Έμžμ—΄μ΄ ν¬ν•¨λ˜μ–΄ μžˆμ„ 경우 μ—λŸ¬μ²˜λ¦¬

: μ§€μ •λœ μ—…λ‘œλ“œ 디렉터리 문자만 포함될 수 μžˆλ„λ‘ 검증 

- 파일 λͺ…을 λ‚œμˆ˜ν™”ν•˜μ—¬ μœ μΆ” λΆˆκ°€λŠ₯ν•˜λ„λ‘ κ΅¬ν˜„

- 응닡 값에 μ—…λ‘œλ“œ 경둜 λ…ΈμΆœ μ œν•œ

- 주기적으둜 μ—…λ‘œλ“œ λ˜μ–΄ μžˆλŠ” νŒŒμΌλ“€μ„ λŒ€μƒμœΌλ‘œ λ°”μ΄λŸ¬μŠ€ 검사 μ‹€μ‹œ


O μ‹œνμ–΄ μ½”λ”©(Secure Coding) μ˜ˆμ‹œ

# μ—…λ‘œλ“œ 디렉터리 μ‹€ν–‰κΆŒν•œ 제거 방법 (IIS) β–Ά

1. μ‹œμž‘ > μ œμ–΄νŒ > 관리도ꡬ > 인터넷 μ„œλΉ„μŠ€ κ΄€λ¦¬μž > 등둝정보 > ν™ˆ 디렉터리 > ν•΄λ‹Ή μ—…λ‘œλ“œ 폴더 선택

2. μ‹€ν–‰ κΆŒν•œμ„ "μ—†μŒ"으둜 μ„€μ •


# μ—…λ‘œλ“œ 디렉터리 μ‹€ν–‰κΆŒν•œ 제거 방법 (Apache) β–Ά

- httpd.conf λ‚΄μš© μˆ˜μ •

<Directory "/usr/local/apache">
 AllowOverride FileInfo


# μ—…λ‘œλ“œ 디렉터리에 '.htaccess' 파일 생성 ν›„ μ„œλ²„ 슀크립트 μ‹€ν–‰ μ œν•œ β–Ά
<FileMatch "(\.(asp|aspx|cer|jsp|jspx|php|htm|html))$"> Order allow, deny
Β  Β  Deny from all
</FileMatch>


# JAVA β–Ά
.....
String fileName = file.getOriginalFilename().toLowerCase();
String fileExt = fileName.substring(fileName.lastIndexOf('.') + 1);

// ν™”μ΄νŠΈλ¦¬μŠ€νŠΈ λ°©μ‹μœΌλ‘œ μ—…λ‘œλ“œ 파일의 ν™•μž₯자λ₯Ό μ²΄ν¬ν•œλ‹€
if( !fileExt.equals("jpg") && !fileExt.equals("png") ) {
    out.println("");
    return;
}

// μ—…λ‘œλ“œ 디렉터리 μœ„μΉ˜λŠ” μ›Ή λ””λ ‰ν„°λ¦¬μ˜ 밖에 μœ„μΉ˜ μ‹œν‚¨λ‹€
String uploadPath = "/upload/img/";

// νƒ€μž„λ°μ΄ν„° 값을 파일 λͺ…μœΌλ‘œ μ‚¬μš©ν•œλ‹€
String timeDate = new String(date.format(today).toString();

// ν™•μž₯자 검증이 μ™„λ£Œλœ fileExt ν™•μž₯자 λ³€μˆ˜ 바인딩
String uploadFilePath = uploadPath + timeDate + "." + fileExt;

/* 파일 μ—…λ‘œλ“œ 둜직 μˆ˜ν–‰ */
.....


# ASP β–Ά
.....
fileExt = Mid(fileName, InstrRev(fileName, ".")+1)

// ν™”μ΄νŠΈλ¦¬μŠ€νŠΈ λ°©μ‹μœΌλ‘œ μ—…λ‘œλ“œ 파일의 ν™•μž₯자λ₯Ό μ²΄ν¬ν•œλ‹€
IF fileExt <> "jpg" and fileExt <> "png" and fileExt <> "gif" Then
    Response.Write("")
    Response.End
End IF

// μ—…λ‘œλ“œ 디렉터리 μœ„μΉ˜λŠ” μ›Ή λ””λ ‰ν„°λ¦¬μ˜ 밖에 μœ„μΉ˜ μ‹œν‚¨λ‹€
uploadPath = "E:\upload\pds\";

// νƒ€μž„λ°μ΄ν„° 값을 파일 λͺ…μœΌλ‘œ μ‚¬μš©ν•œλ‹€
timeDate = DateDiff("s", CDate("1970-01-01 00:00:00"), now()) - (9*60*60)

// ν™•μž₯자 검증이 μ™„λ£Œλœ fileExt ν™•μž₯자 λ³€μˆ˜ 바인딩
uploadFilePath = uploadPath & timeDate & "." & fileExt;

/* 파일 μ—…λ‘œλ“œ 둜직 μˆ˜ν–‰ */
.....


# PHP β–Ά
.....
$fileExt = strtolower(substr($fileName, strrpos($fileName, ".")+1));

// ν™”μ΄νŠΈλ¦¬μŠ€νŠΈ λ°©μ‹μœΌλ‘œ μ—…λ‘œλ“œ 파일의 ν™•μž₯자λ₯Ό μ²΄ν¬ν•œλ‹€
if ($fileExt != "jpg" && $fileExt != "png" && $fileExt != "gif") {
    echo "";
    exit;
}

// μ—…λ‘œλ“œ 디렉터리 μœ„μΉ˜λŠ” λ‹€νλ¨ΌνŠΈ 루트(μ›Ή 디렉터리)의 밖에 μœ„μΉ˜ μ‹œν‚¨λ‹€
$uploadPath = "/uploads/img/";

// νƒ€μž„λ°μ΄ν„° 값을 파일 λͺ…μœΌλ‘œ μ‚¬μš©ν•œλ‹€
$timeDate = time();

// ν™•μž₯자 검증이 μ™„λ£Œλœ fileExt ν™•μž₯자 λ³€μˆ˜ 바인딩
$uploadFilePath = $uploadPath . $timeDate . "." . $fileExt;

/* 파일 μ—…λ‘œλ“œ 둜직 */
.....