๐Ÿ•น๏ธ 7. ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ

๐Ÿ•น๏ธ ๋ชจ์˜ํ•ดํ‚น ์ฒดํ—˜ ๋„์ „

๐Ÿ•น๏ธ ๋ชจ์˜ํ•ดํ‚น ์ฒดํ—˜ ๋”ฐ๋ผํ•˜๊ธฐ โ–ถSTEP_1) ๋“ฑ๋ก๋œ ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ

STEP_2) ์ฒจ๋ถ€๋œ ํŒŒ์ผ(test.txt) ํŒŒ์ผ ํด๋ฆญ

STEP_3) ํ”„๋ก์‹œ ํˆด์ธ Burp Suite์„ ์ด์šฉํ•˜์—ฌ, ์š”์ฒญํ•˜๋Š” ํŒŒ์ผ๋ช…์„ ์‹œ์Šคํ…œ ํŒŒ์ผ(/etc/passwd)์˜ ์ƒ๋Œ€ ๊ฒฝ๋กœ๋กœ ๋ณ€์กฐ ํ›„ ์š”์ฒญ

STEP_4) ์‹œ์Šคํ…œ ํŒŒ์ผ(/etc/passwd)์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํ•ด๋‹น ํŒŒ์ผ ๋‚ด ์ž‘์„ฑ๋œ FLAG ๊ฐ’ ํ™•์ธ ๊ฐ€๋Šฅ


O ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•˜์—ฌ ์„œ๋ฒ„์˜ ์†Œ์Šค์ฝ”๋“œ, ์‹œ์Šคํ…œ ํŒŒ์ผ ๋“ฑ ์ฃผ์š” ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝ์ 


O ๊ทผ๊ฑฐ ์ž๋ฃŒ

โ˜ž ์ฃผ์š”์ •๋ณดํ†ต์‹ ๊ธฐ๋ฐ˜์‹œ์„ค ๊ธฐ์ˆ ์  ์ทจ์•ฝ์  ๋ถ„์„ ํ‰๊ฐ€ ์ƒ์„ธ ๊ฐ€์ด๋“œ(p.715)


O ํŒ๋‹จ ๊ธฐ์ค€

์–‘ํ˜ธ๋‹ค์šด๋กœ๋“œ ํŒŒ์ผ์ด ์ €์žฅ๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ด์™ธ์— ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ
์ทจ์•ฝ๋‹ค์šด๋กœ๋“œ ํŒŒ์ผ์ด ์ €์žฅ๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ด์™ธ์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ


O ์ ๊ฒ€ ๋ฐฉ๋ฒ•

- ๊ฒฝ๋กœ์ด๋™๋ฌธ์ž(../ ํ˜น์€ ..\)๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์šด๋กœ๋“œ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ ์กฐ์ž‘

- '../' ๋ฐ '..\'๋“ฑ์„ ํ•„ํ„ฐ๋งํ•  ๊ฒฝ์šฐ '…/./' ๋ฐ '…\.\'๋“ฑ์œผ๋กœ ํ•„ํ„ฐ๋ง ์šฐํšŒ

- /(%2F) , \(%5C) URL ์ธ์ฝ”๋”ฉ์„ ์ด์šฉํ•˜์—ฌ ํ•„ํ„ฐ๋ง ์šฐํšŒ 

# ์‹œ์Šคํ…œ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ์˜ˆ์‹œ

- Linux ์‹œ์Šคํ…œ ํŒŒ์ผ : ../../../../../etc/passwd

- Windows ์‹œ์Šคํ…œ ํŒŒ์ผ : ..\..\..\..\..\Windows\System32\Drivers\etc\host


O ์กฐ์น˜ ๋ฐฉ๋ฒ•

์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ๊ฐ’์— "../", "..\" ์กด์žฌ ์‹œ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ

- ์—…๋กœ๋“œ ๋ฐ ๋‹ค์šด๋กœ๋“œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌ๋œ ํ•˜๋“œ์›จ์–ด ๋˜๋Š” ํŒŒํ‹ฐ์…˜์— ์œ„์น˜ํ•˜๋„๋ก ์„ค์ •

- ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค์šด๋กœ๋“œ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์œ„์น˜ ์ด์™ธ์˜ ๊ฒฝ๋กœ์—์„œ ๋‹ค์šด๋กœ๋“œ ์ œํ•œ

- ํŒŒ์ผ ๊ฒฝ๋กœ ์ž…๋ ฅ ์‹œ ์ „์ฒด ๊ฒฝ๋กœ ์‚ฌ์šฉ ๋ฐ ๋…ธ์ถœ ๊ธˆ์ง€

- ๋‹ค์šด๋กœ๋“œ ๊ฐ€๋Šฅํ•œ ํŒŒ์ผ๋ช…์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜์—ฌ ๋‹ค์šด๋กœ๋“œ ํŒŒ์ผ์€ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ๊ตฌํ˜„


O ์‹œํ์–ด ์ฝ”๋”ฉ(Secure Coding) ์˜ˆ์‹œ 

# ํŒŒ์ผ๋ช… ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฐธ์กฐ ๋ชจ๋“ˆ โ–ถ
==== com.example.demo.board.service.BoardService.java ====
public FileVO fileDetailService(int bno) throws Exception{   
    return mBoardMapper.fileDetail(bno);
}
==== com.example.demo.board.mapper.BoardMapper.java ====
public FileVO fileDetail(int bno) throws Exception;
==== com.example.demo.board.mapper.BoardMapper.xml ====
SELECT * FROM Files WHERE BNO = #{bno}


# JSP โ–ถ
.....
String UPLOAD_PATH= "/var/www/upload/";
String filename= response.getParameter("filename");
String filepathname = UPLOAD_PATH + filename;

if(filename.equalsIgnoreCase("..") || filename.equalsIgnoreCase("/"))
    // ํŒŒ์ผ ์ด๋ฆ„ ์ฒดํฌ
    return 0;
}
// ํŒŒ์ผ ์ „์†ก ๋ฃจํ‹ด
response.setContentType("application/unknown; charset=euc-kr");
response.setHeader("Content-Disposition","attachment;filename=" + filename + ";");
response.setHeader("Content-Transfer-Encoding:" , "base64");
    
try {
    BufferedInputStream in =
    new BufferedInputStream(new FileInputStream(filepathname));
        .....
} catch(Exception e) { ย  ย  
    // ์—๋Ÿฌ ์ฒดํฌ [ํŒŒ์ผ ์กด์žฌ ์œ ๋ฌด ๋“ฑ]      
}


# ASP โ–ถ
<%
    file = Request.Form ("file") // ํŒŒ์ผ ์ด๋ฆ„
    Response.ContentType = "application/unknown" // ContentType ์„ ์–ธ
    Response.AddHeader "Content-Disposition","attachment; filename=" & file

    Set objStream = Server.Create Object("ADODB.Stream") // Stream ์ด์šฉ
    strFile = Server.MapPath("./upfiles/") & "โ‚ฉ" & file // ์„œ๋ฒ„ ์ ˆ๋Œ€๊ฒฝ๋กœ
    strFname=Mid(Fname,InstrRev(file,"โ‚ฉ")+1) // ํŒŒ์ผ ์ด๋ฆ„ ์ถ”์ถœ, ..โ‚ฉ ๋“ฑ์˜ ํ•˜์œ„ ๊ฒฝ๋กœ ํƒ์ƒ‰์€ ์ œ๊ฑฐ๋จ
    strFPath = Server.MapPath("./upfiles/") & "โ‚ฉ" & strFname // ์›น ์„œ๋ฒ„์˜ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ์ ˆ๋Œ€ ๊ฒฝ๋กœ

ย  ย  // ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์šด ๋ฐ›๋Š” ํŒŒ์ผ๊ณผ ์›น ์„œ๋ฒ„์˜ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ๊ฒฝ๋กœ๊ฐ€ ๋งž๋Š”์ง€ ๋น„๊ต
    If strFile = strFPath Then
        objStream.Open
        objStream.Type = 1
        objStream.LoadFromFile strFile
        download = objStream.Read
        Response.BinaryWrite download
    End If

    // ๊ฐ์ฒด ์ดˆ๊ธฐํ™”
    Set objstream = nothing 
%>


# PHP โ–ถ
.....
// ๋””๋ ‰ํ„ฐ๋ฆฌ์— ํŠน์ˆ˜๋ฌธ์ž ์ฒดํฌ
if (preg_match("/[^a-z0-9_-]/i",$up_dir))
    print "๋””๋ ‰ํ„ฐ๋ฆฌ์— ํŠน์ˆ˜๋ฌธ์ž ์ฒดํฌ";
    exit;

// ํŒŒ์ผ ์ด๋ฆ„์— ํŠน์ˆ˜๋ฌธ์ž ์ฒดํฌ ย       
if (preg_match("/[^\xA1-\xFEa-z0-9._-]|\.\./i",urldecode($dn_file_name)))
    print "ํŒŒ์ผ์ด๋ฆ„์— ํŠน์ˆ˜๋ฌธ์ž ์ฒดํฌ";
    exit;

// ํŒŒ์ผ ์กด์žฌ ์—ฌ๋ถ€ ์ฒดํฌ
$dn_path = "/var/www/data/$up_dir/$dn_file_name";
if (!file_exists($dn_path))
    print "ํŒŒ์ผ์ด ์กด์žฌ์—ฌ๋ถ€ ์ฒดํฌ";
    exit;

// ํŒŒ์ผ ์ „์†ก ๋ฃจํ‹ด
header("Content-Type: doesn/matter");
header("Content-Length: ".filesize("$dn_path"));
header("Content-Disposition: filename=".$dn_file_name]);
header("Content-Transfer-Encoding: binary\r\n");
header("Pragma: no-cache");
header("Expires: 0");
.....