'접근통제 취약점'에 해당되는 글 1건

  1. 2009.10.05 접근통제 취약점
90.개발관련문서2009. 10. 5. 22:14
반응형

3장 1절 접근통제 취약점


□ 취약한 프로그래밍 예
  1. <HTML>
    <HEAD><TITLE> 관리자 페이지 </TITLE>
    <SCRIPT language="JavaScript“>
    function getCookie(name)
    var cname = name +"=";
    var dc = document.cookie;
  2. if(dc.length > 0)
    begin = dc.indexOf(cname);
    if(begin != -1)
    begin += cname.length;
    end = dc.indexOf(";", begin);
  3. if(end == -1) end = dc.length;
    retrun unescape(dc.substring(begin, end));

  4. return null;
  5. function getValue(element)
    var value = getCookie(element.name);
    if(value != null) element.value = value;
  6. </SCRIPT>
    </HEAD>
    <BODY>
    <SCRIPT language="JavaScript">
    var auth;
    auth = getCookie("logged_in");
  7. if(auth != 1) // 인증 성공 쿠키가 없을경우 Main Page로 이동
    window.location = "http://victim.com/login.html";
  8. </SCRIPT>
  9. 관리자 페이지 내용

□ 안전한 프로그래밍 예

ASP
  1. <%
    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")
  2. LogSave($userid, $user_ip)'접속에 사용한 ID 및 IP 기록
  3. ... 중략 ...
    End If
    End If
    %>

  4. o PHP
  5. <?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;//인증 실패시 종료

  6. //인증에 성공한 경우 처리 해야 되는 부분
    if (!session_is_registered("logged_in"))
  7. $logged_in = 1;//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
    $user_ip = $_SERVER["REMOTE_ADDR"];
    session_register("logged_in");//인증 결과 저장
    session_register("userid");//사용자 ID를 저장
    session_register("user_ip");//사용자 IP를 저장
  8. LogSave($userid, $user_ip);// 접속한 사용자 ID 및 IP 기록
    ... 중략 ...

JSP
  1. <%@ 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();
  2. // 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);
  3. LogSave(userid, user_ip);// 접속한 사용자 ID 및 IP기록
    ...


3장 2절 부적절한 파라미터 - 소스


□ ASP

취약한 프로그래밍 예
  1. <%
    strSize = Request.QueryString("font_size")'사용자로부터 폰트의 크기 입력
  2. Response.Write "<HTML><TITLE>사용자 입력값 검증</TITLE></HEAD>"
    Response.Write "<BODY>"
    Response.Write "<FONT size=" & strSize & ">글자 크기 조절</FONT>"
  3. ' ... 중략 ...

안전한 프로그래밍 예
  1. <%
    Size = Request.QueryString("font_size")' 사용자로부터 폰트의 크기 입력
  2. Size = CInt(Size)' 입력되는 값을 정수로 형 변환
  3. Response.Write "<HTML><TITLE>사용자 입력값 검증</TITLE></HEAD>"
    Response.Write "<BODY>"
    Response.Write "<FONT size=" & Size ">글자 크기 조절</FONT>"
  4. ' ... 중략 ...

□ PHP

취약한 프로그래밍 예
  1. <?PHP
    include "./inc/dbconn.inc";// DB 연결 헤더
    include $language . "/head.html";// 각 국가 언어별 HTML 출력
  2. $conn = mysql_connect($SERVER, $USER, $PASSWD);
    $query = "select count(*) from main_tbl";
  3. // ... 중략 ...

안전한 프로그래밍 예
  1. <?PHP
    @require_once "./inc/dbconn.inc";// DB 연결 헤더
    $default_lang = "korea";// 기본값 설정
  2. if(!file_exists($language."/head.html")) // 파일이 존재하는지 체크
    if(eregi(":\/\/", $language)) $language = $default_lang;// URL이 포함되는지 체크
    else // 파일이 없는 경우 기본값 설정
    $language = $default_lang;
  3. @require_once $language . "/head.html";// 각 국가 언어별 HTML 출력
  4. $conn = @mysql_connect($SERVER, $USER, $PASSWD);
    $query = "select count(*) from main_tbl";
  5. // ... 중략 ...

□ JSP

취약한 프로그래밍 예
  1. <%@ page contentType="text/html;charset=euc-kr" %>
    <%@ page import="java.util.* " %>
  2. <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>

안전한 프로그래밍 예
  1. <%@ page contentType="text/html;charset=euc-kr" %>
    <%@ page import="java.util.* " %>
  2. <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");
  3. // HTTP HEADER 중 USER_AGENT를 변경 하여 크로스사이트 스크립트 공격하는 것을 차단
    user_agent = user_agent.replaceAll("<","&lt;");// HTML tag가 있을 경우 제거
    user_agent = user_agent.replaceAll(">","&gt;");
  4. out.print("지금 사용하고 계신 ");
    out.print(user_agent);
    out.print(" 브라우져로는 사이트 접속이 불가능 합니다.");
  5. %>
    </BODY>
    </HTML>

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


□ ASP

취약한 프로그래밍 예
  1. '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
      ...
    %>
  2. user_menu.asp' 사용자 검증이 필요한 페이지
    <%
      IF Request.Cookies("logged_in") = 1 Then
        Response.write "허가된 사용자 입니다."
      Else
        Response.write "허가되지 않은 사용자 입니다."
      End If
    %>

안전한 프로그래밍 예
  1. ‘login_ok.asp 사용자 인증 처리를 하는 스크립트
    <%
    ' form 에서 사용자 id와 사용자 password를 아래 변수로 전달
    If myfunc_userauth(userid, userpw) <> 1 Then ' DB 에서 사용자 인증을 처리하는 부분
    Response.write "인증 실패"
    Else
    '인증에 성공한 경우 처리 해야 되는 부분
  2. 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
    ...
    %>
  3. ‘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

취약한 프로그래밍 예
  1. //login_ok.php// 사용자 인증 처리를 하는 스크립트
    <?PHP
    // form 에서 사용자 id와 사용자 password를 아래 변수로 전달
    if(!myfunc_userauth($userid,$userpw))  //DB 에서 사용자 인증을 처리하는 부분
    print "인증 실패";
    exit;//인증 실패시 종료

  2. //인증에 성공한 경우 처리 해야 되는 부분
    setcookie("logged_in", "1");//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
    setcookie("userid", $userid);
    ...
    ?>
  3. //user_menu.php// 사용자 검증이 필요한 페이지
    <?PHP
    if($_COOKIE["logged_in"] == 1)
    echo "인증 성공: " . $_COOKIE["userid"];
  4. ?>

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

 o 안전한 프로그래밍 예

  1. //login_ok.php// 사용자 인증 처리를 하는 스크립트
    <?PHP
    @session_start(); //세션 데이터를 초기화
    // form 에서 사용자 id와 사용자 password를 아래 변수로 전달
    if(!myfunc_userauth($userid,$userpw))  //DB 에서 사용자 인증을 처리하는 부분
    print "인증 실패";
    exit;//인증 실패시 종료
  2. //인증에 성공한 경우 처리 해야 되는 부분
    if (!session_is_registered("logged_in"))
  3. $logged_in = 1;//인증에 성공했을경우 logged_in 에 1의 값을 셋팅
    $user_ip = $_SERVER["REMOTE_ADDR"];
    session_register("logged_in");//인증 결과 저장
    session_register("userid");//사용자 ID를 저장
    session_register("user_ip");//사용자 IP를 저장
  4. ...
    ?>
  5. //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;
  6. ?>

□ JSP

취약한 프로그래밍 예
  1. <%@ 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);
    ...
    %>
  2. //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();

  3. if(logged_in.equals("1"))
    out.println("인증 성공: " + userid);
  4. %>

안전한 프로그래밍 예
  1. <%@ 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());
    ...
    %>
  2. //user_menu.jsp// 사용자 검증이 필요한 페이지
    <%
    //HttpSession session = request.getSession(true);
    String user_ip = session.getValue("user_ip");
  3. if(user_ip.equals(request.getRemoteAddr()) && logged_in.equals("1"))
    //인증에 성공한 IP와 사용자 IP를 비교, 인증 여부 비교
    //...
    else
    out.println "허가되지 않은 사용자 처리.";
  4. %>


3장 4절 악의적인 명령 실행(XSS) - 소스


□ ASP

취약한 프로그래밍 예
  1. <%
    Set objDBConn = Server.CreateObject("ADODB.Connection")' 게시물 읽기
    Set objRs = Server.CreateObject("ADODB.RecordSet")
    objDBConn.Open "board", "user", "passwd"
  2. query = "SELECT id, name, memo FROM board_tbl WHERE id=1"
    objRs.Open query, objDBConn
  3. memo = objRs("memo")
    Response.write "게시물 내용-" & memo & "<BR>"' DB에서 게시판의 내용 출력

안전한 프로그래밍 예
  1. If use_html Then' HTML tag를 사용하게 할 경우 부분 허용
    memo = Server.HTMLEncode(memo) 'HTML tag를 모두 제거
  2. ' 허용할 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>")
  3. Else' HTML tag를 사용하지 못하게 할 경우
    memo = Server.HTMLEncode(memo)' HTML encoding 수행
    memo = replace(memo, "<", "&lt;")
    memo = replace(memo, ">", "&gt;")
    End If
  4. Response.write "게시물 내용-" & memo & "<BR>"

□ PHP

취약한 프로그래밍 예
  1. $query = "SELECT id, name, memo FROM board_tbl WHERE id=1";// 게시물 읽기
    $result = mysql_query($query, $connect);
  2. while($row = mysql_fetch_array($result))
    $name = $row[name];
    $memo = $row[memo];
    echo "게시물 내용-" . $memo . "<BR>\n";// DB에서 게시판의 내용을 출력

안전한 프로그래밍 예
  1. $use_tag = "img,font,p,br";// 허용할 HTML tag
  2. if($use_html == 1) // HTML tag를 사용하게 할 경우 부분 허용
    $memo = str_replace("<", "&lt;", $memo);// HTML TAG를 모두 제거
  3. $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);
  4. else // HTML tag를 사용하지 못하게 할 경우
  5. // $memo = htmlspecialchars($memo);
    // htmlspecialchars() 사용시 일부 한글이 깨어지는 현상이 발생 할 수 있음
  6. $memo = str_replace("<", "&lt;", $memo);
    $memo = str_replace(">", "&gt;", $memo);

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

□ JSP

취약한 프로그래밍 예
  1. Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
    Statement stmt = conn.createStatement();
    ResultSet rs=null;
  2. String query = "SELECT memo FROM board_tbl WHERE id=1";
    rs = stmt.executeQuery(query);
    String memo = rs.getString(1);
    out.print("게시물 내용-" + memo + "<BR>");

안전한 프로그래밍 예
  1. if(use_html) // HTML tag를 사용하게 할 경우 부분 허용
    memo = memo.replaceAll("<","&lt;");//HTML tag를 모두 제거
    memo = memo.replaceAll(">","&gt;");
  2. // 허용할 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>");
  3. else // HTML tag를 사용하지 못하게 할 경우
    memo = memo.replaceAll("<","&lt;");
    memo = memo.replaceAll(">","&gt;");
  4. out.print("게시물 내용-" + memo + "<BR>");


3장 5절 버퍼 오버플로우 - 소스


□ strcpy() 함수의 대체

취약한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    strcpy(buffer, str);
    return;
    }

안전한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    strncpy(buffer, str, sizeof(buffer)-1);
    buffer[sizeof(buffer)-1] = 0;
    return;
    }

□ strcat() 함수의 대체

취약한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    strcat(buffer, str);
    return;
    }

안전한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    strncat(buffer, str, sizeof(buffer)-1);
    return;
    }

□ sprintf() 함수의 대체

취약한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    sprintf(buffer, "%s", str);
    return;
    }

 

□ gets() 함수의 대체

취약한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    gets(buffer);
    return;
    }

안전한 프로그래밍 예
  1. void func(char *str) {
    char buffer[256];
    fgets(buffer, sizeof(buffer)-1, stdin);
    return;
    }

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

취약한 프로그래밍 예
  1. void func() {
    char buffer[256];
    int num;
    num = fscanf(stdio, "%s", buffer); char buffer[256];
    return;
    }

안전한 프로그래밍 예
  1. void func() {
    char buffer[256];
    int num;
    num = fscanf(stdio, "%255s", buffer);
    return;
    }

□ C로 개발한 프로그램

버퍼오버플로우 취약점 예제
  1. #include <stdio.h>
    #include <string.h>
    #define FILENAME "/usr/local/apache/cgi-bin/counter.dat"
  2. int main() {
    FILE *fp;
    int counter=0;
    char envc[255], *env;
  3. env = getenv("HTTP_USER_AGENT");
  4. printf("Content-Type: text/html \n\n");
  5. if (!env)
                    exit(1);
  6. strcpy(envc, env);
    strtok(envc," ");
  7. 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);
  8. if((fp=fopen(FILENAME,"wt")) == NULL ) exit(1);
    fprintf(fp,"%d\n",counter+1);
    fclose(fp);
  9. return 0;
    }

버퍼오버플로우 취약점 제거 예제
  1. #include <stdio.h>
    #include <string.h>
    #define FILENAME "/usr/local/apache/cgi-bin/counter.dat"
  2. int main() {
    FILE *fp;
    int counter=0;
    char envc[255], *env;
  3. env = getenv("HTTP_USER_AGENT");
    printf("Content-Type: text/html \n\n");
  4. if (!env)
                    exit(1);

  5. strncpy(envc, env, sizeof(envc)-1);
    strtok(envc," ");
  6. 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);

  7. if((fp=fopen(FILENAME,"wt")) == NULL ) exit(1);
    fprintf(fp,"%d\n",counter+1);
    fclose(fp);
  8. return 0;
    }

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


□ ASP

취약한 SQL Injection 예제
  1. prodId = Request.QueryString("productId")
  2.  Set conn = server.createObject("ADODB.Connection")
     Set rs = server.createObject("ADODB.Recordset")
  3.  query = "select prodName from products where id = " & prodId
  4.  conn.Open "Provider=SQLOLEDB; Data Source=(local);
     Initial Catalog=productDB; User Id=dbid; Password="
     rs.activeConnection = conn
     rs.open query
  5.  If not rs.eof Then
     response.write "제품명" & rs.fields("prodName").value
     Else
     response.write "제품이 없습니다"
     End If

안전한 SQL Injection 예제
  1. 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 예제
  1. $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
  2. OCIFetchInto($result, &$rows);
    ... 중략 ...

안전한 SQL Injection 예제
  1. $query = sprintf("SELECT id,password,username FROM user_table WHERE id='%s';",addslashes($id));
    // id변수를 문자형으로 받고, id변수의 특수문자를 일반문자로 변환한다.
  2. // @ 로 php 에러 메시지를 막는다.
    $result = @OCIParse($conn, $query);
    if (!@OCIExecute($result))
    error("SQL 구문 에러");
    exit;
  3. @OCIFetchInto($result,&$rows);
    ... 중략 ...

□ JSP

취약한 SQL Injection 예제
  1. String sql = "SELECT * FROM user_table" + " WHERE id = " + response.getParameter("id") + " AND password = " + response.getParameter("password");
  2. Class.forName("org.gjt.mm.mysql.Driver");
    conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
  3. stmt = conn.createStatement();
    rs = stmt.executeQuery(query);
  4. while(rs.next())

안전한 SQL Injection 예제
  1. String sql = "SELECT * FROM user_table" + " WHERE id = ?" + " AND password = ?";
    ResultSet rs = null;
    PreparedStatement pstmt = null;
    try
    conn = DBManager.getConnection();
    pstmt = conn.prepareStatement(sql);
  2. pstmt.setString(1, request.getParameter("id"));
    pstmt.setString(2, request.getParameter("password"));
  3. rs = pstmt.executeQuery();

3장 7절 업로드 취약점 - 소스


□ ASP

취약한 파일 업로드 예
  1. <%
    Set Up = Server.CreateObject("SiteGalaxyUpload.Form")
  2. uploadPath = server.mappath(".") & "\upload\"' 업로드 디렉토리
  3. Fname = Up("file1")
    if Fname <> "" then'파일 첨부가 되었으면
    fileName=Mid(Fname,InstrRev(Fname,"\")+1)'파일이름부분 추출
    savePath = uploadPath & fileName
  4. Set fso = CreateObject("Scripting.FileSystemObject")
    Up("file1").SaveAs(savePath)
    response.write(savePath & " 저장 완료")
    else
    response.write("Error")
    end if
  5. Set Up = nothing
    %>

안전한 파일 업로드 예
  1. <%
    Set Up = Server.CreateObject("SiteGalaxyUpload.Form")
    Path1 = server.mappath(".") & "\upload\"
  2. Fname = Up("file1")
  3. if Fname <> "" then'파일 첨부가 되었으면
  4. if Up("file1").Size > 10240 then' 용량 제한
    Response.Write "용량 초과"
    Response.End
    end if
  5. if Up("file1").MimeType <> "image" then' 이미지만 업로드 허용
    Response.Write "이미지 파일이 아닙니다."
    Response.End
    end if
  6. Filename=Mid(Fname,InstrRev(Fname,"\")+1)'파일이름부분 추출
  7. ' 중복시에 파일이름부분을 변경하기 위해 분리를 한다
    Farry=split(Filename,".")'.을 기준으로 분리
    preFname=Farry(0)'파일이름 앞부분
    extFname=Farry(1)'파일의 확장자
  8. ' 저장할 전체 path를 만든다, 파일이름을 구한다
    Path2 = Path1 & Filename
    saveFname=preFname & "." & extFname

  9. Set fso = CreateObject("Scripting.FileSystemObject")
    countNo = 0' 파일 중복될경우 셋팅 값
    fExist=0' 같은 이름의 파일 존재 체크
  10. 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
  11. Up("file1").SaveAs(Path2)
    response.write(saveFname & " 저장완료")
    else
    response.write("Error")
    end if
  12. Set Up = nothing
    %>

□ PHP

취약한 파일 업로드 예
  1. <?php
    $uploaddir = '/var/www/uploads/';
  2. $uploadfile = $uploaddir. $_FILES['userfile']['name'];
  3. if(copy($_FILES['userfile']['tmp_name'], $uploadfile))
    print "성공적으로 업로드 되었습니다.";
    print_r($_FILES);
    else
    print "파일 업로드 실패";
    print_r($_FILES);
  4. ?>

안전한 파일 업로드 예
  1. <?php
    $uploaddir = '/var/www/uploads/';
  2. //파일 사이즈가 0byte 보다 작거나 최대 업로드 사이즈보다 크면 업로드를 금지 시킨다.
    if($_FILES['userfile']['name'])
    if($_FILES['userfile']['size'] <= 0)  // 최대 업로드 사이즈 체크 삽입
    print "파일 업로드 에러";
    exit;
  3. //파일 이름의 특수문자가 있을 경우 업로드를 금지 시킨다.
    if (eregi("[^a-z0-9\._\-]",$_FILES['userfile']['name']))
    print "파일 이름의 특수문자 체크";
    exit;
  4. //파일 확장자중 업로드를 허용할 확장자를 정의한다.
    $full_filename = explode(".", $_FILES['userfile']['name']);
    $extension = $full_filename[sizeof($full_filename)-1];
  5. /* PHP의 경우 확장자 체크를 할 때 strcmp(확장자,"php3"); 로 체크를 하게 되면
    pHp3 이나 phP3는 구별을 하지 못하게 되므로 strcasecmp처럼 대소문자 구별을 하지
    않고 비교하는 함수를 사용한다. 또한 .를 기준으로 하여 확장자가 하나로 간주하고
    프로그램을 할 경우 file.zip.php3 이라고 올린다면 zip파일로 인식하고 그냥 첨부가
    되므로 아래와 같이 제일 끝에 존재하는 확장자를 기준으로 점검하도록 한다. */
  6. $extension= strtolower($extension);
    if (!( ereg($extension","hwp") || ereg($extension","pdf") || ereg($extension","jpg")) )
    print "업로드 금지 파일 입니다";
    exit;

  7. $uploadfile = $uploaddir. $_FILES['userfile']['name'];
    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))
    print "파일이 존재하고, 성공적으로 업로드 되었습니다.";
    print_r($_FILES);
    else
    print "파일 업로드 공격의 가능성이 있습니다! 디버깅 정보입니다:\n";
    print_r($_FILES);
  8. ?>

□ JSP

취약한 파일 업로드 예
  1. <%@ 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 ;// 업로드 파일 사이즈 제한
  2. try
    MultipartRequest multi=new MultipartRequest(request, savePath, sizeLimit, new DefaultFileRenamePolicy());
    Enumeration formNames=multi.getFileNames();// 폼의 이름 반환
    String formName=(String)formNames.nextElement();
    String fileName=multi.getFilesystemName(formName);// 파일의 이름 얻기
  3. 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);

  4.  catch(Exception e)
    out.print("Error");
     
    %>

안전한 파일 업로드 예
  1. <%@ 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 ; // 업로드 파일 사이즈 제한
  2. 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); // 파일의 이름 얻기
  3. String file_ext = fileName.substring(fileName.lastIndexOf('.') + 1);
    if(!( file_ext.equalsIgnoreCase("hwp") || file_ext.equalsIgnoreCase("pdf") || file_ext.equalsIgnoreCase("jpg")) )
    out.print("업로드 금지 파일");

  4. if(fileName == null)
    out.print("파일 업로드 실패");
     else
    fileName=new String(fileName.getBytes("8859_1"),"euc-kr"); // 한글인코딩
    out.print("File Name  : " + fileName);
  5.  catch(Exception e)


3장 8절 다운로드 취약점 - 소스


□ ASP

취약한 파일 다운로드 예
  1. <%
    file = Request.Form ("file")'파일 이름
  2. Response.ContentType = "application/unknown"'ContentType 선언
    Response.AddHeader "Content-Disposition","attachment; filename=" & file
  3. Set objStream = Server.CreateObject("ADODB.Stream")'Stream 이용
  4. objStream.Open
    objStream.Type = 1
    objStream.LoadFromFile Server.MapPath("./upfiles/")&"\"& file '서버 절대경로
  5. download = objStream.Read
    Response.BinaryWrite download
  6. Set objStream = nothing'객체 초기화

안전한 파일 다운로드 예제
  1. <%
    file = Request.Form ("file")'파일 이름
  2. Response.ContentType = "application/unknown"'ContentType 선언
    Response.AddHeader "Content-Disposition","attachment; filename=" & file
  3. Set objStream = Server.CreateObject("ADODB.Stream")'Stream 이용
  4. strFile = Server.MapPath("./upfiles/") & "\" & file '서버 절대경로
    strFname=Mid(Fname,InstrRev(file,"\")+1) '파일 이름 추출, ..\ 등의 하위 경로 탐색은 제거 됨
    strFPath = Server.MapPath("./upfiles/") & "\" & strFname '웹서버의 파일 다운로드 절대 경로
  5. If strFile = strFPath Then'사용자가 다운 받는 파일과 웹서버의 파일 다운로드 경로가 맞는지 비교
    objStream.Open
    objStream.Type = 1
    objStream.LoadFromFile strFile
  6. download = objStream.Read
    Response.BinaryWrite download
    End If
    Set objstream = nothing'객체 초기화
    %>

□ PHP

취약한 파일 다운로드 예
  1. $dn_path = "/var/www/data/$up_dir/$dn_file_name";
  2. //파일 전송 루틴
    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");

안전한 파일 다운로드 예
  1. if (preg_match("/[^a-z0-9_-]/i",$up_dir))
    print "디렉토리에 특수문자 체크";
    exit;
  2. if (preg_match("/[^\xA1-\xFEa-z0-9._-]|\.\./i",urldecode($dn_file_name)))
    print "파일이름에 특수문자 체크";
    exit;
  3. $dn_path = "/var/www/data/$up_dir/$dn_file_name";
    if (!file_exists($dn_path))
    print "파일이 존재여부 체크";
    exit;
  4. //파일 전송 루틴
    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

취약한 파일 다운로드 예
  1. String UPLOAD_PATH= "/var/www/upload/";
    String filename= response.getParameter("filename");
    String filepathname = UPLOAD_PATH + filename;
  2. // 파일 전송 루틴
    response.setContentType("application/unknown; charset=euc-kr");
    response.setHeader("Content-Disposition","attachment;filename=" + filename + ";");
    response.setHeader("Content-Transfer-Encoding:" , "base64");
  3. BufferedInputStream in = new BufferedInputStream(new FileInputStream(filepathname));

안전한 파일 다운로드 예
  1. String UPLOAD_PATH= "/var/www/upload/";
    String filename= response.getParameter("filename");
    String filepathname = UPLOAD_PATH + filename;
  2. if(filename.equalsIgnoreCase("..") || filename.equalsIgnoreCase("/"))
    // 파일 이름 체크
    return 0;
  3. // 파일 전송 루틴
    response.setContentType("application/unknown; charset=euc-kr");
    response.setHeader("Content-Disposition","attachment;filename=" + filename + ";");
    response.setHeader("Content-Transfer-Encoding:" , "base64");
  4. try
    BufferedInputStream in = new BufferedInputStream(new FileInputStream(filepathname));
    .........
    catch(Exception e)
    // 에러 체크 [파일 존재 유무등]

[부록1] 개발 언어별 로그인 인증 프로세스 예제


1. ASP 예제
 가. login.html

  1. <html>
    <head>
    <title> Login </title>
    <script>
    function check_submit()
    if(!login.user_id.value)
    alert("아이디를 입력하세요");
    login.user_id.focus();
    return false;
  2. if(!login.password.value)
    alert("아이디를 입력하세요");
    login.password.focus();
    return false;
  3. return true;
  4. </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

  1. <% Option Explicit %>
    <%
    Dim user_id, password
    user_id = Request.Form("user_id")' 사용자로부터 입력 받은 아이디
    password = Request.Form("password")' 사용자로부터 입력 받은 패스워드
  2. 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
    %>
  3. <%
    Function stripQuotes(strWords)
    stripQuotes = replace(strWords, "'", "''")' 특수문자 제거
    End Function
  4. Function UserAuth(user_id, user_pwd)' 사용자 인증
    Dim objConn, objRs
    Dim strConnection, strQuery
  5. Set objConn = Server.CreateObject("ADODB.Connection")
    Set objRs = Server.CreateObject("ADODB.RecordSet")
  6. ' DB 연결 정보, 별도의 헤더 파일로 관리하여 INCLUDE
    strConnection = "DSN=MEMBER;uid=DBUSER;pwd=DBPASSWD"
  7. On Error Resume Next' 에러가 생길경우
    objConn.Open strConnection
    objRs.ActiveConnection = objConn
  8. strQuery = "SELECT * FROM user_tbl WHERE user_id= '" &_
    stripQuotes(user_id) & "' AND password='" &_
    stripQuotes(user_pwd) & "'"
    objRs.Open strQuery
  9. If objRs.BOF or objRs.EOF Then' 올바른 사용자를 찾지 못했을경우
    UserAuth = 0
    Else
    UserAuth = 1
    End If
  10. objRs.Close' DB 연결 해제
    Set objRs = Nothing
    objConn.Close
    Set objConn = Nothing
    End Function

다. main.asp

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

  1. <html>
    <head>
    <title> Login </title>
    <script>
    function check_submit()
    if(!login.user_id.value)
    alert("아이디를 입력하세요");
    login.user_id.focus();
    return false;
  2. if(!login.password.value)
    alert("아이디를 입력하세요");
    login.password.focus();
    return false;
  3. return true;
  4. </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

  1. <?PHP
    @session_cache_limiter('nocache');
    @session_start(); //세션 데이터를 초기화
  2. // form 에서 사용자 id와 사용자 password를 아래 변수로 전달
    if(!UserAuth($_POST['user_id'],$_POST['password'])) //DB 에서 사용자 인증 처리하는 부분
                    header("Location: login.html");
                    exit;//인증 실패시 종료
  3. //인증에 성공한 경우 처리 해야 되는 부분
    if (!session_is_registered("logged_in"))
  4. $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를 저장
  5. header("Location: main.php");
    ?>
    <?PHP
    function UserAuth($userid, $userpwd)
    $connect = mysql_connect("localhost","DBUSER","DBPASSWD");
    mysql_select_db("MEMBER");
  6. $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;
  7. return 0;
    @mysql_close($connect);
    return 0;
    ?>

다. main.php

  1. <?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;
  2. ?>

3. JSP

가. login.html

  1. <html>
    <head>
    <title> Login </title>
    <script>
    function check_submit()
    if(!login.user_id.value)
    alert("아이디를 입력하세요");
    login.user_id.focus();
    return false;

  2. if(!login.password.value)
    alert("아이디를 입력하세요");
    login.password.focus();
    return false;
  3. return true;
  4. </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

  1. <%@ page contentType="text/html;charset=euc-kr" %>
    <%@ page import="java.util.*" %>
    <%@ page import="java.sql.* " %>
  2. <%
    String DB_URL = "jdbc:mysql://127.0.0.1/MEMBER";// DB 연결 정보, 별도의 헤더 파일로 관리하여 INCLUDE
    String DB_USER = "DBUSER";
    String DB_PASSWORD= "DBPASSWD";
  3. //HttpSession session = request.getSession(true);// Servlet 의 경우만 추가
    String user_ip = request.getRemoteAddr();// 연결된 사용자의 IP 획득
    String user_id = null;
  4. Connection conn;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
  5. 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);
  6. pstmt.setString(1, request.getParameter("user_id"));// 사용자 입력값 전달
    pstmt.setString(2, request.getParameter("password"));
  7. rs = pstmt.executeQuery();
    if(rs.next())
    user_id = rs.getString(1);// DB에서 사용자 정보 획득

  8. 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);
  9. //LogSave(user_id, user_ip);// 인증에 성공한 사용자 정보 기록
  10. response.sendRedirect("/main.jsp");// 인증 성공시 Main 페이지로 Redirect
    else
    response.sendRedirect("/login.html");// 인증 실패시 인증 페이지로 Redirect
  11. 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)
  12. %>

나. main.jsp

  1. <%@ page contentType="text/html;charset=euc-kr" %>
    <%@ page import="java.util.*" %>
  2. <%
    //HttpSession session = request.getSession(true);
  3. 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
  4. %>



출처 :ㅣ http://dozob.springnote.com/pages/1472316

Posted by 1010