Notice
Recent Posts
Recent Comments
Link
IgnatiusHeo
구현단계 보안약점 제거 기준-DNS lookup에 의존한 보안결정 본문
작성일: 230704
※ 본 게시글은 학습 목적으로 행정안전부·KISA의 소프트웨어 보안약점 진단 가이드, 소프트웨어 개발보안 가이드를 참고하여 작성하였습니다.
정리 내용: 소프트웨어 보안약점 진단 가이드(492~496p)
구분 | - 보안기능, API오용 |
설계단계 | - 인증 대상 및 방식 https://cryptocurrencyclub.tistory.com/100 |
개요 | 공격자가 DNS 엔트리를 속일 수 있으므로 도메인명에 의존에서 보안결정(인증 및 접근통제 등)을 하지 않아야 한다. 만약, 로컬 DNS 서버의 캐시가 공격자에 의해 오염된 상황이라면, 사용자와 특정 서버 간의 네트워크 트래픽이 공격자를 경유하도록 할 수도 있다. 또한, 공격자가 마치 동일 도메인에 속한 서버인 것처럼 위장할 수도 있다. |
진단 세부사항 (설계단계) |
① 중요기능이나 리소스에 대해서는 인증 후 사용 정책이 적용되어야 한다. 중요기능은 안전한 인증방식을 사용하여 인증 후 사용하도록 설계하고 인증이 수행되도록 설계되어 있는지 확인한다. ㅇ 중요기능과 중요 리소스에 대한 접근 권한이 분류되어 있는지 확인 ㅇ 접근권한을 기반으로 인증이 요구되는 중요 기능이나 리소스가 분류되어 있는지 확인 ㅇ 인증 누락이 발생하지 않도록 인증적용 방법이 안전하게 설계됐는지 확인(프레임워크 컴포넌트를 활용 및 적용, 인증 누락이 발생하지 않도록 설정) ㅇ 중요 기능, 리소스에 대한 접근통제가 수행되고 있는지 점검하기 위한 테스트 계획 수립 여부 확인 ② 안전한 인증방식을 사용하여 인증우회나 권한 상승이 발생하지 않도록 해야 한다. 안전한 인증방식을 사용하여 인증 후 사용하도록 설계되어 있는지 확인한다. ㅇ 인증기능 설계 시 안전한 인증방식을 사용하도록 설계되어 있는지 확인(Type1/ Type2 / Type3) ㅇ 인증정보의 저장방식이 안전하게 설계되어 있는지 확인(인증 사용값은 안전하게 암호화되어 서버에 저장되어야 함) ㅇ 인증에 대한 인증횟수 제한 및 오류처리기능의 설계 여부 확인 ㅇ 인증오류 또는 인증실패에 대한 로깅의 설계 여부 확인(인증시도를 추적할 수 있는 인증시도시간/IP/ID정보 등 포함 여부 확인) ③ 중요기능에 대해 2단계(2-factor)인증을 고려해야 한다. 중요기능은 안전한 인증방식을 사용하여 인증 후 사용하도록 설계하고 2단계 인증 등 보안을 강화하는 방법을 고려해야 한다. ㅇ 개인정보변경, 비밀번호 재설정, 권한 관리, 관리자 기능과 같은 중요기능의 경우 추가인증을 요청하도록 설계되었는지 확인 ㅇ 추가 인증기능 설계시 안전한 인증방식이 사용되도록 설계되어 있는지 확인 → ID/PW 또는 OTP, 멀티디바이스를 이용한 추가 인증, (공인/사설) 인증서, 바이오정보(지문, 홍채 등) ㅇ 추가인증이 요구되는 중요기능을 사용하거나 해당 인증을 실패하는 경우 사용시간, IP주소, ID정보, 사용기능 등이 로깅되도록 설계되었는지 확인 |
보안대책 (구현단계) |
보안결정에서 도메인명을 이용한 DNS lookup을 하지 않도록 한다. |
진단방법 (구현단계) |
① DNS lookup을 하는 모듈이 존재하는지 확인하고, ② 보안결정을 하는 부분이 존재하는지 확인한다. DNS 이름으로 해당 요청이 신뢰할 수 있는지를 검사한다. 그러나 공격자가 DNS 캐시 등을 조작하면 잘못된 신뢰 상태 정보를 얻을 수 있다. |
다. 코드예제
ㅇ 분석
1: public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
2: boolean trusted = false;
3: String ip = req.getRemoteAddr();
4: InetAddress addr = InetAddress.getByName(ip);
5: //도메인은 공격자에 의해 실행되는 서버의 DNS가 변경될 수 있으므로 안전하지 않다.
6: if (addr.getCanonicalHostName().endsWith("trustme.com")) {
7: do_something_for_Trust_System();
8: }
ㅇ 수정
1: public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
2: String ip = req.getRemoteAddr();
3: if (ip == null || "".equals(ip)) return ;
4: //이용하려는 실제 서버의 IP 주소를 사용하여 DNS변조에 방어한다.
5: String trustedAddr = "127.0.0.1";
6: if (ip.equals(trustedAddr)) {
7: do_something_for_Trust_System();
8: }
ㅇ 내용
1. 신뢰 대상을 IP로 박음
ㅇ 분석
1: bool trusted;
2: string remoteIpAddress = Request.ServerVariables["REMOTE_HOST"];
3: IPAddress hostIPAddress = IPAddress.Parse(remoteIpAddress);
4: IPHostEntry hostInfo = Dns.GetHostByAddress(hostIPAddress);
5: string hostName = hostInfo.HostName;
6: if (hostName.EndsWith("trust.com"))
7: {
8: trusted = true;
9: }
ㅇ 수정
1: bool trusted;
2: string remoteIpAddress = Request.ServerVariables["REMOTE_HOST"];
3: if (remoteIpAddress.Equals(trustedAddr))
4: {
5: trusted = true;
6: Do_something_for_Trust_System();
7: }
ㅇ 내용
ㅇ 분석
1: struct hostent *hp;struct in_addr myaddr;
2: char* tHost = "trustme.example.com";
3: myaddr.s_addr=inet_addr(ip_addr_string);
4: hp = gethostbyaddr((char *) &myaddr, sizeof(struct in_addr), AF_INET);
5: // 요청의 신뢰성을 호스트의 이름으로 판별하고 있다.
6: if (hp && !strncmp(hp->h_name, tHost, sizeof(tHost))) {
7: trusted = true;
8: } else {
9: trusted = false;
10:}
ㅇ 수정
1: struct hostent *hp;struct in_addr myaddr;
2: char* tHost = "127.0.0.1";
3: myaddr.s_addr=inet_addr(ip_addr_string);
4: hp = gethostbyaddr((char *) &myaddr, sizeof(struct in_addr), AF_INET);
5: // 호스트의 이름이 아니라 IP로 직접 비교한다.
6: if (hp && !strncmp(hp->h_name, tHost, sizeof(tHost))) {
7: trusted = true;
8: } else {
9: trusted = false;
10: }
ㅇ 내용
끝.
'자격 > SW보안약점진단원' 카테고리의 다른 글
설계단계 보안설계기준 정리 (0) | 2023.07.08 |
---|---|
구현단계 보안약점 제거 기준-취약한 API 사용 (0) | 2023.07.06 |
구현단계 보안약점 제거 기준-Private 배열에 Public 데이터 할당 (0) | 2023.07.06 |
구현단계 보안약점 제거 기준-Public 메소드부터 반환된 Private 배열 (0) | 2023.07.06 |
구현단계 보안약점 제거 기준-제거되지 않고 남은 디버그 코드 (0) | 2023.07.06 |