반응형
3장 1절 접근통제 취약점
□ 취약한 프로그래밍 예
- <HTML>
<HEAD><TITLE> 관리자 페이지 </TITLE>
<SCRIPT language="JavaScript“>
function getCookie(name)
var cname = name +"=";
var dc = document.cookie; - if(dc.length > 0)
begin = dc.indexOf(cname);
if(begin != -1)
begin += cname.length;
end = dc.indexOf(";", begin); - if(end == -1) end = dc.length;
retrun unescape(dc.substring(begin, end));
return null;- function getValue(element)
var value = getCookie(element.name);
if(value != null) element.value = value; - </SCRIPT>
</HEAD>
<BODY>
<SCRIPT language="JavaScript">
var auth;
auth = getCookie("logged_in"); - if(auth != 1) // 인증 성공 쿠키가 없을경우 Main Page로 이동
window.location = "http://victim.com/login.html"; - </SCRIPT>
- 관리자 페이지 내용
□ 안전한 프로그래밍 예
ASP
- <%
If myfunc_userauth(userid, userpw) <> 1 Then 'DB에서 사용자 인증을 처리
Response.write "인증 실패"
Else
If Request.ServerVariables("REMOTE_ADDR") <> "10.10.1.1" Then' 관리자 IP 확인
Response.write "관리자 IP가 아닙니다."
Response.write "인증실패“
LogSave(userid, user_ip, 0)'접속에 실패한 ID 및 IP 기록
Else
Session("logged_in") = 1'인증에 성공했을경우 logged_in 에 1의 값을 셋팅
Session("userid") = userid
Session("user_ip") = Request.ServerVariables("REMOTE_ADDR") - LogSave($userid, $user_ip)'접속에 사용한 ID 및 IP 기록
- ... 중략 ...
End If
End If
%>
o PHP- <?PHP
@session_start(); //세션 데이터를 초기화
if(!myfunc_userauth($userid, $userpw) || $_SERVER["REMOTE_ADDR'] != "10.10.1.1")
//DB 에서 사용자 인증을 처리, 관리자 IP인지 확인
print "인증 실패";
LogSave(userid, user_ip, 0)'접속에 실패한 ID 및 IP 기록
exit;//인증 실패시 종료
//인증에 성공한 경우 처리 해야 되는 부분
if (!session_is_registered("logged_in"))- $logged_in = 1;//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
$user_ip = $_SERVER["REMOTE_ADDR"];
session_register("logged_in");//인증 결과 저장
session_register("userid");//사용자 ID를 저장
session_register("user_ip");//사용자 IP를 저장 - LogSave($userid, $user_ip);// 접속한 사용자 ID 및 IP 기록
... 중략 ...
JSP
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.* " %>
<%@ page import="java.sql.* " %>
<%
//HttpSession session = request.getSession(true);
String user_ip = request.getRemoteAddr(); - // form 에서 사용자 id와 사용자 password를 아래 변수로 전달
if(!myfunc_userauth(userid, userpw) || !user_ip.equals("10.10.1.1"))
//DB 에서 사용자 인증을 처리, 관리자 IP인지 확인
out.println "인증 실패";
LogSave(userid, user_ip, 0)'접속에 실패한 ID 및 IP 기록
else
//인증에 성공한 경우 처리 해야 되는 부분
session.putValue("logged_in","logok");
session.putValue("userid",userid);
session.putValue("user_ip", user_ip); - LogSave(userid, user_ip);// 접속한 사용자 ID 및 IP기록
...
3장 2절 부적절한 파라미터 - 소스
□ ASP
취약한 프로그래밍 예
- <%
strSize = Request.QueryString("font_size")'사용자로부터 폰트의 크기 입력 - Response.Write "<HTML><TITLE>사용자 입력값 검증</TITLE></HEAD>"
Response.Write "<BODY>"
Response.Write "<FONT size=" & strSize & ">글자 크기 조절</FONT>" - ' ... 중략 ...
안전한 프로그래밍 예
- <%
Size = Request.QueryString("font_size")' 사용자로부터 폰트의 크기 입력 - Size = CInt(Size)' 입력되는 값을 정수로 형 변환
- Response.Write "<HTML><TITLE>사용자 입력값 검증</TITLE></HEAD>"
Response.Write "<BODY>"
Response.Write "<FONT size=" & Size ">글자 크기 조절</FONT>" - ' ... 중략 ...
□ PHP
취약한 프로그래밍 예
- <?PHP
include "./inc/dbconn.inc";// DB 연결 헤더
include $language . "/head.html";// 각 국가 언어별 HTML 출력 - $conn = mysql_connect($SERVER, $USER, $PASSWD);
$query = "select count(*) from main_tbl"; - // ... 중략 ...
안전한 프로그래밍 예
- <?PHP
@require_once "./inc/dbconn.inc";// DB 연결 헤더
$default_lang = "korea";// 기본값 설정 - if(!file_exists($language."/head.html")) // 파일이 존재하는지 체크
if(eregi(":\/\/", $language)) $language = $default_lang;// URL이 포함되는지 체크
else // 파일이 없는 경우 기본값 설정
$language = $default_lang; - @require_once $language . "/head.html";// 각 국가 언어별 HTML 출력
- $conn = @mysql_connect($SERVER, $USER, $PASSWD);
$query = "select count(*) from main_tbl"; - // ... 중략 ...
□ JSP
취약한 프로그래밍 예
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.* " %> - <HTML><HEAD><TITLE> 사이트 접속 불가 </TITLE>
<META HTTP-EQUIV="Refresh" CONTENT="10;URL=http://victim.com/bye.html">
</HEAD>
<BODY>
<%
out.print("지금 사용하고 계신 ");
out.print(request.getHeader("USER-AGENT"));
out.print(" 브라우져로는 사이트 접속이 불가능 합니다.");
%>
</BODY>
</HTML>
안전한 프로그래밍 예
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.* " %> - <HTML><HEAD><TITLE> 사이트 접속 불가 </TITLE>
<META HTTP-EQUIV="Refresh" CONTENT="10;URL=http://victim.com/bye.html">
</HEAD>
<BODY>
<%
String user_agent = request.getHeader("USER-AGENT"); - // HTTP HEADER 중 USER_AGENT를 변경 하여 크로스사이트 스크립트 공격하는 것을 차단
user_agent = user_agent.replaceAll("<","<");// HTML tag가 있을 경우 제거
user_agent = user_agent.replaceAll(">",">"); - out.print("지금 사용하고 계신 ");
out.print(user_agent);
out.print(" 브라우져로는 사이트 접속이 불가능 합니다."); - %>
</BODY>
</HTML>
3장 3절 취약한 세션 관리 (Cookie Injection) - 소스
□ ASP
취약한 프로그래밍 예
- 'login_ok.asp 사용자 인증 처리를 하는 스크립트
<%
' form 에서 사용자 id와 사용자 password를 아래 변수로 전달
If myfunc_userauth(userid, userpw) <> 1 Then ' DB 에서 사용자 인증을 처리하는 부분
Response.write "인증 실패"
Else
'인증에 성공한 경우 처리 해야 되는 부분
Response.Cookies("logged_in") = 1
' 인증에 성공했을경우 logged_in 에 1의 값을 셋팅
Response.Cookies("userid") = userid
End If
...
%> - user_menu.asp' 사용자 검증이 필요한 페이지
<%
IF Request.Cookies("logged_in") = 1 Then
Response.write "허가된 사용자 입니다."
Else
Response.write "허가되지 않은 사용자 입니다."
End If
%>
안전한 프로그래밍 예
- ‘login_ok.asp 사용자 인증 처리를 하는 스크립트
<%
' form 에서 사용자 id와 사용자 password를 아래 변수로 전달
If myfunc_userauth(userid, userpw) <> 1 Then ' DB 에서 사용자 인증을 처리하는 부분
Response.write "인증 실패"
Else
'인증에 성공한 경우 처리 해야 되는 부분 - If Session("logged_in") <> 1 Then
Session("logged_in") = 1'인증에 성공했을경우 logged_in 에 1의 값을 셋팅
Session("userid") = userid
Session("user_ip") = Request.Servervariables("REMOTE_ADDR")
End If
End If
...
%> - ‘user_menu.asp 사용자 검증이 필요한 페이지
<%
IF Session("user_ip) = Request.Servervariables("REMOTE_ADDR") AND Session("logged_in") = 1 Then
'인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
'...
Else
Response.write "허가되지 않은 사용자 입니다."
End If
%>
□ PHP
취약한 프로그래밍 예
- //login_ok.php// 사용자 인증 처리를 하는 스크립트
<?PHP
// form 에서 사용자 id와 사용자 password를 아래 변수로 전달
if(!myfunc_userauth($userid,$userpw)) //DB 에서 사용자 인증을 처리하는 부분
print "인증 실패";
exit;//인증 실패시 종료
//인증에 성공한 경우 처리 해야 되는 부분
setcookie("logged_in", "1");//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
setcookie("userid", $userid);
...
?>- //user_menu.php// 사용자 검증이 필요한 페이지
<?PHP
if($_COOKIE["logged_in"] == 1)
echo "인증 성공: " . $_COOKIE["userid"]; - ?>
=================================================================================================================
o 안전한 프로그래밍 예
- //login_ok.php// 사용자 인증 처리를 하는 스크립트
<?PHP
@session_start(); //세션 데이터를 초기화
// form 에서 사용자 id와 사용자 password를 아래 변수로 전달
if(!myfunc_userauth($userid,$userpw)) //DB 에서 사용자 인증을 처리하는 부분
print "인증 실패";
exit;//인증 실패시 종료 - //인증에 성공한 경우 처리 해야 되는 부분
if (!session_is_registered("logged_in")) - $logged_in = 1;//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
$user_ip = $_SERVER["REMOTE_ADDR"];
session_register("logged_in");//인증 결과 저장
session_register("userid");//사용자 ID를 저장
session_register("user_ip");//사용자 IP를 저장 - ...
?> - //user_menu.php// 사용자 검증이 필요한 페이지
<?PHP
session_start();
if(strcmp($_SESSION['user_ip'], $_SERVER['REMOTE_ADDR']) == 0 && session_is_registered('logged_in'))
//인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
//...
else
print "허가되지 않은 사용자 입니다.";
exit; - ?>
□ JSP
취약한 프로그래밍 예
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.*" %>
<%@ page import="java.sql.* " %>
//login_ok.jsp// 사용자 로그인 처리를 하는 스크립트
<%
// form 에서 사용자 id와 사용자 password를 아래 변수로 전달
if(!myfunc_userauth(userid, userpw)) //DB 에서 사용자 인증을 처리하는 부분
out.println "인증 실패";
else
//인증에 성공한 경우 처리 해야 되는 부분
Cookie cookie1 = new Cookie("logged_in", "1");
response.addCookie(cookie1);//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
Cookie cookie2 = new Cookie("userid", userid);
response.addCookie(cookie2);
...
%> - //user_menu.jsp// 사용자 검증이 필요한 페이지
<%
Cookie[] cookies = request.getCookies();
for(int i=0; i< cookies.length; i++)
Cookie thisCookie = cookie[i];
if(thisCookie.getName.equals("logged_in"))
String logged_in = thisCookie.getValue();
if(thisCookie.getName.equals("userid"))
String userid = thisCookie.getValue();
if(logged_in.equals("1"))
out.println("인증 성공: " + userid);- %>
안전한 프로그래밍 예
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.*" %>
<%@ page import="java.sql.* " %>
//login_ok.jsp// 사용자 로그인 처리를 하는 스크립트
<%
//HttpSession session = request.getSession(true);
// form 에서 사용자 id와 사용자 password를 아래 변수로 전달
if(!myfunc_userauth(userid, userpw)) //DB 에서 사용자 인증을 처리하는 부분
out.println "인증 실패";
else
//인증에 성공한 경우 처리 해야 되는 부분
session.putValue('logged_in',"1");
session.putValue('userid',userid);
session.putValue('user_ip',request.getRemoteAddr());
...
%> - //user_menu.jsp// 사용자 검증이 필요한 페이지
<%
//HttpSession session = request.getSession(true);
String user_ip = session.getValue("user_ip"); - if(user_ip.equals(request.getRemoteAddr()) && logged_in.equals("1"))
//인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
//...
else
out.println "허가되지 않은 사용자 처리."; - %>
3장 4절 악의적인 명령 실행(XSS) - 소스
□ ASP
취약한 프로그래밍 예
- <%
Set objDBConn = Server.CreateObject("ADODB.Connection")' 게시물 읽기
Set objRs = Server.CreateObject("ADODB.RecordSet")
objDBConn.Open "board", "user", "passwd" - query = "SELECT id, name, memo FROM board_tbl WHERE id=1"
objRs.Open query, objDBConn - memo = objRs("memo")
Response.write "게시물 내용-" & memo & "<BR>"' DB에서 게시판의 내용 출력
안전한 프로그래밍 예
- If use_html Then' HTML tag를 사용하게 할 경우 부분 허용
memo = Server.HTMLEncode(memo) 'HTML tag를 모두 제거 - ' 허용할 HTML tag만 변경
memo = replace(memo, "<p>", "<p>")
memo = replace(memo, "<P>", "<P>")
memo = replace(memo, "<br>", "<br>")
memo = replace(memo, "<BR>", "<BR>") - Else' HTML tag를 사용하지 못하게 할 경우
memo = Server.HTMLEncode(memo)' HTML encoding 수행
memo = replace(memo, "<", "<")
memo = replace(memo, ">", ">")
End If - Response.write "게시물 내용-" & memo & "<BR>"
□ PHP
취약한 프로그래밍 예
- $query = "SELECT id, name, memo FROM board_tbl WHERE id=1";// 게시물 읽기
$result = mysql_query($query, $connect); - while($row = mysql_fetch_array($result))
$name = $row[name];
$memo = $row[memo];
echo "게시물 내용-" . $memo . "<BR>\n";// DB에서 게시판의 내용을 출력
안전한 프로그래밍 예
- $use_tag = "img,font,p,br";// 허용할 HTML tag
- if($use_html == 1) // HTML tag를 사용하게 할 경우 부분 허용
$memo = str_replace("<", "<", $memo);// HTML TAG를 모두 제거 - $tag = explode(",", $use_tag);
for($i=0; $i<count($tag); $i++) // 허용할 TAG만 사용 가능하게 변경
$memo = eregi_replace("<".$tag[$i]." ", "<".$tag[$i]." ", $memo);
$memo = eregi_replace("<".$tag[$i].">", "<".$tag[$i].">", $memo);
$memo = eregi_replace("</".$tag[$i], "</".$tag[$i], $memo); - else // HTML tag를 사용하지 못하게 할 경우
- // $memo = htmlspecialchars($memo);
// htmlspecialchars() 사용시 일부 한글이 깨어지는 현상이 발생 할 수 있음 - $memo = str_replace("<", "<", $memo);
$memo = str_replace(">", ">", $memo);
echo "게시물 내용-" . $memo . "<BR>\n";
□ JSP
취약한 프로그래밍 예
- Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
Statement stmt = conn.createStatement();
ResultSet rs=null; - String query = "SELECT memo FROM board_tbl WHERE id=1";
rs = stmt.executeQuery(query);
String memo = rs.getString(1);
out.print("게시물 내용-" + memo + "<BR>");
안전한 프로그래밍 예
- if(use_html) // HTML tag를 사용하게 할 경우 부분 허용
memo = memo.replaceAll("<","<");//HTML tag를 모두 제거
memo = memo.replaceAll(">",">"); - // 허용할 HTML tag만 변경
memo = memo.replaceAll("<p>", "<p>");
memo = memo.replaceAll("<P>", "<P>");
memo = memo.replaceAll("<br>", "<br>");
memo = memo.replaceAll("<BR>", "<BR>"); - else // HTML tag를 사용하지 못하게 할 경우
memo = memo.replaceAll("<","<");
memo = memo.replaceAll(">",">"); - out.print("게시물 내용-" + memo + "<BR>");
3장 5절 버퍼 오버플로우 - 소스
□ strcpy() 함수의 대체
취약한 프로그래밍 예
- void func(char *str) {
char buffer[256];
strcpy(buffer, str);
return;
}
안전한 프로그래밍 예
- void func(char *str) {
char buffer[256];
strncpy(buffer, str, sizeof(buffer)-1);
buffer[sizeof(buffer)-1] = 0;
return;
}
□ strcat() 함수의 대체
취약한 프로그래밍 예
- void func(char *str) {
char buffer[256];
strcat(buffer, str);
return;
}
안전한 프로그래밍 예
- void func(char *str) {
char buffer[256];
strncat(buffer, str, sizeof(buffer)-1);
return;
}
□ sprintf() 함수의 대체
취약한 프로그래밍 예
- void func(char *str) {
char buffer[256];
sprintf(buffer, "%s", str);
return;
}
□ gets() 함수의 대체
취약한 프로그래밍 예
- void func(char *str) {
char buffer[256];
gets(buffer);
return;
}
안전한 프로그래밍 예
- void func(char *str) {
char buffer[256];
fgets(buffer, sizeof(buffer)-1, stdin);
return;
}
□ scanf(), sscanf(), fscanf() 함수의 대체
취약한 프로그래밍 예
- void func() {
char buffer[256];
int num;
num = fscanf(stdio, "%s", buffer); char buffer[256];
return;
}
안전한 프로그래밍 예
- void func() {
char buffer[256];
int num;
num = fscanf(stdio, "%255s", buffer);
return;
}
□ C로 개발한 프로그램
버퍼오버플로우 취약점 예제
- #include <stdio.h>
#include <string.h>
#define FILENAME "/usr/local/apache/cgi-bin/counter.dat" - int main() {
FILE *fp;
int counter=0;
char envc[255], *env; - env = getenv("HTTP_USER_AGENT");
- printf("Content-Type: text/html \n\n");
- if (!env)
exit(1); - strcpy(envc, env);
strtok(envc," "); - if((fp=fopen(FILENAME,"rt")) == NULL ) exit(1);
fscanf(fp,"%d",&counter);
fclose(fp);
printf("<FONT size=2><B>VISIT</B>: %d / <B>BROWSER</B>: %s</FONT>\n",counter, envc); - if((fp=fopen(FILENAME,"wt")) == NULL ) exit(1);
fprintf(fp,"%d\n",counter+1);
fclose(fp); - return 0;
}
버퍼오버플로우 취약점 제거 예제
- #include <stdio.h>
#include <string.h>
#define FILENAME "/usr/local/apache/cgi-bin/counter.dat" - int main() {
FILE *fp;
int counter=0;
char envc[255], *env; - env = getenv("HTTP_USER_AGENT");
printf("Content-Type: text/html \n\n"); - if (!env)
exit(1);
strncpy(envc, env, sizeof(envc)-1);
strtok(envc," ");- if((fp=fopen(FILENAME,"rt")) == NULL ) exit(1);
fscanf(fp,"%d",&counter);
fclose(fp);
printf("<FONT size=2><B>VISIT</B>: %d / <B>BROWSER</B>: %s</FONT>\n",counter, envc);
if((fp=fopen(FILENAME,"wt")) == NULL ) exit(1);
fprintf(fp,"%d\n",counter+1);
fclose(fp);- return 0;
}
3장 6절 악의적인 명령어 주입 공격 (SQL Injection) - 소스
□ ASP
취약한 SQL Injection 예제
- prodId = Request.QueryString("productId")
- Set conn = server.createObject("ADODB.Connection")
Set rs = server.createObject("ADODB.Recordset") - query = "select prodName from products where id = " & prodId
- conn.Open "Provider=SQLOLEDB; Data Source=(local);
Initial Catalog=productDB; User Id=dbid; Password="
rs.activeConnection = conn
rs.open query - If not rs.eof Then
response.write "제품명" & rs.fields("prodName").value
Else
response.write "제품이 없습니다"
End If
안전한 SQL Injection 예제
- prodId = Request.QueryString("productId")
prodId = replace(prodId, "'", "''")' 특수문자 제거
prodId = replace(prodId, ";", "")
set conn = server.createObject("ADODB.Connection")
set rs = server.createObject("ADODB.Recordset")
query = "select prodName from products where id = " & prodId
conn.Open "Provider=SQLOLEDB; Data Source=(local);
Initial Catalog=productDB; User Id=dbid; Password="
rs.activeConnection = conn
rs.open query
If not rs.eof Then
response.write "제품명" & rs.fields("prodName").value
Else
response.write "제품이 없습니다"
End If
□ PHP
취약한 SQL Injection 예제
- $query = "SELECT id, password, username FROM user_table WHERE id='$id'";
// 사용자로부터 입력받은 id 값을 사용자 table에서 조회
$result = OCIParse($conn, $query);
if (!OCIExecute($result))
echo "<META http-equiv=\"refresh\" content=\"0;URL=http://victim.com\">";
// 메인 페이지로 redirect - OCIFetchInto($result, &$rows);
... 중략 ...
안전한 SQL Injection 예제
- $query = sprintf("SELECT id,password,username FROM user_table WHERE id='%s';",addslashes($id));
// id변수를 문자형으로 받고, id변수의 특수문자를 일반문자로 변환한다. - // @ 로 php 에러 메시지를 막는다.
$result = @OCIParse($conn, $query);
if (!@OCIExecute($result))
error("SQL 구문 에러");
exit; - @OCIFetchInto($result,&$rows);
... 중략 ...
□ JSP
취약한 SQL Injection 예제
- String sql = "SELECT * FROM user_table" + " WHERE id = " + response.getParameter("id") + " AND password = " + response.getParameter("password");
- Class.forName("org.gjt.mm.mysql.Driver");
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); - stmt = conn.createStatement();
rs = stmt.executeQuery(query); - while(rs.next())
안전한 SQL Injection 예제
- String sql = "SELECT * FROM user_table" + " WHERE id = ?" + " AND password = ?";
ResultSet rs = null;
PreparedStatement pstmt = null;
try
conn = DBManager.getConnection();
pstmt = conn.prepareStatement(sql); - pstmt.setString(1, request.getParameter("id"));
pstmt.setString(2, request.getParameter("password")); - rs = pstmt.executeQuery();
3장 7절 업로드 취약점 - 소스
□ ASP
취약한 파일 업로드 예
- <%
Set Up = Server.CreateObject("SiteGalaxyUpload.Form") - uploadPath = server.mappath(".") & "\upload\"' 업로드 디렉토리
- Fname = Up("file1")
if Fname <> "" then'파일 첨부가 되었으면
fileName=Mid(Fname,InstrRev(Fname,"\")+1)'파일이름부분 추출
savePath = uploadPath & fileName - Set fso = CreateObject("Scripting.FileSystemObject")
Up("file1").SaveAs(savePath)
response.write(savePath & " 저장 완료")
else
response.write("Error")
end if - Set Up = nothing
%>
안전한 파일 업로드 예
- <%
Set Up = Server.CreateObject("SiteGalaxyUpload.Form")
Path1 = server.mappath(".") & "\upload\" - Fname = Up("file1")
- if Fname <> "" then'파일 첨부가 되었으면
- if Up("file1").Size > 10240 then' 용량 제한
Response.Write "용량 초과"
Response.End
end if - if Up("file1").MimeType <> "image" then' 이미지만 업로드 허용
Response.Write "이미지 파일이 아닙니다."
Response.End
end if - Filename=Mid(Fname,InstrRev(Fname,"\")+1)'파일이름부분 추출
- ' 중복시에 파일이름부분을 변경하기 위해 분리를 한다
Farry=split(Filename,".")'.을 기준으로 분리
preFname=Farry(0)'파일이름 앞부분
extFname=Farry(1)'파일의 확장자 - ' 저장할 전체 path를 만든다, 파일이름을 구한다
Path2 = Path1 & Filename
saveFname=preFname & "." & extFname
Set fso = CreateObject("Scripting.FileSystemObject")
countNo = 0' 파일 중복될경우 셋팅 값
fExist=0' 같은 이름의 파일 존재 체크- Do until fExist = 1
If(fso.FileExists(Path2)) Then
countNo = countNo + 1
Path2 = Path1 & preFname & countNo & "." & extFname
saveFname=preFname & countNo & "." & extFname
else
fExist=1
End If
Loop - Up("file1").SaveAs(Path2)
response.write(saveFname & " 저장완료")
else
response.write("Error")
end if - Set Up = nothing
%>
□ PHP
취약한 파일 업로드 예
- <?php
$uploaddir = '/var/www/uploads/'; - $uploadfile = $uploaddir. $_FILES['userfile']['name'];
- if(copy($_FILES['userfile']['tmp_name'], $uploadfile))
print "성공적으로 업로드 되었습니다.";
print_r($_FILES);
else
print "파일 업로드 실패";
print_r($_FILES); - ?>
안전한 파일 업로드 예
- <?php
$uploaddir = '/var/www/uploads/'; - //파일 사이즈가 0byte 보다 작거나 최대 업로드 사이즈보다 크면 업로드를 금지 시킨다.
if($_FILES['userfile']['name'])
if($_FILES['userfile']['size'] <= 0) // 최대 업로드 사이즈 체크 삽입
print "파일 업로드 에러";
exit; - //파일 이름의 특수문자가 있을 경우 업로드를 금지 시킨다.
if (eregi("[^a-z0-9\._\-]",$_FILES['userfile']['name']))
print "파일 이름의 특수문자 체크";
exit; - //파일 확장자중 업로드를 허용할 확장자를 정의한다.
$full_filename = explode(".", $_FILES['userfile']['name']);
$extension = $full_filename[sizeof($full_filename)-1]; - /* PHP의 경우 확장자 체크를 할 때 strcmp(확장자,"php3"); 로 체크를 하게 되면
pHp3 이나 phP3는 구별을 하지 못하게 되므로 strcasecmp처럼 대소문자 구별을 하지
않고 비교하는 함수를 사용한다. 또한 .를 기준으로 하여 확장자가 하나로 간주하고
프로그램을 할 경우 file.zip.php3 이라고 올린다면 zip파일로 인식하고 그냥 첨부가
되므로 아래와 같이 제일 끝에 존재하는 확장자를 기준으로 점검하도록 한다. */ - $extension= strtolower($extension);
if (!( ereg($extension","hwp") || ereg($extension","pdf") || ereg($extension","jpg")) )
print "업로드 금지 파일 입니다";
exit;
$uploadfile = $uploaddir. $_FILES['userfile']['name'];
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
print "파일이 존재하고, 성공적으로 업로드 되었습니다.";
print_r($_FILES);
else
print "파일 업로드 공격의 가능성이 있습니다! 디버깅 정보입니다:\n";
print_r($_FILES);- ?>
□ JSP
취약한 파일 업로드 예
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="com.oreilly.servlet.MultipartRequest,com.oreilly.servlet.multipart.DefaultFileRenamePolicy, java.util.*"%>
<%
String savePath="/var/www/uploads";// 업로드 디렉토리
int sizeLimit = 5 * 1024 * 1024 ;// 업로드 파일 사이즈 제한 - try
MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());
Enumeration formNames=multi.getFileNames();// 폼의 이름 반환
String formName=(String)formNames.nextElement();
String fileName=multi.getFilesystemName(formName);// 파일의 이름 얻기 - if(fileName == null)
out.print("Error");
else
fileName=new String(fileName.getBytes("8859_1"),"euc-kr");
out.print("User Name : " + multi.getParameter("userName") + "<BR>");
out.print("Form Name : " + formName + "<BR>");
out.print("File Name : " + fileName);
catch(Exception e)
out.print("Error");
%>
안전한 파일 업로드 예
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="com.oreilly.servlet.MultipartRequest,com.oreilly.servlet.multipart.DefaultFileRenamePolicy, java.util.*"%>
<%
String savePath="/var/www/uploads";// 업로드 디렉토리
int sizeLimit = 5 * 1024 * 1024 ; // 업로드 파일 사이즈 제한 - try
MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, "euc-kr", new DefaultFileRenamePolicy());
Enumeration formNames=multi.getFileNames(); // 폼의 이름 반환
String formName=(String)formNames.nextElement();
String fileName=multi.getFilesystemName(formName); // 파일의 이름 얻기 - String file_ext = fileName.substring(fileName.lastIndexOf('.') + 1);
if(!( file_ext.equalsIgnoreCase("hwp") || file_ext.equalsIgnoreCase("pdf") || file_ext.equalsIgnoreCase("jpg")) )
out.print("업로드 금지 파일");
if(fileName == null)
out.print("파일 업로드 실패");
else
fileName=new String(fileName.getBytes("8859_1"),"euc-kr"); // 한글인코딩
out.print("File Name : " + fileName);- catch(Exception e)
3장 8절 다운로드 취약점 - 소스
□ ASP
취약한 파일 다운로드 예
- <%
file = Request.Form ("file")'파일 이름 - Response.ContentType = "application/unknown"'ContentType 선언
Response.AddHeader "Content-Disposition","attachment; filename=" & file - Set objStream = Server.CreateObject("ADODB.Stream")'Stream 이용
- objStream.Open
objStream.Type = 1
objStream.LoadFromFile Server.MapPath("./upfiles/")&"\"& file '서버 절대경로 - download = objStream.Read
Response.BinaryWrite download - Set objStream = nothing'객체 초기화
안전한 파일 다운로드 예제
- <%
file = Request.Form ("file")'파일 이름 - Response.ContentType = "application/unknown"'ContentType 선언
Response.AddHeader "Content-Disposition","attachment; filename=" & file - Set objStream = Server.CreateObject("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
취약한 파일 다운로드 예
- $dn_path = "/var/www/data/$up_dir/$dn_file_name";
- //파일 전송 루틴
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");
안전한 파일 다운로드 예
- 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");
□ JSP
취약한 파일 다운로드 예
- String UPLOAD_PATH= "/var/www/upload/";
String filename= response.getParameter("filename");
String filepathname = UPLOAD_PATH + filename; - // 파일 전송 루틴
response.setContentType("application/unknown; charset=euc-kr");
response.setHeader("Content-Disposition","attachment;filename=" + filename + ";");
response.setHeader("Content-Transfer-Encoding:" , "base64"); - BufferedInputStream in = new BufferedInputStream(new FileInputStream(filepathname));
안전한 파일 다운로드 예
- 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)
// 에러 체크 [파일 존재 유무등]
[부록1] 개발 언어별 로그인 인증 프로세스 예제
1. ASP 예제
가. login.html
- <html>
<head>
<title> Login </title>
<script>
function check_submit()
if(!login.user_id.value)
alert("아이디를 입력하세요");
login.user_id.focus();
return false; - if(!login.password.value)
alert("아이디를 입력하세요");
login.password.focus();
return false; - return true;
- </script>
</head>
<body>
<form method=post action=login.asp onsubmit="return check_submit();" name=login>
<TABLE border=0>
<TR>
<TD>아이디</TD>
<TD><input type=text name="user_id" value="" maxlength=12 size=19></TD>
</TR>
<TR>
<TD>패스워드</TD>
<TD><input type=password name="password" value="" maxlength=12 size=19><input type=submit value="login"></TD>
</TR>
</TABLE>
</form>
</body>
</html>
나. login.asp
- <% Option Explicit %>
<%
Dim user_id, password
user_id = Request.Form("user_id")' 사용자로부터 입력 받은 아이디
password = Request.Form("password")' 사용자로부터 입력 받은 패스워드 - If UserAuth(user_id, password) <> 1 Then
Response.redirect("/login.html")' 인증 실패시 인증 페이지로 Redirect
Else
If Session("logged_in") <> 1 Then' 인증된 사용자 인지 체크
Session("logged_in") = 1' 인증에 성공했을경우 logged_in 에 1의 값을 셋팅
Session("user_id") = user_id' 사용자 ID 저장
Session("user_ip") = Request.Servervariables("REMOTE_ADDR")' IP 저장
End If
Response.redirect("/main.asp")' 인증 성공시 Main 페이지로 Redirect
End If
%> - <%
Function stripQuotes(strWords)
stripQuotes = replace(strWords, "'", "''")' 특수문자 제거
End Function - Function UserAuth(user_id, user_pwd)' 사용자 인증
Dim objConn, objRs
Dim strConnection, strQuery - Set objConn = Server.CreateObject("ADODB.Connection")
Set objRs = Server.CreateObject("ADODB.RecordSet") - ' DB 연결 정보, 별도의 헤더 파일로 관리하여 INCLUDE
strConnection = "DSN=MEMBER;uid=DBUSER;pwd=DBPASSWD" - On Error Resume Next' 에러가 생길경우
objConn.Open strConnection
objRs.ActiveConnection = objConn - strQuery = "SELECT * FROM user_tbl WHERE user_id= '" &_
stripQuotes(user_id) & "' AND password='" &_
stripQuotes(user_pwd) & "'"
objRs.Open strQuery - If objRs.BOF or objRs.EOF Then' 올바른 사용자를 찾지 못했을경우
UserAuth = 0
Else
UserAuth = 1
End If - objRs.Close' DB 연결 해제
Set objRs = Nothing
objConn.Close
Set objConn = Nothing
End Function
다. main.asp
- <%
If Session("user_ip") = Request.Servervariables("REMOTE_ADDR") AND Session("logged_in") = 1 Then
Response.Write Session("user_id") & "님은 " & Session("user_ip") & "에서 접속하셨습니다."
'인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
'... 중략 ...
Else
Response.write "허가되지 않은 사용자 입니다."
End If
%>
2. PHP
가. login.html
- <html>
<head>
<title> Login </title>
<script>
function check_submit()
if(!login.user_id.value)
alert("아이디를 입력하세요");
login.user_id.focus();
return false; - if(!login.password.value)
alert("아이디를 입력하세요");
login.password.focus();
return false; - return true;
- </script>
</head>
<body>
<form method=post action=login.php onsubmit="return check_submit();" name=login>
<TABLE border=0>
<TR>
<TD>아이디</TD>
<TD><input type=text name="user_id" value="" maxlength=12 size=19></TD>
</TR>
<TR>
<TD>패스워드</TD>
<TD><input type=password name="password" value="" maxlength=12 size=19><input type=submit value="login"></TD>
</TR>
</TABLE>
</form>
</body>
</html>
나. login.php
- <?PHP
@session_cache_limiter('nocache');
@session_start(); //세션 데이터를 초기화 - // form 에서 사용자 id와 사용자 password를 아래 변수로 전달
if(!UserAuth($_POST['user_id'],$_POST['password'])) //DB 에서 사용자 인증 처리하는 부분
header("Location: login.html");
exit;//인증 실패시 종료 - //인증에 성공한 경우 처리 해야 되는 부분
if (!session_is_registered("logged_in")) - $logged_in = 1;//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
$user_id = $_POST["user_id"];
$user_ip = $_SERVER["REMOTE_ADDR"];
session_register("logged_in");//인증 결과 저장
session_register("user_id");//사용자 ID를 저장
session_register("user_ip");//사용자 IP를 저장 - header("Location: main.php");
?>
<?PHP
function UserAuth($userid, $userpwd)
$connect = mysql_connect("localhost","DBUSER","DBPASSWD");
mysql_select_db("MEMBER"); - $strQuery = "SELECT * FROM user_tbl WHERE user_id ='" . addslashes($userid) . "' AND password='" . addslashes($userpwd) . "'";
$result = @mysql_query($strQuery);
if($result)
if(mysql_num_rows($result))
$data = mysql_fetch_array($result);
$userLevel = $data["level"];
@mysql_free_result($result);
@mysql_close($connect);
return 1; - return 0;
@mysql_close($connect);
return 0;
?>
다. main.php
- <?PHP
@session_start();
if(strcmp($_SESSION['user_ip'], $_SERVER['REMOTE_ADDR']) == 0 && session_is_registered('logged_in'))
//인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
//... 중략 ...
echo $_SESSION['user_id'] . "님은 " . $_SESSION['user_ip'] . "에서 접속하셨습니다.";
else
echo "허가되지 않은 사용자 입니다.";
exit; - ?>
3. JSP
가. login.html
- <html>
<head>
<title> Login </title>
<script>
function check_submit()
if(!login.user_id.value)
alert("아이디를 입력하세요");
login.user_id.focus();
return false;
if(!login.password.value)
alert("아이디를 입력하세요");
login.password.focus();
return false;- return true;
- </script>
</head>
<body>
<form method=post action=login.jsp onsubmit="return check_submit();" name=login>
<TABLE border=0>
<TR>
<TD>아이디</TD>
<TD><input type=text name="user_id" value="" maxlength=12 size=19></TD>
</TR>
<TR>
<TD>패스워드</TD>
<TD><input type=password name="password" value="" maxlength=12 size=19><input type=submit value="login"></TD>
</TR>
</TABLE>
</form>
</body>
</html>
나. login.jsp
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.*" %>
<%@ page import="java.sql.* " %> - <%
String DB_URL = "jdbc:mysql://127.0.0.1/MEMBER";// DB 연결 정보, 별도의 헤더 파일로 관리하여 INCLUDE
String DB_USER = "DBUSER";
String DB_PASSWORD= "DBPASSWD"; - //HttpSession session = request.getSession(true);// Servlet 의 경우만 추가
String user_ip = request.getRemoteAddr();// 연결된 사용자의 IP 획득
String user_id = null; - Connection conn;
PreparedStatement pstmt = null;
ResultSet rs = null; - try
Class.forName("org.gjt.mm.mysql.Driver");// 드라이버 등록
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);// DB연결
String query = "SELECT * FROM user_tbl WHERE user_id = ? AND password = ?";
pstmt = conn.prepareStatement(query); - pstmt.setString(1, request.getParameter("user_id"));// 사용자 입력값 전달
pstmt.setString(2, request.getParameter("password")); - rs = pstmt.executeQuery();
if(rs.next())
user_id = rs.getString(1);// DB에서 사용자 정보 획득
if(user_id != null)
if(session.getValue("logged_in") != "1") // 인증된 사용자 인지 체크
session.putValue("logged_in", "1");// SESSION에 사용자 정보 기록
session.putValue("user_id", user_id);
session.putValue("user_ip", user_ip);- //LogSave(user_id, user_ip);// 인증에 성공한 사용자 정보 기록
- response.sendRedirect("/main.jsp");// 인증 성공시 Main 페이지로 Redirect
else
response.sendRedirect("/login.html");// 인증 실패시 인증 페이지로 Redirect - catch(Exception ex) // 에러처리
out.println(ex);
finally // DB연결 종료
if(rs != null) try rs.close(); catch(SQLException ex)
if(pstmt != null) try pstmt.close(); catch(SQLException ex) - %>
나. main.jsp
- <%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.util.*" %> - <%
//HttpSession session = request.getSession(true); - if(session.getValue("user_ip") == request.getRemoteAddr() && session.getValue("logged_in") == "1")
//인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
//...
out.println(session.getValue("user_id") + " 님은 " + session.getValue("user_ip") + " 에서 접속하셨습니다.");
//... 중략 ...
else
response.sendRedirect("/login.html");// 인증 실패시 인증 페이지로 Redirect - %>