보안 강화를 위한 중간자 공격, 제한된 시간 및 횟수에 의하여 잠금 기능 및 일회용 인증키 검증하는 프로그래밍 가이드

댓글 0

▶ BaroSolution/BaroPAM

2020. 5. 4.

1. 개요

 

WAS(Web Application Server)에서 BaroPAM간 인증 프로그램 가이드는 어플리케이션 로그인/인증 시 비밀번호를 대체/인증하기 위한 중간자 공격(Man-in-the-middle attack, 양자간의 통신에 누군가가 개입하여, 도청이나 변경을 행하는 수법으로 로그 인 계정이나 개인정보의 도난, 스파이 행위, 통신 방해, 데이터 변경 등에 사용됨), 제한된 시간 및 횟수에 의하여 잠금 기능일회용 인증키를 검증하는 기능을 제공한다.

 

 

2. BaroPAM 모듈(barokey.jar)

 

어플리케이션 로그인/인증 시 비밀번호를 대체/인증하기 위한 중간자 공격(Man-in-the-middle attack), 제한된 시간 및 횟수에 의하여 잠금 기능일회용 인증키를 검증하는 API "barokey.jar"로 제공되며, WAS "~/WEB-INF/lib" 디렉토리에 "barokey.jar"를 위치 시켜야 한다.

 

/home/tomcat/webapps/ROOT/WEB-INF/lib > ls -al barokey.jar

-rw-r--r-- 1 root root 6746 12 29 07:43 barokey.jar

 

 

2.1 verifyKEYL 함수

 

- NAME

  verifyKEYL

 

- SYNOPSIS

  boolean bauth_key = barokey.verifyKEYL(String login_id, String phone_no, String cycle_time, String corr_time, String key_method, String auth_key);

 

- DESCRIPTION

  어플리케이션 로그인/인증 시 비밀번호를 대체/인증시 일회용 인증키를 검증하는 함수.

  login_id : 로그인-ID를 설정.

  phone_no : 스마트 폰 번호(숫자만 허용)를 설정.

  cycle_time : 일회용 인증키의 생성 주기(3~60)를 설정.

  corr_time : 일회용 인증키의 보증오차시간()으로 인증카드인 경우만 설정. (0)

  key_method : 일회용 인증키의 생성 방식(app1, app256, app384, app512: , card1, ard256,

                    card384, card512: 인증카드)을 설정.

  auth_key : 입력한 일회용 인증키를 설정.

 

- RETURN VALUES

  성공 시에는 true을 반환하며, 실패 시는 false을 반환한다.

 

 

2.2 verifyKEYP 함수

 

- NAME

  verifyKEYP

 

- SYNOPSIS

  boolean bauth_key = barokey.verifyKEYP(String secure_key, String cycle_time, String corr_time, String key_method, String auth_key);

 

- DESCRIPTION

  다양한 운영체제에서 2차 인증 및 어플리케이션 로그인/인증 시 비밀번호를 대체/인증시

  일회용 인증키를 검증하는 함수.

  secure_key : 벤더에서 제공한 서버별/개인별 Secure key를 설정.

  cycle_time : 일회용 인증키의 생성 주기를 설정. (3~60)

  corr_time : 일회용 인증키의 보증오차시간()으로 인증카드인 경우만 설정.

  key_method : 일회용 인증키의 생성 방식(app1, app256, app384, app512: , card1, ard256,

                    card384, card512: 인증카드)을 설정.

  auth_key : 입력한 일회용 인증키를 설정.

 

- RETURN VALUES

  성공 시에는 true을 반환하며, 실패 시는 false을 반환한다.

 

 

2.3 getCorrectionTime 함수

 

- NAME

  getCorrectionTime

 

- SYNOPSIS

  public static String getCorrectionTime(String secure_key, String cycle_time, String corr_time, String key_method, String auth_key)

 

- DESCRIPTION

  카드인 경우 카드의 시간과 서버의 시간 차이가 발생하는 시간()을 보정하는 함수.

  secure_key : 벤더에서 제공한 서버별/개인별 Secure key를 설정.

  cycle_time : 일회용 인증키의 생성 주기를 설정. (3~60)

  corr_time : 일회용 인증키의 보증오차시간()으로 인증카드인 경우만 설정.

  key_method : 일회용 인증키의 생성 방식(app1, app256, app384, app512: , card1, ard256,

                    card384, card512: 인증카드)을 설정.

  auth_key : 입력한 일회용 인증키를 설정.

 

- RETURN VALUES

  성공 시에는 보정오차 시간()을 반환하며, 실패 시는 "fail"을 반환한다.

 

 

2.4 checkRateLimit 함수

 

- NAME

  checkRateLimit

 

- SYNOPSIS

  public static String checkRateLimit(int rate_cnt, String rate_limit, long login_time)

 

- DESCRIPTION

  로그인/인증 시 중간자 공격에 대비하여 제한시간 및 횟수에 의하여 잠금 여부를 확인하는

  함수.

  rate_cnt : 로그인/인증 실패에 대한 제한하는 횟수를 설정.

  rate_limit : 로그인/인증 실패에 대한 시간(제한)을 설정.

  login_time : 로그인/인증을 요청한 시간을 설정.

 

- RETURN VALUES

  성공 시에는 로그인/인증을 요청한 시간을 추가한 제한시간과 잠김여부(Y or N)을 반환하며,

  실패 시는 ""을 반환한다.

 

 

3. 사용법(Java)

3.1 앱 인증인 경우

 

사용자정보 속성 예)

 

인증 프로그램 예)

package com.barokey.key;

 

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.util.Vector;

 

import org.apache.log4j.Logger;

import org.json.simple.JSONArray;

import org.json.simple.JSONObject;

 

import com.barokey.common.CommonLib;

import com.barokey.common.DBConnection;

import com.barokey.*;

……

/**

     * App 인증.

     *

     * @param auth_type

     * @param auth_use

     * @param user_no

     * @param auth_key

     * @param rate_cnt

     * @param ip_addr

     * @return result

     * @throws Exception

     */

    public String authAPP(String auth_type, String auth_use, String user_no, String auth_key, int rate_cnt, String ip_addr) throws Exception {

        /*--------------------------------------------------------------------*/

        /* 변수선언 및 초기화.                                                */

        /*--------------------------------------------------------------------*/

        int     ii = 0, jj = 0, kk = 0, ll = 0;           // Index

        Logger    logger = Logger.getLogger(this.getClass());

        CommonLib clib   = new CommonLib();               // CommonLib

        CardDAO   cdao   = new CardDAO();                 // CardDAO

        UserDAO   udao   = new UserDAO();                 // UserDAO

        BaroDTO   bdto   = new BaroDTO();                 // BaroDTO

 

        String  corr_time  = "fail";                      // 보정시간

        String  result     = "";                          // Result

        String  values     = "";                          // Return value

        boolean bauth_key  = false;                       // 인증키 검증

 

        long    login_time = 0;                           // Lock time

        String  rate_limit = "";                          // 제한 시간

        String  lock_yn    = "N";                         // Lock여부

        /*--------------------------------------------------------------------*/

        /* 처리 시작.                                                         */

        /*--------------------------------------------------------------------*/

        try {

            /*----------------------------------------------------------------*/

            /* 사용자정보 조회.                                               */

            /*----------------------------------------------------------------*/

            bdto = udao.read(user_no);

            /*----------------------------------------------------------------*/

            /* 사용자정보가 존재한 경우.                                      */

            /*----------------------------------------------------------------*/

            if (bdto != null) {

                /*------------------------------------------------------------*/

                /* 로그인 최종 시간 Edit.                                     */

                /*------------------------------------------------------------*/

                login_time = clib.get_timestamps() / (Long.parseLong(bdto.getCycle_time()) * 1000);

                /*------------------------------------------------------------*/

                /* 잠긴계정인 경우.                                           */

                /*------------------------------------------------------------*/

                if ("Y".equals(bdto.getLock_yn())) {

                    result = "10";

                /*------------------------------------------------------------*/

                /* 사용기간(From) 확인.                                       */

                /*------------------------------------------------------------*/

                } else if (Integer.parseInt(bdto.getUse_fr_dttm().replaceAll("-", "")) > Integer.parseInt(clib.nowDate().replaceAll("-", ""))) {

                    result = "03";

                /*------------------------------------------------------------*/

                /* 사용기간(To) 확인.                                         */

                /*------------------------------------------------------------*/

                } else if (Integer.parseInt(bdto.getUse_to_dttm().replaceAll("-", "")) < Integer.parseInt(clib.nowDate().replaceAll("-", ""))) {

                    result = "04";

                /*------------------------------------------------------------*/

                /* 사용하는 사용자인 경우.                                    */

                /*------------------------------------------------------------*/

                } else {

                    /*--------------------------------------------------------*/

                    /* 인증키인 경우.                                         */

                    /*--------------------------------------------------------*/

                    if (auth_key.length() == 6) {

                        logger.debug("barokey.verifyKEYL = [" + bdto.getUser_email() + "," + bdto.getUser_phone().replace("-", "") + "," + bdto.getCycle_time() + ",0," + bdto.getCreate_algorism() + "," + auth_key + "]");

                        /*----------------------------------------------------*/

                        /* 인증키 검증.                                       */

                        /*----------------------------------------------------*/

                        bauth_key = barokey.verifyKEYL(bdto.getUser_email(), bdto.getUser_phone().replace("-", ""), bdto.getCycle_time(), "0", bdto.getCreate_algorism(), auth_key);

                        logger.debug("barokey.verifyKEYL = [" + bdto.getUser_email() + "," + bdto.getUser_phone().replace("-", "") + "," + bdto.getCycle_time() + ",0," + bdto.getCreate_algorism() + "," + auth_key + "," + bauth_key + "]");

                    /*--------------------------------------------------------*/

                    /* PIN번호인 경우.                                        */

                    /*--------------------------------------------------------*/

                    } else {

                        /*----------------------------------------------------*/

                        /* PIN번호가 동일한 경우.                             */

                        /*----------------------------------------------------*/

                        if (auth_key.equals(bdto.getPin_no())) {

                            bauth_key = true;

                        /*----------------------------------------------------*/

                        /* Pin번호가 틀린한 경우.                             */

                        /*----------------------------------------------------*/

                        } else {

                            bauth_key = false;

                        }

                    }

                    /*--------------------------------------------------------*/

                    /* 인증키 검증(성공).                                     */

                    /*--------------------------------------------------------*/

                    if (bauth_key == true) {

                        /*----------------------------------------------------*/

                        /* 생성주기 내에 기인증 성공인 경우.                  */

                        /*----------------------------------------------------*/

                        if (Long.toString(login_time).equals(bdto.getLogin_time())) {

                            result = "12";

                        /*----------------------------------------------------*/

                        /* 인증 성공인 경우.                                  */

                        /*----------------------------------------------------*/

                        } else {

                            result = "00";

                            /*------------------------------------------------*/

                            /* 로그인 최종 시간을 Update.                     */

                            /*------------------------------------------------*/

                            udao.updateLoginTime(user_no, Long.toString(login_time), user_no);

                        }

                    /*--------------------------------------------------------*/

                    /* 인증키 검증(실패).                                     */

                    /*--------------------------------------------------------*/

                    } else {

                        result = "99";

                    }

                }

                /*------------------------------------------------------------*/

                /* 인증키 검증(실패).                                         */

                /*------------------------------------------------------------*/

                if (!"00".equals(result) && !"Y".equals(bdto.getLock_yn())) {

                    /*--------------------------------------------------------*/

                    /* 제한시간이 존재한 경우.                                */

                    /*--------------------------------------------------------*/

                    if (bdto.getRate_limit().trim().length() > 0) {

                        /*----------------------------------------------------*/

                        /* 제한회수 적용 Check.                               */

                        /*----------------------------------------------------*/

                        values = barokey.checkRateLimit(rate_cnt, bdto.getRate_limit().trim(), login_time);

                        /*----------------------------------------------------*/

                        /* 제한시간 확인하기 위해 대상 데이터를 분할.         */

                        /*----------------------------------------------------*/

                        String[] value = values.split(",");

 

                        if (value.length == 2) {

                            rate_limit = value[0];

                            lock_yn    = value[1];

                        }

                        logger.debug("rate_limit = [" + rate_limit + "," + lock_yn + "]");

                    /*--------------------------------------------------------*/

                    /* 제한시간이 존재하지 않은 경우.                         */

                    /*--------------------------------------------------------*/

                    } else {

                        rate_limit = Long.toString(login_time);

                        lock_yn    = "N";

                    }

                    logger.debug("rate_limit = [" + rate_limit + "," + lock_yn + "]");

                    /*--------------------------------------------------------*/

                    /* 제한 시간을 Update.                                    */

                    /*--------------------------------------------------------*/

                    udao.updateRateLimit(user_no, rate_limit, lock_yn, user_no);

                }

            /*----------------------------------------------------------------*/

            /* 사용자정보가 존재하지 않는 경우.                               */

            /*----------------------------------------------------------------*/

            } else {

                result = "01";

            }

            /*----------------------------------------------------------------*/

            /* 인증로그 정보를 insert.                                        */

            /*----------------------------------------------------------------*/

            createApp(user_no, auth_type, ip_addr, bdto.getUser_email(), bdto.getUser_phone(), bdto.getCycle_time(), auth_use, result);

        /*--------------------------------------------------------------------*/

        /* 예외사항 처리(Exception).                                          */

        /*--------------------------------------------------------------------*/

        } catch(Exception e) {

            logger.info("Exception = [" + e + "]");

            /*----------------------------------------------------------------*/

            /* 오류 메시지 StackTrace.                                        */

            /*----------------------------------------------------------------*/

            e.printStackTrace();

        /*--------------------------------------------------------------------*/

        /* 처리 종료.                                                         */

        /*--------------------------------------------------------------------*/

        } finally {

        }

        return result;

    }

 

 

3.2 카드인 경우

카드정보 속성 예)

인증 프로그램 예)

package com.barokey.key;

 

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.util.Vector;

 

import org.apache.log4j.Logger;

import org.json.simple.JSONArray;

import org.json.simple.JSONObject;

 

import com.barokey.common.CommonLib;

import com.barokey.common.DBConnection;

import com.barokey.*;

……

/**

     * 인증카드 인증.

     *

     * @param auth_type

     * @param auth_use

     * @param user_no

     * @param auth_key

     * @param rate_cnt

     * @param ip_addr

     * @return result

     * @throws Exception

     */

    public String authCARDS(String auth_type, String auth_use, String user_no, String auth_key, int rate_cnt, String ip_addr) throws Exception {

        /*--------------------------------------------------------------------*/

        /* 변수선언 및 초기화.                                                */

        /*--------------------------------------------------------------------*/

        int     ii = 0, jj = 0, kk = 0, ll = 0;           // Index

        Logger    logger = Logger.getLogger(this.getClass());

        CommonLib clib   = new CommonLib();               // CommonLib

        CardDAO   cdao   = new CardDAO();                 // CardDAO

        UserDAO   udao   = new UserDAO();                 // UserDAO

        BaroDTO   bdto   = new BaroDTO();                 // BaroDTO

 

        String  corr_time  = "fail";                      // 보정시간

        String  result     = "";                          // Result

        String  values     = "";                          // Return value

        boolean bauth_key  = false;                       // 인증키 검증

 

        long    login_time = clib.get_timestamps();       // Lock time

        String  rate_limit = "";                          // 제한 시간

        String  lock_yn    = "N";                         // Lock여부

        /*--------------------------------------------------------------------*/

        /* 처리 시작.                                                         */

        /*--------------------------------------------------------------------*/

        try {

            /*----------------------------------------------------------------*/

            /* 인증카드 정보 조회.                                            */

            /*----------------------------------------------------------------*/

            bdto = cdao.reads(user_no);

            /*----------------------------------------------------------------*/

            /* 인증카드 정보가 존재한 경우.                                   */

            /*----------------------------------------------------------------*/

            if (bdto != null) {

                /*------------------------------------------------------------*/

                /* 잠긴계정인 경우.                                           */

                /*------------------------------------------------------------*/

                if ("Y".equals(bdto.getLock_yn())) {

                    result = "10";

                /*------------------------------------------------------------*/

                /* 사용기간(From) 확인.                                       */

                /*------------------------------------------------------------*/

                } else if (Integer.parseInt(bdto.getUse_fr_dttm().replaceAll("-", "")) > Integer.parseInt(clib.nowDate().replaceAll("-", ""))) {

                    result = "03";

                /*------------------------------------------------------------*/

                /* 사용기간(To) 확인.                                         */

                /*------------------------------------------------------------*/

                } else if (Integer.parseInt(bdto.getUse_to_dttm().replaceAll("-", "")) < Integer.parseInt(clib.nowDate().replaceAll("-", ""))) {

                    result = "04";

                /*------------------------------------------------------------*/

                /* 카드상태가 미발급인 경우.                                  */

                /*------------------------------------------------------------*/

                } else if ("01".equals(bdto.getCard_status())) {

                    result = "11";

                /*------------------------------------------------------------*/

                /* 카드상태가 폐기인 경우.                                    */

                /*------------------------------------------------------------*/

                } else if ("03".equals(bdto.getCard_status())) {

                    result = "06";

                /*------------------------------------------------------------*/

                /* 분실카드인 경우.                                           */

                /*------------------------------------------------------------*/

                } else if ("02".equals(bdto.getAccident_yn())) {

                    result = "07";

                /*------------------------------------------------------------*/

                /* 보증기간(From) 확인.                                       */

                /*------------------------------------------------------------*/

                } else if (Integer.parseInt(bdto.getWarranty_fr_dttm().replaceAll("-", "")) > Integer.parseInt(clib.nowDate().replaceAll("-", ""))) {

                    result = "08";

                /*------------------------------------------------------------*/

                /* 보증기간(To) 확인.                                         */

                /*------------------------------------------------------------*/

                } else if (Integer.parseInt(bdto.getWarranty_to_dttm().replaceAll("-", "")) < Integer.parseInt(clib.nowDate().replaceAll("-", ""))) {

                    result = "09";

                /*------------------------------------------------------------*/

                /* 알고리즘인 hmac-sha2 base인 경우.                          */

                /*------------------------------------------------------------*/

                } else {

                    /*--------------------------------------------------------*/

                    /* 인증키 검증.                                           */

                    /*--------------------------------------------------------*/

                    bauth_key = barokey.verifyKEYP(bdto.getSecure_key(), bdto.getCycle_time(), bdto.getCorr_time(), bdto.getCreate_algorism(), auth_key);

                    logger.debug("barokey.verifyKEYP = [" + user_no + "," + bdto.getSecure_key() + "," + bdto.getCycle_time() + "," + corr_time + "," + bdto.getCreate_algorism() + "," + auth_key + "," + bauth_key + "]");

                }

                /*------------------------------------------------------------*/

                /* 인증키 검증(성공).                                         */

                /*------------------------------------------------------------*/

                if (bauth_key == true) {

                    /*--------------------------------------------------------*/

                    /* 로그인 최종시간 계산.                                  */

                    /*--------------------------------------------------------*/

                    login_time = (clib.get_timestamps() - (Long.parseLong(bdto.getCorr_time()) * 1000)) / (Long.parseLong(bdto.getCycle_time()) * 1000);

                    logger.debug("Last time = [" + clib.get_timestamps() + "," + login_time + "]");

                    /*--------------------------------------------------------*/

                    /* 생성주기 내에 기인증 성공인 경우.                      */

                    /*--------------------------------------------------------*/

                    if (Long.toString(login_time).equals(bdto.getLogin_time())) {

                        result = "12";

                    /*--------------------------------------------------------*/

                    /* 인증 성공인 경우.                                      */

                    /*--------------------------------------------------------*/

                    } else {

                        result = "00";

                        /*----------------------------------------------------*/

                        /* 로그인 최종 시간을 Update.                         */

                        /*----------------------------------------------------*/

                        udao.updateLoginTime(user_no, Long.toString(login_time), user_no);

                    }

                /*------------------------------------------------------------*/

                /* 인증키 검증(실패).                                         */

                /*------------------------------------------------------------*/

                } else {

                    /*--------------------------------------------------------*/

                    /* 보정시간 계산.                                         */

                    /*--------------------------------------------------------*/

                    corr_time = barokey.getCorrectionTime(bdto.getSecure_key(), bdto.getCycle_time(), bdto.getCorr_time(), bdto.getCreate_algorism(), auth_key);

                    /*--------------------------------------------------------*/

                    /* 보정시간 계산(실패).                                   */

                    /*--------------------------------------------------------*/

                    if ("fail".equals(corr_time)) {

                        result = "99";

                    /*--------------------------------------------------------*/

                    /* 보정시간 계산(성공).                                   */

                    /*--------------------------------------------------------*/

                    } else {

                        /*----------------------------------------------------*/

                        /* 보정시간 Update.                                   */

                        /*----------------------------------------------------*/

                        cdao.updateCorrTime(bdto.getCard_no(), corr_time);

                        /*----------------------------------------------------*/

                        /* 로그인 최종시간 계산.                              */

                        /*----------------------------------------------------*/

                        login_time = (clib.get_timestamps() - (Long.parseLong(bdto.getCorr_time()) * 1000)) / (Long.parseLong(bdto.getCycle_time()) * 1000);

                        logger.debug("Last time = [" + clib.get_timestamps() + "," + login_time + "," + corr_time + "]");

                        /*----------------------------------------------------*/

                        /* 생성주기 내에 기인증 성공인 경우.                  */

                        /*----------------------------------------------------*/

                        if (Long.toString(login_time).equals(bdto.getLogin_time())) {

                            result = "12";

                        /*----------------------------------------------------*/

                        /* 인증 성공인 경우.                                  */

                        /*----------------------------------------------------*/

                        } else {

                            result = "00";

                            /*------------------------------------------------*/

                            /* 로그인 최종 시간을 Update.                     */

                            /*------------------------------------------------*/

                            udao.updateLoginTime(user_no, Long.toString(login_time), user_no);

                        }

                    }

                }

                /*------------------------------------------------------------*/

                /* 인증키 검증(실패).                                         */

                /*------------------------------------------------------------*/

                if (!"00".equals(result) && !"Y".equals(bdto.getLock_yn())) {

                    /*--------------------------------------------------------*/

                    /* 제한시간이 존재한 경우.                                */

                    /*--------------------------------------------------------*/

                    if (bdto.getRate_limit().trim().length() > 0) {

                        /*----------------------------------------------------*/

                        /* 제한회수 적용 Check.                               */

                        /*----------------------------------------------------*/

                        values = barokey.checkRateLimit(rate_cnt, bdto.getRate_limit().trim(), login_time);

                        /*----------------------------------------------------*/

                        /* 제한시간 확인하기 위해 대상 데이터 분할.           */

                        /*----------------------------------------------------*/

                        String[] value = values.split(",");

 

                        if (value.length == 2) {

                            rate_limit = value[0];

                            lock_yn    = value[1];

                        }

                        logger.debug("rate_limit = [" + rate_limit + "]");

                    /*--------------------------------------------------------*/

                    /* 제한시간이 존재하지 않은 경우.                         */

                    /*--------------------------------------------------------*/

                    } else {

                        rate_limit = Long.toString(login_time);

                        lock_yn    = "N";

                    }

                    logger.debug("rate_limit = [" + rate_limit + "]");

                    /*--------------------------------------------------------*/

                    /* 제한 시간을 Update.                                    */

                    /*--------------------------------------------------------*/

                    udao.updateRateLimit(user_no, rate_limit, lock_yn, user_no);

                }

            /*----------------------------------------------------------------*/

            /* 인증카드 정보가 존재하지 않는 경우.                            */

            /*----------------------------------------------------------------*/

            } else {

                result = "03";

            }

            /*----------------------------------------------------------------*/

            /* 인증로그 정보를 insert.                                        */

            /*----------------------------------------------------------------*/

            createCard(user_no, auth_type, ip_addr, bdto.getCard_no(), bdto.getCycle_time(), auth_use, result);

        /*--------------------------------------------------------------------*/

        /* 예외사항 처리(Exception).                                          */

        /*--------------------------------------------------------------------*/

        } catch(Exception e) {

            logger.info("Exception = [" + e + "]");

            /*----------------------------------------------------------------*/

            /* 오류 메시지 StackTrace.                                        */

            /*----------------------------------------------------------------*/

            e.printStackTrace();

        /*--------------------------------------------------------------------*/

        /* 처리 종료.                                                         */

        /*--------------------------------------------------------------------*/

        } finally {

        }

        return result;

    }

 

 

3.3 인증결과

 

인증한 결과 다음과 같은 코드를 반환한다.

 

사업자 정보 표시
주식회사 누리아이티 | 이종일 | 서울시 강서구 공항대로 186 로뎀타워 617호 | 사업자 등록번호 : 258-87-00901 | TEL : 010-2771-4076 | Mail : mc529@nurit.co.kr | 사이버몰의 이용약관 바로가기