작은 메모장

41. 소스코드 취약점 진단 본문

실더스 루키즈 교육

41. 소스코드 취약점 진단

으앙내눈 2024. 3. 6. 18:44
String fileName = request.getParameter ("P"); 
BufferedInputStream bis = null; 
BufferedOutputStream bos = null; 
FileInputStream fis = null;
try { response.setHeader("Content-Disposition", "attachment;filename="+fileName+";");

...
fis = new FileInputStream ("C:/datas/"+fileName); 
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(response.getOutputStream());

정/오탐 판별 1
- 취약점: 디렉토리 탐색 취약점(Directory Traversal)
- 양호/취약 여부: 취약
- 취약 사유: 사용자 입력('fileName')을 검증 없이 직접 파일 시스템 접근으로 넘겨 사용하고 있습니다. 이로 인해, 웹 어플리케이션의 루트 디렉토리를 벗어나서 상위 디렉토리로 접근이 가능합니다. 따라서, 사용자 입력에 따라 서버의 중요 시스템 파일에 접근할 수 있는 취약점이 발생합니다.

 

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
...
<select id="boardSearch" parameterType="map" resultType="BoardDto">
select * from tbl_board where title like '%'||#{{keyword}||'%' order by pos asc
</select>

 

정/오탐 판별 2
- 취약점: SQL 인젝션(SQL Injection)
- 양호/취약 여부: 취약
- 취약 사유: 해당 쿼리에서 사용자 입력('keyword')에 해당하는 내용을 SQL문에 동적으로 삽입하고 있습니다. 다시말해, 사용자 입력이 SQL 쿼리에 직접 입력이 되고 있습니다. 따라서, 악의적인 사용자가 임의의 SQL문을 주입하여 데이터베이스를 조작하거나 민감한 정보를 추출당할 가능성이 매우 높습니다.

 

<% String keyword = request.getParameter("keyword"); %>
keyword = keyword.replaceAll("&", "&amp;"); 
keyword = keyword.replaceAll("<", "&lt;"); 
keyword = keyword.replaceAll(">", "&gt;"); 
keyword = keyword.replaceAll("₩"", "&quot;"); 
keyword = keyword.replaceAll("'", "&#x27;"); 
keyword = keyword.replaceAll("/"", "&#x2F;"); 
keyword = keyword.replaceAll("(", "&#x28;"); 
keyword = keyword.replaceAll(")", "&#x29;");
검색어 : <%=keyword%>

정/오탐 판별 3
- 취약점: XSS(Cross-site Scripting) 방지를 위한 문자 변환
- 양호/취약 여부: 양호
- 양호 사유: 사용자 입력으로부터 keyword값을 받아와 XSS 공격에 자주 사용되는 특수 문자(현 예시에서는 &, <, >, ", ', /, (, ) )를 HTML 엔티티로 변환합니다. 이를 통해 브라우저가 keyword의 사용자 값을 스크립트가 아닌 단순한 텍스트로 인식하게 만듭니다. 결론적으로, 사용자의 브라우저에서 스크립트가 실행되는 것을 방지합니다.

 

if (FileUploadCtr.PostedFile.ContentType == "image/jpeg") { 
if (FileUploadCtr.PostedFile.ContentLength < 102400) { 
string fn = Path.GetFileName(FileUploadCtr.FileName);
FileUploadCtr.SaveAs(Server.MapPath("~/") + fn); 
StatusLabel.Text = "Upload status: File uploaed!"; 
} 
else StatusLabel.Text = "Upload Status: The File has to be less than 100 kb!";
}
else 
StatusLabel.Text = "Upload Status: Only JPEG files are accepted!";

정/오탐 판별 4
- 취약점: 파일 업로드 취약점(File Upload Vulnerability)
- 양호/취약 여부: 취약
- 취약 사유: Path.GetFileName(FileUploadCtr.FileName)를 통해 추출된 파일 이름(fn)이 사용자의 입력으로부터 직접 입력받고 있습니다. 이는 사용자가 파일 이름에 상대 경로를 포함하는 경우(../)에 지정된 웹 디렉토리가 아닌, 다른 예상하지 못한 디렉토리에 파일을 업로드 할 위험성이 높습니다.
또, 단순히 파일의 컨텐츠 타입을 image/jpeg만을 확인하는 것은 검사가 부족할 수 있습니다. 파일의 컨텐츠 타입은 클라이언트에서 얼마든지 조작이 가능하며, 실제 파일이 jpeg 형식이 아니거나, 악의적인 코드를 포함하고 있을 수 있습니다. 따라서, 파일의 MIME 타입만으로 판별하는 것이 아닌, 파일의 매직 넘버(0xFFD8)를 확인하거나 파일 내용을 키워드 분석하여 실제 파일 타입을 검증하는 방식도 고려할 수 있습니다.

 

String id = (String)session.getValue("id"); 
String bn = request.getParameter("gubun"); 
String rd = request.getParameter("redirect"); 
if (id.length() > 0) {
String sql = "select level from customer where customer_id = ? "; 
conn = db.getConnection();
pstmt = conn.prepareStatement(sql); 
pstmt.setString(1, id);
rs = pstmt.executeQuery(); 
rs.next(); 
if ("0".equals(rs.getString(1)) && "01AD".equals(bn)) { 
response.sendRedirect(rd); 
return;
}

 

정/오탐 판별 5
- 취약점: 오픈 리다이렉션(Open Redirection)
- 양호/취약 여부: 취약
- 취약 사유: redirect 파라미터를 사용하여 response.sendRedirect() 메소드를 호출하고 있습니다. 더 자세히는, 'rd' 변수로 받은 URL을 검증 없이 리다이렉션에 사용하고 있어, 이는 공격자가 악의적인 URL로 사용자를 리다이렉션할 수 있게 합니다. 이로 인해, 사용자가 신뢰하는 사이트로부터 온 것처럼 보이는 악의적인 페이지에 접근하도록 유도할 수 있습니다.

 

String gubun = request.getParameter(“gubun”);
…
String sql = “SELECT * FROM board WHERE b_gubun = ‘”+gubun+ “’”;
Connection con = db.getConnection(); 
Statement stmt = con.createStatement(); 
ResultSet rs = stmt.executeQuery(sql);

 

정/오탐 판별 6
- 취약점: SQL 인젝션(SQL Injection)
- 양호/취약 여부: 취약
- 취약 사유: 사용자 입력('gubun')이 검증없이 직접 SQL 쿼리문에 입력되어 사용되고 있어, 악의적인 사용자가 SQL 인젝션 공격을 수행할 수 있는 가능성을 제공하고 있습니다. 이는 gubun 값으로 SQL 문을 종료하는 문자열과 함께 추가적인 SQL 명령을 삽입할 수 있습니다. 즉, 악의적인 SQL 쿼리가 데이터베이스 서버에서 실행될 수 있습니다.

 

public static void main(String args[]) throws IOException { 
List<String> allowedCommands = new ArrayList<String>(); 
allowedCommands.add("notepad"); 
allowedCommands.add("calc"); 
String cmd = args[0]; 
if (!allowedCommands.contains(cmd)) { 
System.err.println("Error"); 
return; 
}
Process ps = null;
try { 
ps = Runtime.getRuntime().exec(cmd);
......

정/오탐 판별 7
- 취약점: 명령 주입 공격(Command Injection)
- 양호/취약 여부: 대부분 양호
- 양호 사유: 이 코드는 실행되는 커맨드를 allowedCommands 리스트에 명시된 커맨드로 제한하고 있습니다. 즉, 화이트리스트를 통한 임의의 시스템 커맨드 실행을 방지하고 있습니다. 제한적인 커맨드만 실행이 가능하므로, 사용자가 악의적인 커맨드를 주입할 가능성이 크게 줄어듭니다.

 

string file = Request.QueryString["path"]; 
if (file != null) { 
if (file.IndexOf('\\') > -1 || file.IndexOf('/') > -1) { 
Response.Write("Path Traversal Attack");
}
else {
File.Delete(file);
}
}

 

정/오탐 판별 8
- 취약점: 경로순회 공격(Path Traversal)
- 양호/취약 여부: 양호
- 취약 사유: 해당 코드는 단순히 파일 경로에 '\' 혹은 '/'가 포함되어 있는지만을 확인하고 있으므로, 이 문자를 제외하면서 악의적인 사용자가 경로 조작으로 서버의 다른 파일을 제어하기 어렵습니다.

 

<%
String param = request.getParameter(“param”); 
If(param != null) {
param = param.replaceAll(“<script>”,””); 
param = param.replaceAll(“</script>”,””);
}
%>
…

<p> 제목 : <%=param%></p>

 

정/오탐 판별 9
- 취약점: 불완전한 XSS(Cross-site Scripting) 취약점 방지
- 양호/취약 여부: 조건부 취약
- 취약 사유: 이 코드는 사용자 입력에서 '<script>'와 '</script>' 태그를 단순히 제거하여 XSS 공격을 막는 형태입니다. 그러나, 이는 특정 형태의 스크립트에만 유효하기 때문에, XSS 공격으로 완벽하게 방어할 수 없습니다. 가령, 해당 경우와 다른 태그(<img>, <iframe> 등)을 사용해서도 스크립트 주입이 가능합니다.
따라서, 특정 태그를 제거하는 형태로 사용자 입력을 HTML에 반영하는 방식보단, 특수 문자(<, >, ", ', & 등)를 HTML 엔티티로 이스케이프 처리하여 스크립트 동작 자체를 방지하는 방식이 더 바람직한 방어 방식입니다.

 

<%@taglibprefix=”c”url=”http://java.sun.com/jsp/jstl/core”%> 
<%@tagliburi=”http://java.sun.com/jsp/jstl/functions”prefix=”fn”%> 
…
<c:out value=”${param.name}” escapeXml=”false”/>

 

정/오탐 판별 10
- 취약점: XSS(Cross-site Scripting)
- 양호/취약 여부: 취약
- 취약 사유: escapeXml="false" 설정은 '<c:out>' 태그가 출력하는 데이터에 대한 XML/HTML 이스케이프 처리를 비활성화합니다. 이는 사용자로부터 제어될 수 있는 데이터('param.name')이 HTML 페이지에 직접 주입될 때, 해당 데이터에 악의적인 스크립트가 포함되어 있을 경우 그대로 실행될 가능성이 존재합니다. 즉, 이는 XSS 취약점으로 이어질 수 있습니다.

 

MultipartRequest multi = new MultipartRequest(request,savePath,sizeLimit,"euc-kr",new 
DefaultFileRenamePolicy()); 
...... 
String fileName=multi.getFilesystemName("filename"); 
...... 
sql="INSERT INTO board(email,r_num,w_date,pwd,content,re_step,re_num,filename)“ 
+"values(?,0,sysdate(),?,?,?,?,?)";

PreparedStatement pstmt=con.prepareStatement(sql); 
pstmt.setString(1,stemail); 
pstmt.setString(2,stpwd); 
pstmt.setString(3,stcontent); 
pstmt.setString(4, stre_step); 
pstmt.setString(5, stre_num); 
pstmt.setString(6, fileName); 
pstmt.executeUpdate();    
Thumbnail.create(savePath+"/"+fileName, savePath+"/"+"s_"+fileName, 150);

정/오탐 판별 11
- 취약점: 파일 업로드 취약점, 경로 조작(Path Traversal), SQL Injection 방지(양호)
- 양호/취약 여부:
파일 업로드 취약점: 취약
경로조작(Path Traversal): 취약
SQL 인젝션: 양호
- 양호 및 취약 사유:
파일 업로드 취약점/취약 사유: 위 코드는 업로드된 파일의 종류나 크기에 대한 검사가 전혀 이루어지지 않고 있습니다. 때문에 악의적인 사용자가 서버에 악성 파일을 업로드 할 가능성이 매우 높습니다. 
경로 조작(Path Traversal)/취약 사유: 업로드된 파일의 이름 또한 검증하지 않고 직접 사용하므로, 파일 이름을 이용해 서버의 다른 경로로 파일을 저장하거나 덮어쓸 수 있는 악의적인 공격도 가능합니다.
SQL 인젝션(SQL Injection)/양호 사유: PreparedStatement를 사용하여 데이터베이스 쿼리를 실행해 사용자 입력을 파라미터로 취급하고, 쿼리를 실행하기 전 사용자 입력을 유용하게 이스케이프 처리하여 SQL 인젝션을 적극적으로 방어하고 있습니다.

'실더스 루키즈 교육' 카테고리의 다른 글

42. 모의해킹 총정리  (0) 2024.03.22
40. 취약점 진단 실습 3  (0) 2024.02.28
39. 취약점 진단 실습 2  (0) 2024.02.27
38. 취약점 진단 실습 1  (0) 2024.02.26
37. 도커 파일과 도커 컴포즈  (0) 2024.02.23