쪽지발송 성공
Click here
재능넷 이용방법
재능넷 이용방법 동영상편
가입인사 이벤트
판매 수수료 안내
안전거래 TIP
재능인 인증서 발급안내

🌲 지식인의 숲 🌲

🌳 디자인
🌳 음악/영상
🌳 문서작성
🌳 번역/외국어
🌳 프로그램개발
🌳 마케팅/비즈니스
🌳 생활서비스
🌳 철학
🌳 과학
🌳 수학
🌳 역사
해당 지식과 관련있는 인기재능

AS규정기본적으로 A/S 는 평생 가능합니다. *. 구매자의 요청으로 수정 및 보완이 필요한 경우 일정 금액의 수고비를 상호 협의하에 요청 할수 있...

안녕하세요!!!고객님이 상상하시는 작업물 그 이상을 작업해 드리려 노력합니다.저는 작업물을 완성하여 고객님에게 보내드리는 것으로 거래 완료...

30년간 직장 생활을 하고 정년 퇴직을 하였습니다.퇴직 후 재능넷 수행 내용은 쇼핑몰/학원/판매점 등 관리 프로그램 및 데이터 ...

  1.엑셀의 기본기능으로 하기 어렵거나 복잡한 내용 VBA로 자동화 2.셀메뉴형태 또는 리본메뉴형태의 프로그램 3.MY-SQ...

솔리디티 보안 취약점 분석 및 대응 방안

2024-10-05 23:21:37

재능넷
조회수 521 댓글수 0

솔리디티 보안 취약점 분석 및 대응 방안 🛡️💻

 

 

안녕? 오늘은 솔리디티 보안에 대해 재밌고 쉽게 설명해볼게. 솔리디티는 이더리움 기반의 스마트 컨트랙트를 개발하는 데 사용되는 프로그래밍 언어야. 근데 이게 왜 중요하냐고? 바로 블록체인 세계에서 엄청난 영향력을 가지고 있거든! 😎

우리가 재능넷 같은 플랫폼에서 다양한 재능을 거래하듯이, 블록체인에서도 스마트 컨트랙트를 통해 다양한 거래와 상호작용이 일어나. 그런데 이 스마트 컨트랙트에 보안 취약점이 있다면? 음... 생각만 해도 아찔하지? 그래서 오늘은 솔리디티의 보안 취약점과 그에 대한 대응 방안에 대해 깊이 있게 파헤쳐볼 거야. 준비됐니? 그럼 시작해보자고! 🚀

💡 알아두면 좋은 점: 솔리디티 보안은 단순히 코드를 안전하게 작성하는 것을 넘어서, 블록체인 생태계 전체의 신뢰성과 안정성을 지키는 중요한 역할을 해. 마치 재능넷에서 거래의 신뢰성을 지키는 것처럼 말이야!

1. 재진입 공격 (Reentrancy Attack) 🔄

자, 이제 본격적으로 솔리디티의 보안 취약점에 대해 알아볼 건데, 첫 번째로 소개할 녀석은 바로 '재진입 공격'이야. 이름부터 좀 무서워 보이지? 😱

재진입 공격이 뭔지 쉽게 설명해줄게. 상상해봐, 네가 은행에 가서 돈을 인출하려고 해. 근데 은행원이 잠깐 정신을 잃은 사이에 네가 계속해서 돈을 인출한다면? 이게 바로 재진입 공격의 개념이야.

재진입 공격은 스마트 컨트랙트의 함수가 완전히 실행되기 전에 다시 호출되는 취약점을 이용한 공격이야.

이 공격은 특히 이더를 전송하는 함수에서 자주 발생해. 왜 그럴까? 이더를 전송하는 과정에서 외부 컨트랙트의 fallback 함수가 호출될 수 있기 때문이지.

🎭 재진입 공격 시나리오:

  1. 공격자가 악의적인 컨트랙트를 만들어.
  2. 이 컨트랙트는 취약한 컨트랙트의 출금 함수를 호출해.
  3. 취약한 컨트랙트가 이더를 전송하면, 공격자의 컨트랙트의 fallback 함수가 실행돼.
  4. fallback 함수에서 다시 출금 함수를 호출해.
  5. 이 과정이 반복되면서 컨트랙트의 모든 이더를 탈취할 수 있어.

이제 실제 코드로 어떻게 재진입 공격이 일어나는지 볼까? 아래는 취약한 컨트랙트의 예시야:


contract VulnerableContract {
    mapping(address => uint) public balances;

    function withdraw() public {
        uint bal = balances[msg.sender];
        require(bal > 0);
        (bool sent, ) = msg.sender.call{value: bal}("");
        require(sent, "Failed to send Ether");
        balances[msg.sender] = 0;
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }
}

이 컨트랙트에서 withdraw 함수를 보면, 이더를 전송한 후에 잔액을 0으로 설정하고 있어. 이게 바로 문제야! 공격자는 이 틈을 노려서 재진입 공격을 시도할 수 있어.

그럼 이제 공격자의 컨트랙트를 한번 볼까?


contract AttackerContract {
    VulnerableContract public vulnerableContract;

    constructor(address _vulnerableContractAddress) {
        vulnerableContract = VulnerableContract(_vulnerableContractAddress);
    }

    function attack() external payable {
        vulnerableContract.deposit{value: 1 ether}();
        vulnerableContract.withdraw();
    }

    receive() external payable {
        if (address(vulnerableContract).balance >= 1 ether) {
            vulnerableContract.withdraw();
        }
    }
}

이 공격자 컨트랙트는 attack 함수를 통해 취약한 컨트랙트에 1 이더를 입금하고 바로 출금을 요청해. 그리고 receive 함수에서 다시 출금을 요청하는 걸 볼 수 있어. 이렇게 하면 취약한 컨트랙트의 잔액이 0이 될 때까지 계속해서 출금이 이루어지는 거지.

그럼 이런 재진입 공격을 어떻게 막을 수 있을까? 여기 몇 가지 방법을 소개할게:

  1. Checks-Effects-Interactions 패턴 사용: 이 패턴은 상태를 변경하는 코드를 외부 호출 전에 실행해. 위의 예시에서는 잔액을 0으로 만드는 코드를 이더 전송 전에 실행하면 돼.
  2. 재진입 가드 사용: 함수 실행 중에는 다시 호출될 수 없도록 잠금 장치를 만들어.
  3. send() 또는 transfer() 사용: 이 함수들은 2300 gas만을 전달하기 때문에, 복잡한 로직을 실행하기 어려워져.

자, 이제 안전한 컨트랙트는 어떻게 생겼는지 볼까?


contract SafeContract {
    mapping(address => uint) public balances;
    bool private locked;

    modifier noReentrant() {
        require(!locked, "No re-entrancy");
        locked = true;
        _;
        locked = false;
    }

    function withdraw() public noReentrant {
        uint bal = balances[msg.sender];
        require(bal > 0);
        balances[msg.sender] = 0;
        (bool sent, ) = msg.sender.call{value: bal}("");
        require(sent, "Failed to send Ether");
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }
}

이 안전한 컨트랙트에서는 재진입 가드(noReentrant 수정자)를 사용하고, Checks-Effects-Interactions 패턴을 적용했어. 이렇게 하면 재진입 공격을 효과적으로 막을 수 있지!

재진입 공격 시각화 취약한 컨트랙트 공격자 컨트랙트 재진입 공격

와, 재진입 공격에 대해 꽤 깊이 있게 알아봤네! 😄 이런 보안 지식은 블록체인 개발자에게 정말 중요해. 마치 재능넷에서 거래의 안전성을 지키는 것처럼, 스마트 컨트랙트의 안전성도 꼭 지켜야 하거든.

다음으로는 또 다른 중요한 보안 취약점에 대해 알아볼 거야. 준비됐니? 계속 가보자고! 🚀

2. 정수 오버플로우와 언더플로우 (Integer Overflow and Underflow) 🔢

자, 이번에 알아볼 보안 취약점은 '정수 오버플로우와 언더플로우'야. 이름만 들어도 뭔가 수학적인 느낌이 나지? 맞아, 이건 숫자와 관련된 취약점이야. 😎

정수 오버플로우와 언더플로우가 뭔지 간단히 설명해줄게. 상상해봐, 네가 자전거 계기판을 가지고 있다고 해. 이 계기판은 999km까지만 표시할 수 있어. 근데 넌 1000km를 달렸어. 그러면 계기판은 어떻게 될까? 바로 000km로 돌아가겠지? 이게 바로 오버플로우야. 반대로, 계기판이 000km일 때 뒤로 1km를 가면 999km가 되는 거, 이게 언더플로우야.

정수 오버플로우는 변수가 저장할 수 있는 최대값을 초과할 때 발생하고, 언더플로우는 최소값보다 작아질 때 발생해.

솔리디티에서 이런 현상이 일어나면? 음... 생각만 해도 아찔하지? 😱

🎭 정수 오버플로우/언더플로우 시나리오:

  1. 토큰 컨트랙트에서 사용자의 잔액을 uint8(0~255)로 저장해.
  2. 사용자가 256개의 토큰을 받으면? 잔액이 0이 돼! (오버플로우)
  3. 반대로, 잔액이 0일 때 1개를 빼면? 잔액이 255가 돼! (언더플로우)

이제 실제 코드로 어떻게 정수 오버플로우와 언더플로우가 일어나는지 볼까? 아래는 취약한 컨트랙트의 예시야:


contract VulnerableToken {
    mapping(address => uint8) public balances;

    function transfer(address _to, uint8 _value) public {
        balances[msg.sender] -= _value;
        balances[_to] += _value;
    }
}

이 컨트랙트에서 balances 맵핑은 uint8을 사용하고 있어. uint8은 0부터 255까지의 값만 저장할 수 있지. 그래서 256이 되면 다시 0으로 돌아가고, -1이 되면 255가 돼.

이런 취약점을 이용한 공격 시나리오를 한번 볼까?


contract AttackerContract {
    VulnerableToken public vulnerableToken;

    constructor(address _vulnerableTokenAddress) {
        vulnerableToken = VulnerableToken(_vulnerableTokenAddress);
    }

    function attack(address _victim) public {
        // 피해자로부터 1 토큰을 가져와 (언더플로우 발생)
        vulnerableToken.transfer(address(this), 1);
        
        // 이제 공격자는 255 토큰을 가지게 됨
        // 모든 토큰을 다른 주소로 전송
        vulnerableToken.transfer(_victim, 255);
    }
}

이 공격자 컨트랙트는 피해자의 잔액이 0일 때 1 토큰을 가져와. 그러면 언더플로우가 발생해서 공격자의 잔액이 255가 돼. 그리고 이 255 토큰을 모두 다른 주소로 전송하는 거지. 결과적으로 공격자는 1개의 토큰으로 255개의 토큰을 만들어낸 셈이야!

그럼 이런 정수 오버플로우와 언더플로우를 어떻게 막을 수 있을까? 여기 몇 가지 방법을 소개할게:

  1. SafeMath 라이브러리 사용: OpenZeppelin의 SafeMath 라이브러리를 사용하면 자동으로 오버플로우와 언더플로우를 체크해줘.
  2. 더 큰 데이터 타입 사용: uint8 대신 uint256을 사용하면 오버플로우가 발생할 가능성이 훨씬 줄어들어.
  3. 수동으로 체크: 연산 전후로 값을 체크해서 오버플로우나 언더플로우가 발생하지 않도록 해.

자, 이제 안전한 컨트랙트는 어떻게 생겼는지 볼까?


import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract SafeToken {
    using SafeMath for uint256;
    
    mapping(address => uint256) public balances;

    function transfer(address _to, uint256 _value) public {
        require(balances[msg.sender] >= _value, "Insufficient balance");
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
    }
}

이 안전한 컨트랙트에서는 SafeMath 라이브러리를 사용하고 있어. 또한 uint8 대신 uint256을 사용해서 오버플로우의 가능성을 크게 줄였지. 그리고 transfer 함수에서는 잔액 체크도 하고 있어. 이렇게 하면 정수 오버플로우와 언더플로우를 효과적으로 막을 수 있어!

정수 오버플로우/언더플로우 시각화 0 64 128 192 오버플로우 언더플로우

와, 정수 오버플로우와 언더플로우에 대해 꽤 깊이 있게 알아봤네! 😄 이런 보안 지식은 스마트 컨트랙트 개발에서 정말 중요해. 마치 재능넷에서 거래 금액을 정확하게 계산하는 것처럼, 스마트 컨트랙트에서도 숫자를 정확하게 다루는 게 중요하거든.

다음으로는 또 다른 중요한 보안 취약점에 대해 알아볼 거야. 준비됐니? 계속 가보자고! 🚀

3. 접근 제어 취약점 (Access Control Vulnerabilities) 🔐

이번에 알아볼 보안 취약점은 '접근 제어 취약점'이야. 이건 뭔가 문을 지키는 경비원과 관련이 있을 것 같은 느낌이 들지? 맞아, 정확히 그거야! 😎

접근 제어 취약점이 뭔지 쉽게 설명해줄게. 상상해봐, 네가 운영하는 비밀 클럽이 있어. 이 클럽에는 특별한 회원만 들어갈 수 있어. 근데 문지기가 잠깐 졸았더니 아무나 다 들어와버렸어! 이게 바로 접근 제어 취약점이야.

접근 제어 취약점은 스마트 컨트랙트에서 중요한 함수나 데이터에 대한 접근을 제대로 제한하지 않았을 때 발생해.

이런 취약점이 있으면 권한이 없는 사용자가 중요한 기능을 실행하거나 민감한 데이터를 볼 수 있게 돼. 음... 생각만 해도 아찔하지? 😱

🎭 접근 제어 취약점 시나리오:

  1. 스마트 컨트랙트에 관리자만 실행할 수 있는 함수가 있어.
  2. 하지만 이 함수에 접근 제어가 제대로 구현되어 있지 않아.
  3. 악의적인 사용자가 이 함수를 호출해서 컨트랙트의 중요한 상태를 변경해버려!
  4. 결과적으로 컨트랙트의 보안이 완전히 무너지게 돼.

이제 실제 코드로 어떻게 접근 제어 취약점이 발생하는지 볼까? 아래는 취약한 컨트랙트의 예시야:


contract VulnerableBank {
    mapping(address => uint) public balances;
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint _amount) public {
        require(balances[msg.sender] >= _amount);
        balances[msg.sender] -= _amount;
        payable(msg.sender).transfer(_amount);
    }

    function drainBank() public {
        payable(msg.sender).transfer(address(this).balance);
    }
}

이 컨트랙트에서 drainBank 함수를 봐. 이 함수는 컨트랙트의 모든 잔액을 호출자에게 전송해. 원래 이 함수는 오너만 호출할 수 있어야 하는데, 아무런 접근 제어가 없어! 이건 정말 위험한 상황이야.

이런 취약점을 이용한 공격 시나리오를 한번 볼까?


contract AttackerContract {
    VulnerableBank public vulnerableBank;

    constructor(address _vulnerableBankAddress) {
        vulnerableBank = VulnerableBank(_vulnerableBankAddress);
    }

    function attack() public {
        vulnerableBank.drainBank();
    }

    receive() external payable {}
}

이 공격자 컨트랙트는 단순히 drainBank 함수를 호출해. 그리고 받은 이더는 receive 함수를 통해 처리해. 이렇게 하면 취약한 은행 컨트랙트의 모든 자금을 탈취할 수 있어!

그럼 이런 접근 제어 취약점을 어떻게 막을 수 있을까? 여기 몇 가지 방법을 소개할게:

  1. 함수 수정자(modifier) 사용: 특정 조건을 만족해야만 함수를 실행할 수 있도록 제한해.
  2. 명시적인 접근 제어 체크: 함수 내에서 직접 호출자의 권한을 확인해.
  3. 역할 기반 접근 제어(RBAC) 구현: 더 복잡한 시스템에서는 여러 역할과 권한을 정의하고 관리해.

자, 이제 안전한 컨트랙트는 어떻게 생겼는지 볼까?


contract SafeBank {
    mapping(address => uint) public balances;
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not the owner");
        _;
    }

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint _amount) public {
        require(balances[msg.sender] >= _amount, "Insufficient balance");
        balances[msg.sender] -= _amount;
        payable(msg.sender).transfer(_amount);
    }

    function drainBank() public onlyOwner {
        payable(owner).transfer(address(this).balance);
    }
}

이 안전한 컨트랙트에서는 onlyOwner 수정자를 사용해서 drainBank 함수에 접근 제어를 구현했어. 이제 오너만이 이 함수를 호출할 수 있게 됐지. 또한 withdraw 함수에도 잔액 체크를 추가해서 더 안전해졌어!

접근 제어 시각화 접근 제어 관리자 해커

와, 접근 제어 취약점에 대해 꽤 깊이 있게 알아봤네! 😄 이런 보안 지식은 스마트 컨트랙트 개발에서 정말 중요해. 마치 재능넷에서 관리자 권한을 잘 관리하는 것처럼, 스마트 컨트랙트에서도 접근 권한을 잘 관리하는 게 중요하거든.

자, 이제 우리가 살펴본 세 가지 주요 보안 취약점에 대해 정리해볼까? 🤔

📌 솔리디티 주요 보안 취약점 요약

  1. 재진입 공격 (Reentrancy Attack)
    • 문제: 외부 호출 후 상태 변경으로 인한 취약점
    • 해결: Checks-Effects-Interactions 패턴, 재진입 가드 사용
  2. 정수 오버플로우와 언더플로우 (Integer Overflow and Underflow)
    • 문제: 숫자 타입의 한계로 인한 예상치 못한 값 변화
    • 해결: SafeMath 라이브러리 사용, 큰 데이터 타입 사용
  3. 접근 제어 취약점 (Access Control Vulnerabilities)
    • 문제: 중요 기능에 대한 부적절한 접근 제어
    • 해결: 함수 수정자 사용, 명시적 접근 제어 체크

이 세 가지 취약점은 솔리디티 개발에서 가장 흔하고 위험한 문제들이야. 하지만 걱정하지 마! 우리가 배운 방법들을 잘 적용하면 이런 취약점들을 효과적으로 막을 수 있어. 😊

솔리디티 개발을 할 때는 항상 이런 보안 이슈들을 염두에 두고 코딩해야 해. 또한, 정기적인 보안 감사(audit)를 받는 것도 좋은 방법이야. 전문가의 눈으로 한 번 더 검토받으면 놓친 부분을 발견할 수 있거든.

그리고 잊지 마, 블록체인 기술은 계속 발전하고 있어. 새로운 취약점이 발견될 수도 있고, 새로운 보안 기술이 나올 수도 있어. 그래서 항상 최신 트렌드를 따라가는 것이 중요해. 마치 재능넷에서 새로운 기능과 보안 업데이트를 계속 적용하는 것처럼 말이야! 🚀

자, 이제 우리의 솔리디티 보안 여행이 거의 끝나가고 있어. 마지막으로 몇 가지 팁을 더 줄게:

💡 추가 보안 팁

  • 항상 최신 버전의 솔리디티를 사용해. 새 버전에는 보안 패치가 포함되어 있을 수 있어.
  • 테스트를 많이 해. 단위 테스트, 통합 테스트, 퍼징 테스트 등 다양한 테스트를 실행해봐.
  • 오픈소스 라이브러리를 사용할 때는 신중해야 해. 잘 알려진, 감사받은 라이브러리를 선택해.
  • 형변환(type casting)을 할 때는 특히 주의해. 예상치 못한 동작이 발생할 수 있어.
  • 이벤트를 적극적으로 사용해. 중요한 상태 변경을 추적하는 데 도움이 돼.

와, 정말 많은 내용을 다뤘네! 😄 솔리디티 보안은 정말 중요하고 깊이 있는 주제야. 우리가 오늘 배운 내용은 시작에 불과해. 계속해서 공부하고, 경험을 쌓아가면서 더 안전한 스마트 컨트랙트를 만들 수 있을 거야.

기억해, 좋은 개발자는 기능만 구현하는 게 아니라 안전성도 함께 고려해. 마치 재능넷이 사용자의 정보와 거래를 안전하게 지키는 것처럼, 우리도 블록체인 생태계를 안전하게 만드는 데 기여할 수 있어!

자, 이제 정말 끝이야. 솔리디티 보안에 대해 배운 걸 실제 프로젝트에 적용해보면 어떨까? 연습이 완벽을 만든다고 하잖아. 계속 코딩하고, 테스트하고, 개선해나가면 분명 훌륭한 블록체인 개발자가 될 수 있을 거야. 화이팅! 🚀🔒💻

관련 키워드

  • 솔리디티
  • 스마트 컨트랙트
  • 보안 취약점
  • 재진입 공격
  • 정수 오버플로우
  • 접근 제어
  • SafeMath
  • 함수 수정자
  • 이더리움
  • 블록체인

지적 재산권 보호

지적 재산권 보호 고지

  1. 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
  2. AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
  3. 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
  4. 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
  5. AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.

재능넷은 최신 AI 기술과 법률에 기반하여 자사의 지적 재산권을 적극적으로 보호하며,
무단 사용 및 침해 행위에 대해 법적 대응을 할 권리를 보유합니다.

© 2024 재능넷 | All rights reserved.

댓글 작성
0/2000

댓글 0개

해당 지식과 관련있는 인기재능

저희는 국내 명문대학교 컴퓨터교육과에 재학중인 학생으로 이루어진 팀입니다.개발 프로젝트 실력은 물론이고 C언어, JAVA 및 각종 프로그래밍 언...

윈도우 프로그램밍 3년차 개발자 입니다.업무시간이 짧아 남는 시간에 재능이 필요한분께 도움이 되고자 합니다.구매 전 간단한 요구사항 및 금액 ...

개인용도의 프로그램이나 소규모 프로그램을 합리적인 가격으로 제작해드립니다.개발 아이디어가 있으시다면 부담 갖지 마시고 문의해주세요. ...

📚 생성된 총 지식 10,106 개

  • (주)재능넷 | 대표 : 강정수 | 경기도 수원시 영통구 봉영로 1612, 7층 710-09 호 (영통동) | 사업자등록번호 : 131-86-65451
    통신판매업신고 : 2018-수원영통-0307 | 직업정보제공사업 신고번호 : 중부청 2013-4호 | jaenung@jaenung.net

    (주)재능넷의 사전 서면 동의 없이 재능넷사이트의 일체의 정보, 콘텐츠 및 UI등을 상업적 목적으로 전재, 전송, 스크래핑 등 무단 사용할 수 없습니다.
    (주)재능넷은 통신판매중개자로서 재능넷의 거래당사자가 아니며, 판매자가 등록한 상품정보 및 거래에 대해 재능넷은 일체 책임을 지지 않습니다.

    Copyright © 2024 재능넷 Inc. All rights reserved.
ICT Innovation 대상
미래창조과학부장관 표창
서울특별시
공유기업 지정
한국데이터베이스진흥원
콘텐츠 제공서비스 품질인증
대한민국 중소 중견기업
혁신대상 중소기업청장상
인터넷에코어워드
일자리창출 분야 대상
웹어워드코리아
인터넷 서비스분야 우수상
정보통신산업진흥원장
정부유공 표창장
미래창조과학부
ICT지원사업 선정
기술혁신
벤처기업 확인
기술개발
기업부설 연구소 인정
마이크로소프트
BizsPark 스타트업
대한민국 미래경영대상
재능마켓 부문 수상
대한민국 중소기업인 대회
중소기업중앙회장 표창
국회 중소벤처기업위원회
위원장 표창