2013.04.04 11:00

################################################

접근통제 취약점

################################################

□ 취약한 프로그래밍 예

<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>

관리자 페이지 내용

==========================================================

□ 안전한 프로그래밍 예

o 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 기록
... 중략 ...


o 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기록
...

==========================================================

##################################################

부적절한 파라미터 - 소스

##################################################


□ ASP


o 취약한 프로그래밍 예

<%
strSize = Request.QueryString("font_size")'사용자로부터 폰트의 크기 입력

Response.Write "<HTML><TITLE>사용자 입력값 검증</TITLE></HEAD>"
Response.Write "<BODY>"
Response.Write "<FONT size=" & strSize & ">글자 크기 조절</FONT>"

' ... 중략 ...

===========================================================

o 안전한 프로그래밍 예

<%
Size = Request.QueryString("font_size")' 사용자로부터 폰트의 크기 입력

Size = CInt(Size)' 입력되는 값을 정수로 형 변환

Response.Write "<HTML><TITLE>사용자 입력값 검증</TITLE></HEAD>"
Response.Write "<BODY>"
Response.Write "<FONT size=" & Size ">글자 크기 조절</FONT>"

' ... 중략 ...

============================================================

□ PHP


o 취약한 프로그래밍 예


<?PHP
include "./inc/dbconn.inc";// DB 연결 헤더
include $language . "/head.html";// 각 국가 언어별 HTML 출력

$conn = mysql_connect($SERVER, $USER, $PASSWD);
$query = "select count(*) from main_tbl";

// ... 중략 ...

============================================================

o 안전한 프로그래밍 예

<?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

o 취약한 프로그래밍 예

<%@ 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>

=========================================================

o 안전한 프로그래밍 예

<%@ 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("<","&lt;");// HTML tag가 있을 경우 제거
user_agent = user_agent.replaceAll(">","&gt;");

out.print("지금 사용하고 계신 ");
out.print(user_agent);
out.print(" 브라우져로는 사이트 접속이 불가능 합니다.");

%>
</BODY>
</HTML>

==========================================================

##################################################

취약한 세션 관리 (Cookie Injection) - 소스

##################################################

□ ASP


o 취약한 프로그래밍 예

'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
%>

===========================================================

o 안전한 프로그래밍 예

‘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

o 취약한 프로그래밍 예

//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

o 취약한 프로그래밍 예

<%@ 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);

%>

==========================================================

o 안전한 프로그래밍 예

<%@ 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 "허가되지 않은 사용자 처리.";

%>

=======================================================

###############################################

악의적인 명령 실행(XSS) - 소스

###############################################

□ ASP

o 취약한 프로그래밍 예

<%
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에서 게시판의 내용 출력

============================================================

o 안전한 프로그래밍 예

If use_html Then' HTML tag를 사용하게 할 경우 부분 허용
memo = Server.HTMLEncode(memo) 'HTML tag를 모두 제거

' 허용할 HTML tag만 변경
memo = replace(memo, "&lt;p&gt;", "<p>")
memo = replace(memo, "&lt;P&gt;", "<P>")
memo = replace(memo, "&lt;br&gt;", "<br>")
memo = replace(memo, "&lt;BR&gt;", "<BR>")

Else' HTML tag를 사용하지 못하게 할 경우
memo = Server.HTMLEncode(memo)' HTML encoding 수행
memo = replace(memo, "<", "&lt;")
memo = replace(memo, ">", "&gt;")
End If

Response.write "게시물 내용-" & memo & "<BR>"

============================================================

□ PHP

o 취약한 프로그래밍 예

$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에서 게시판의 내용을 출력

=============================================================

o 안전한 프로그래밍 예

$use_tag = "img,font,p,br";// 허용할 HTML tag

if($use_html == 1) // HTML tag를 사용하게 할 경우 부분 허용
$memo = str_replace("<", "&lt;", $memo);// HTML TAG를 모두 제거

$tag = explode(",", $use_tag);
for($i=0; $i<count($tag); $i++) // 허용할 TAG만 사용 가능하게 변경
$memo = eregi_replace("&lt;".$tag[$i]." ", "<".$tag[$i]." ", $memo);
$memo = eregi_replace("&lt;".$tag[$i].">", "<".$tag[$i].">", $memo);
$memo = eregi_replace("&lt;/".$tag[$i], "</".$tag[$i], $memo);

else // HTML tag를 사용하지 못하게 할 경우

// $memo = htmlspecialchars($memo);
// htmlspecialchars() 사용시 일부 한글이 깨어지는 현상이 발생 할 수 있음

$memo = str_replace("<", "&lt;", $memo);
$memo = str_replace(">", "&gt;", $memo);


echo "게시물 내용-" . $memo . "<BR>\n";

===========================================================

□ JSP

o 취약한 프로그래밍 예

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>");

===========================================================

o 안전한 프로그래밍 예

if(use_html) // HTML tag를 사용하게 할 경우 부분 허용
memo = memo.replaceAll("<","&lt;");//HTML tag를 모두 제거
memo = memo.replaceAll(">","&gt;");

// 허용할 HTML tag만 변경
memo = memo.replaceAll("&lt;p&gt;", "<p>");
memo = memo.replaceAll("&lt;P&gt;", "<P>");
memo = memo.replaceAll("&lt;br&gt;", "<br>");
memo = memo.replaceAll("&lt;BR&gt;", "<BR>");

else // HTML tag를 사용하지 못하게 할 경우
memo = memo.replaceAll("<","&lt;");
memo = memo.replaceAll(">","&gt;");

out.print("게시물 내용-" + memo + "<BR>");

===========================================================

###################################################

버퍼 오버플로우 - 소스

###################################################

□ strcpy() 함수의 대체

o 취약한 프로그래밍 예

void func(char *str) {
char buffer[256];
strcpy(buffer, str);
return;
}

============================================================

o 안전한 프로그래밍 예

void func(char *str) {
char buffer[256];
strncpy(buffer, str, sizeof(buffer)-1);
buffer[sizeof(buffer)-1] = 0;
return;
}

=============================================================

□ strcat() 함수의 대체

o 취약한 프로그래밍 예

void func(char *str) {
char buffer[256];
strcat(buffer, str);
return;
}

==============================================================

o 안전한 프로그래밍 예

void func(char *str) {
char buffer[256];
strncat(buffer, str, sizeof(buffer)-1);
return;
}

==============================================================

□ sprintf() 함수의 대체

o 취약한 프로그래밍 예

void func(char *str) {
char buffer[256];
sprintf(buffer, "%s", str);
return;
}
========================================================

□ gets() 함수의 대체

o 취약한 프로그래밍 예

void func(char *str) {
char buffer[256];
gets(buffer);
return;
}

========================================================

o 안전한 프로그래밍 예

void func(char *str) {
char buffer[256];
fgets(buffer, sizeof(buffer)-1, stdin);
return;
}

========================================================

□ scanf(), sscanf(), fscanf() 함수의 대체

o 취약한 프로그래밍 예

void func() {
char buffer[256];
int num;
num = fscanf(stdio, "%s", buffer); char buffer[256];
return;
}

========================================================

o 안전한 프로그래밍 예

void func() {
char buffer[256];
int num;
num = fscanf(stdio, "%255s", buffer);
return;
}

========================================================

□ C로 개발한 프로그램

o 버퍼오버플로우 취약점 예제

#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;
}

======================================================

o 버퍼오버플로우 취약점 제거 예제

#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;
}

======================================================

##############################################

악의적인 명령어 주입 공격 (SQL Injection) - 소스

##############################################

□ ASP

o 취약한 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

=======================================================

o 안전한 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

o 취약한 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);
... 중략 ...

=======================================================

o 안전한 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

o 취약한 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())

========================================================

o 안전한 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();

=========================================================

#################################################

업로드 취약점 - 소스

#################################################

□ ASP

o 취약한 파일 업로드 예

<%
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
%>

========================================================

o 안전한 파일 업로드 예

<%
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

o 취약한 파일 업로드 예

<?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);

?>

=====================================================================

o 안전한 파일 업로드 예

<?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

o 취약한 파일 업로드 예

<%@ 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");

%>

=====================================================================

o 안전한 파일 업로드 예

<%@ 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)

===========================================================

###################################################

다운로드 취약점 - 소스

###################################################

□ ASP

o 취약한 파일 다운로드 예

<%
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'객체 초기화

==========================================================

o 안전한 파일 다운로드 예제

<%
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

o 취약한 파일 다운로드 예

$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");

==========================================================

o 안전한 파일 다운로드 예

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

o 취약한 파일 다운로드 예

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));

==========================================================

o 안전한 파일 다운로드 예

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. 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

%>

===========================================================

 

http://blog.naver.com/jaisonyi/40027002213

Posted by 물색없는세상