-------------------------
The universe is run by the complex interweaving of three elements: matter, energy, and enlightened self-interest.
- G'kar, Babylon 5
1. 매번 로그인 페이지에 접속할때마다 임의의 문자열을 생성해서 클라이언트로 보내줍니다. 그리고 이 문자열을 서버측에도 저장해 둡니다.
2. 클라이언트 측에서는 사용자가 입력한 ID 및 암호 및 서버에서 보내온 문자열을 조합한 다음 sha1 같은 해쉬 알고리듬을 사용해 해쉬 코드를 구해서 이 코드를 서버측으로 전송합니다.
3. 서버 측에서는 미리 저장되어 있던 ID와 암호 및 클라이언트로 보내기 위해서 생성했던 문자열을 조합한 다음 마찬가지로 sha1 해쉬 코드를 구해서 클라이언트 측에서 보내온 해쉬 코드와 비교합니다.
실제로는 서버측에 ID와 패스워드를 직접 저장하는 것을 피하기 위해서 서버에는 ID와 패스워드 대신에 그 해쉬 값을 저장하고, 클라이언트 측에서는 먼저 ID와 패스워드의 해쉬 코드를 구한 다음, 그렇게 구한 해쉬 코드를 이용해서 2의 과정을 거쳐야 합니다.
이렇게 하면 매번 서버로 보내는 데이터가 달라지게 되고, 중간에 가로채서 서버로 보내는 데이터를 알아내더라도 쓸모가 없게 됩니다.
alee 님의 방법은 어차피 암호화를 위한 seed값이 네트워크를 통해서 지나간다는 점에서 약간 번거로워질 뿐이지 일반적인 쿠키/세션 인증법하고 다른 점이 별로 없어 보입니다. 1번의 과정에서 임의의 문자열을 가로챌 수 있으니까요.
만약 클라이언트와 서버가 아주 처음부터 약속된 각자의 seed값을 가지고 있다면 모르겠지만..... 그리고 그렇게 하는 방법이 https이고요.
alee 님의 방법은 어차피 암호화를 위한 seed값이 네트워크를 통해서 지나간다는 점에서 약간 번거로워질 뿐이지 일반적인 쿠키/세션 인증법하고 다른 점이 별로 없어 보입니다. 1번의 과정에서 임의의 문자열을 가로챌 수 있으니까요.
만약 클라이언트와 서버가 아주 처음부터 약속된 각자의 seed값을 가지고 있다면 모르겠지만..... 그리고 그렇게 하는 방법이 https이고요.
매번 로그인 할 때 마다 seed 값이 바뀝니다. 따라서 seed 값을 가로채더라도 쓸모가 없게 됩니다. 물론 https 보다야 못합니다만, sha1이 뚫리지 않는 이상 중간에 패킷을 가로채는 것은 아무 소용이 없게 됩니다. 이해를 잘 못하신 것 같습니다.
아, 그리고 sha1도 자바스크립트로 구현이 가능하고, 구글을 검색해 보면 이미 구현되어 있는 소스를 다운받을 수 있습니다.
alee 님의 방법은 어차피 암호화를 위한 seed값이 네트워크를 통해서 지나간다는 점에서 약간 번거로워질 뿐이지 일반적인 쿠키/세션 인증법하고 다른 점이 별로 없어 보입니다. 1번의 과정에서 임의의 문자열을 가로챌 수 있으니까요.
만약 클라이언트와 서버가 아주 처음부터 약속된 각자의 seed값을 가지고 있다면 모르겠지만..... 그리고 그렇게 하는 방법이 https이고요.
매번 로그인 할 때 마다 seed 값이 바뀝니다. 따라서 seed 값을 가로채더라도 쓸모가 없게 됩니다.
한 번 로그인한 다음에 한동안은 seed가 고정되는것 아닌가요? 그렇다면 그 동안은 가능성이 있어보입니다. 아니면 매 요청마다 seed를 생성해서 돌려주는 방법을 말씀하신 것인가요?
alee 님의 방법은 어차피 암호화를 위한 seed값이 네트워크를 통해서 지나간다는 점에서 약간 번거로워질 뿐이지 일반적인 쿠키/세션 인증법하고 다른 점이 별로 없어 보입니다. 1번의 과정에서 임의의 문자열을 가로챌 수 있으니까요.
만약 클라이언트와 서버가 아주 처음부터 약속된 각자의 seed값을 가지고 있다면 모르겠지만..... 그리고 그렇게 하는 방법이 https이고요.
매번 로그인 할 때 마다 seed 값이 바뀝니다. 따라서 seed 값을 가로채더라도 쓸모가 없게 됩니다.
한 번 로그인한 다음에 한동안은 seed가 고정되는것 아닌가요? 그렇다면 그 동안은 가능성이 있어보입니다. 아니면 매 요청마다 seed를 생성해서 돌려주는 방법을 말씀하신 것인가요?
필요에 따라서 적당히 구현하면 됩니다. 좀 더 보안이 요구된다면 매번 seed를 생성해서 돌려주는 방법을 쓰면 되고, 그보다는 덜 요구된다면 세션당 한번씩만 생성해서 돌려주면 되겠죠.
필요에 따라서 적당히 구현하면 됩니다. 좀 더 보안이 요구된다면 매번 seed를 생성해서 돌려주는 방법을 쓰면 되고, 그보다는 덜 요구된다면 세션당 한번씩만 생성해서 돌려주면 되겠죠.
어떤 의도인지는 이해를 했습니다만, response와 다음번 request 사이에 텀이 있다면 (당연히 있겠지만요) 그 사이에 일을 도모할 수 있다는 생각이 듭니다. 그리고 매 요청마다 생성을 하게 되면 사용자가 두 개의 창을 띄운다거나 하면 어려움이 있겠네요.
말씀하신 방법이 소용 없다는 뜻은 아니구요, 상황에 따라 간단하게 구현 가능한 방법일 수도 있고 위험의 소지가 남아있기도 하다는 뜻이었습니다.
목적은 클라이언트와 서버간에 주고 받는 패킷을 가로채더라도 암호와 관련된 어떠한 정보도 얻을 수 없게 하는 것입니다. 다른 장점들도 문서에 잘 설명되어 있습니다. 그리고 양단 간의 인증시 마다 매번 바뀌는 해쉬값을 의미있는 용도로 사용할 수 있습니다.
실제로 SRP-6a 를 약간 변경해서 World of Warcraft 가 인증을 구현하고 있고 WoW realmlist 서버와 SRP-6a 로 인증된 후 내부의 40바이트 해쉬값을 차례대로 이용해서 실제 게임서버와의 통신에 각 패킷의 앞부분을 약간 비틀어서 암호화하고 있습니다. (더 자세히 밝혔다가는... )
아주 큰 숫자의 멱승에 소수로 나눈 나머지를 이용하는건데 신기하게도 안전하고 정확하게 인증 절차를 구현할 수 있었습니다.
완전한 구현을 이 데모 페이지의 자바 스크립트에서 얻을 수 있습니다. 한번 관심을 가져볼만한 인증 프로토콜이라고 생각합니다.
필요에 따라서 적당히 구현하면 됩니다. 좀 더 보안이 요구된다면 매번 seed를 생성해서 돌려주는 방법을 쓰면 되고, 그보다는 덜 요구된다면 세션당 한번씩만 생성해서 돌려주면 되겠죠.
어떤 의도인지는 이해를 했습니다만, response와 다음번 request 사이에 텀이 있다면 (당연히 있겠지만요) 그 사이에 일을 도모할 수 있다는 생각이 듭니다. 그리고 매 요청마다 생성을 하게 되면 사용자가 두 개의 창을 띄운다거나 하면 어려움이 있겠네요.
말씀하신 방법이 소용 없다는 뜻은 아니구요, 상황에 따라 간단하게 구현 가능한 방법일 수도 있고 위험의 소지가 남아있기도 하다는 뜻이었습니다.
response와 다음번 request 사이에 텀이 있더라도 관계가 없습니다. 인증을 위해서 필요한 것은 seed 값과 사용자 정보(ID와 패스워드) 입니다. 서버의 response를 가로채서 알아낼 수 있는 것은 seed 값 뿐입니다. 반면에 클라이언트의 request를 가로채서 알아낼 수 있는 것은, seed값과 사용자 정보를 조합하여 얻어진 해쉬 값인데, 이 해쉬 값은 일단 서버가 request를 받는 순간 만료되기 때문에 중간에 가로채 봐야 아무 쓸모가 없습니다.
만약 중간에 request를 가로챈 다음에 그 request가 서버에 도달하지 못하도록 아예 가로막아 버리고 조작된 request를 서버로 보낸다면 일을 도모하는 것이 가능하겠죠. 그렇지만 이것은 네트워크 선을 중간에 끊지 않는 이상 불가능하고, 설사 그렇게 한다 해도 단 한 번 조작된 패킷을 보낼 수 있을 뿐 지속적으로 서버를 속이는 것은 불가능합니다.
만약 이보다 더 보안이 요구된다면 https를 사용하면 되겠죠. 그렇지만 https를 사용하기 위해서는 인증서도 있어야 하고, 웹 서버 설정도 따로 해줘야 합니다. 단지 POST 데이터를 가로채는 것이 불안해서 https를 사용하는 것은 너무 번거롭다면 이러한 방법도 있다고 말씀드리는 것입니다.
솔직히 매번 이렇게 seed 값을 바꾸는 것은 말씀하신 대로 여러 창을 띄우는 경우 구현이 아주 어렵지는 않지만 약간 복잡해 집니다. 일반적인 포털 사이트 수준에서 이 정도의 보안은 불필요한 것 같고, 매 세션마다 한 번만 seed 값을 생성해서 보내주면 충분하다고 생각합니다. 실제로 Yahoo인가? 에서 이 방법을 사용하고 있다고 합니다.
목적은 클라이언트와 서버간에 주고 받는 패킷을 가로채더라도 암호와 관련된 어떠한 정보도 얻을 수 없게 하는 것입니다. 다른 장점들도 문서에 잘 설명되어 있습니다. 그리고 양단 간의 인증시 마다 매번 바뀌는 해쉬값을 의미있는 용도로 사용할 수 있습니다.
실제로 SRP-6a 를 약간 변경해서 World of Warcraft 가 인증을 구현하고 있고 WoW realmlist 서버와 SRP-6a 로 인증된 후 내부의 40바이트 해쉬값을 차례대로 이용해서 실제 게임서버와의 통신에 각 패킷의 앞부분을 약간 비틀어서 암호화하고 있습니다. (더 자세히 밝혔다가는... )
아주 큰 숫자의 멱승에 소수로 나눈 나머지를 이용하는건데 신기하게도 안전하고 정확하게 인증 절차를 구현할 수 있었습니다.
완전한 구현을 이 데모 페이지의 자바 스크립트에서 얻을 수 있습니다. 한번 관심을 가져볼만한 인증 프로토콜이라고 생각합니다.
User -> Host: I, A = g^a
Host -> User: s, B = kv + g^b
이런 내용이 보이는데요...
문제는 B를 구하기 위해선 client 로부터 I를 받아야 한다는 거죠...
이는 곧 일반적인 인증 방식에 비해 한번의 통신이 더 일어 나야 한다는 것을 의미 합니다.
여기서 말하는 일반적인 인증 방식이란 plain text password 전송, SSL 에 의한 데이터 암호화 또는 alee 님의 random seed 를 기반으로 한 one-time hash 전송 방식을 말하는 것입니다.
alee wrote:
필요에 따라서 적당히 구현하면 됩니다. 좀 더 보안이 요구된다면 매번 seed를 생성해서 돌려주는 방법을 쓰면 되고, 그보다는 덜 요구된다면 세션당 한번씩만 생성해서 돌려주면 되겠죠.
alee님이 제안하신 방식의 문제점은 다수의 서버를 L4 switch 뒤에 숨겨서 운영하는 환경에선 사용자가 random seed를 생성하고 저장한 서버에 다시 접속 하리라는 보장이 없다는 것에 문제가 있습니다.
이를 해결 하려면 plain text 형태의 random seed 와 Rijndael이나 Triple DES 같은 대칭키 암호화 방식을 사용해 암호화된 ramdom seed 를 같이 cookie 에 심어 처리 할 수 있습니다만, plain text와 cipher text를 같이 두는건 그리 바람직한 방법은 아닙니다.
또다른 해결 방법으론 session 을 관리하는 별도의 서버를 두는것도 생각 해 볼수 있지만, L4를 통해 부하분산을 해야 할 만큼 많은 사용자를 받아 내야 하는 시스템에선 이 역시 가용성과 성능이라는 측면에선 답이 안나오는 상황 입니다.
저두 요즘 비슷한 내용을 가지고 이런저런 고민을 하다 이 글타래를 만나 한번 끄적이고 갑니다.
목적은 클라이언트와 서버간에 주고 받는 패킷을 가로채더라도 암호와 관련된 어떠한 정보도 얻을 수 없게 하는 것입니다. 다른 장점들도 문서에 잘 설명되어 있습니다. 그리고 양단 간의 인증시 마다 매번 바뀌는 해쉬값을 의미있는 용도로 사용할 수 있습니다.
실제로 SRP-6a 를 약간 변경해서 World of Warcraft 가 인증을 구현하고 있고 WoW realmlist 서버와 SRP-6a 로 인증된 후 내부의 40바이트 해쉬값을 차례대로 이용해서 실제 게임서버와의 통신에 각 패킷의 앞부분을 약간 비틀어서 암호화하고 있습니다. (더 자세히 밝혔다가는... )
아주 큰 숫자의 멱승에 소수로 나눈 나머지를 이용하는건데 신기하게도 안전하고 정확하게 인증 절차를 구현할 수 있었습니다.
완전한 구현을 이 데모 페이지의 자바 스크립트에서 얻을 수 있습니다. 한번 관심을 가져볼만한 인증 프로토콜이라고 생각합니다.
User -> Host: I, A = g^a
Host -> User: s, B = kv + g^b
이런 내용이 보이는데요...
문제는 B를 구하기 위해선 client 로부터 I를 받아야 한다는 거죠...
이는 곧 일반적인 인증 방식에 비해 한번의 통신이 더 일어 나야 한다는 것을 의미 합니다.
여기서 말하는 일반적인 인증 방식이란 plain text password 전송, SSL 에 의한 데이터 암호화 또는 alee 님의 random seed 를 기반으로 한 one-time hash 전송 방식을 말하는 것입니다.
http의 특성때문에 접속유지와 같은 역활을 하는 (예, php의 세션같은) 것이 있지 않나요? 이전 접속과 다음번 접속이 같은 흐름에 놓여 있다라고 확신할 수 있는 방법이 제공된다고 알고 있습니다. SRP 하고는 별개로 생각할 수 있는 문제라고 생각합니다.
물론 SRP 는 양단간의 임시적이고 임의적으로 한번만 사용하는 값을 교환하기는 해야 하지만 전달되는 값들을 적절히 배치하면 네번의 패킷교환만으로 서로를 확신할 수 있습니다.
C ==> S C, A ; 첫번째 접속때 전달
C <== S s, B ; 첫번째 접속의 결과
C ==> S M[1] ; 두번째 접속때 전달
C <== S M[2] ; 두번째 접속의 결과
http 접속때 값을 전달할 수 있고, 그 결과를 얻을 수 있다면 연속된 접속이라는 것을 보장받을 수 있는 방법으로 이것을 유지해서 인증을 성공시킬 수 있지 않을까요?
... 밑에 글을 읽지 않고 여기까지 썼는데 하신 말씀을 또 한 꼴이 되어 버렸군요. 세션 얘기가 바로 나와버리는 ...
하여튼, 원하시는 것이 한번의 전송이다라고 한다면 패킷을 조작하거나 다음번에 같은 값을 사용해서 악용될 소지가 있다고 생각합니다. 어떤 글에서인가 plain text 와 md5 나 sha1 등으로 얻은 해쉬값을 해킹쪽에서는 동등한 레벨로 본다고 나온 걸로 기억하고 있습니다. 알고리즘에 의한 암호화도 클라이언트쪽이 훤히 보이는 문제가 발생할 수 있을 것 같습니다.
부하분산 문제를 제기하셨는데, 일반적으로 웹을 부하분산할 때 접속 세션은 어떻게 관리되고 있나요? 그런 환경은 접해보질 못해서 궁금합니다. 말씀하신대로 어떤 값을 발급하고 관리하는 머신이 따로 있긴 해야 할 것 같습니다만... 그런걸 신경 안쓰게 해주는 웹 전용 부하분산기가 시중에 있긴 하겠죠?
alee님이 제안하신 방식의 문제점은 다수의 서버를 L4 switch 뒤에 숨겨서 운영하는 환경에선 사용자가 random seed를 생성하고 저장한 서버에 다시 접속 하리라는 보장이 없다는 것에 문제가 있습니다.
이를 해결 하려면 plain text 형태의 random seed 와 Rijndael이나 Triple DES 같은 대칭키 암호화 방식을 사용해 암호화된 ramdom seed 를 같이 cookie 에 심어 처리 할 수 있습니다만, plain text와 cipher text를 같이 두는건 그리 바람직한 방법은 아닙니다.
또다른 해결 방법으론 session 을 관리하는 별도의 서버를 두는것도 생각 해 볼수 있지만, L4를 통해 부하분산을 해야 할 만큼 많은 사용자를 받아 내야 하는 시스템에선 이 역시 가용성과 성능이라는 측면에선 답이 안나오는 상황 입니다.
그런 문제가 있겠군요. 제가 설명한 것은 그냥 적당한 타협안 입니다. 보통 스니핑 같은 것으로 빼내는 것은 아이디와 패스워드 정도이고, 그 이상의 일을 하기 위해서는 특별히 프로그램도 짜야 하고 일반인이 쉽게 하기는 어렵습니다. 로그인 시에만 random seed와 hash를 사용해도 아이디와 패스워드를 빼내는 것 정도는 방지할 수 있습니다.
예를 들어 KLDP 로그인 하는 데에 이 정도면 충분하지 않을까요? 이런 방법 까지도 필요 없다고 생각하는 분도 계시겠지만, 그냥 입력받은 내용을 그대로 전송하는 경우 솔직히 너무 쉽게 아이디와 패스워드를 가로챌 수 있잖아요.
부하분산 문제를 제기하셨는데, 일반적으로 웹을 부하분산할 때 접속 세션은 어떻게 관리되고 있나요? 그런 환경은 접해보질 못해서 궁금합니다. 말씀하신대로 어떤 값을 발급하고 관리하는 머신이 따로 있긴 해야 할 것 같습니다만... 그런걸 신경 안쓰게 해주는 웹 전용 부하분산기가 시중에 있긴 하겠죠?
network 레벨에선 주로 L4 switch를 이중화해 부하 분산과 가용성을 확보 합니다. 요즘은 가격이 많이 떨어진 관계로 L7도 많이 쓰더군요...
시중에 세션을 관리 해 주는 제품이 몇가지가 있는걸로 알고 있는데...(ASP.NET 에서도 기본으로 제공하죠...) 쓸만한 제품은 못 봤습니다.
일례로 코리아 닷컴과 삼성이 네티그리티의 사이트마인더를 도입했는데... 거의 실패한 사례라고 할 정도로 결과는 처절 합니다.
그래서 사용하는 방법이, 타임스템프와 필요한 데이터를 암호화 해 쿠키에 담아 놓는 방법을 사용합니다. (쿠키가=세션 뭐 대충 이런겁니다.)
그나마 이 방식도 이런 저런 제약 사항때문에 그리 쉽지 않더군요... ㅠㅠ
저희 회사가 운영하는 사이트를 포함한 네이버, 한게임, 다음, 네이트 같이 국내에서 수위를 다투는 사이트들은 이 방식을 사용한다고 보시면 틀림 없습니다.
JBoss에는 SRP기반의 인증 시스템이 붙어 있네요.
정확한 사용법은 문서를 찾고 있는 중인데..
(뭐, 일반적인 웹에서 그리 쓸만할 것 같지는 않습니다. 인증시스템들이야 이래저래 붙어있긴 하지만.. 상황이랑 그리 딱 떨어지게 만들어 놓는게 아니니.. JBoss 관리 목적의 사용자 인증이라면 모를까.. @.@)
만약, 범용적으로 사용하기 용이하게 되어 있다면, 나름대로 쓸만할 것 같네요.
1) 서버는 Root CA가 아닌 곳에서 서명한 certificate를 사용한다. (예를들어, 자기 자신이 서명한 certificate)
2) 공격자는 웹 서버와 동일하게 보이는 certificate를 가진 가짜 웹 서버를 만든다. (본래의 웹서버가 제대로 인증된 certificate을 갖고 있는게 아니므로 이것이 쉽게 가능해진다.)
3) 공격자는 ARP 를 통해, 자신을 DNS로 속인다.
4) Victim은 웹 서버의 DNS를 찾고자하고, 공격자의 머신을 DNS로 착각한다.
5) Victim은 공격자가 제공하는 DNS에서 웹 서버의 주소를 받는다. 물론 이때 제공된 주소는 공격자가 작성한 certificate를 갖는 가짜 웹서버 SSL Proxy이다.
6) Victim은 SSL Proxy에 접속한다.
7) 이 단계에서 변경된 certificate이 Victim에게 전달되지만, Victim은 이 사실을 알아채지 못한다.
8 ) 공격자는 SSL Proxy를 통하여 Victim과 실제 웹 서버간의 통신을 중계하면서, 통신 내용을 엿듣거나 조작한다.
당연하게도 가능합니다. :wink:
당연하게도 가능합니다. :wink:
-------------------------
The universe is run by the complex interweaving of three elements: matter, energy, and enlightened self-interest.
- G'kar, Babylon 5
결론부터 말씀드리자면 가능합니다.일단 저 POST 를 보내는 사람
결론부터 말씀드리자면 가능합니다.
일단 저 POST 를 보내는 사람이 POST 내용을 임의로 수정해서
보내는 것은 너무나도 당연하게 가능합니다.
그리고 제3자가 POST 내용을 수정하는 것은 네트워크를 스니핑해서
가능합니다.
해결하는 방법은 아마 SSL 같은 암호화 통신을 사용하면 될 듯합니다.
그래서 POST 된 데이터가 긴가민가 매번 확인 해줘야 합니다. 코드 파
그래서 POST 된 데이터가 긴가민가 매번 확인 해줘야 합니다. 코드 파일들끼리 서로 믿음을 갖지 않는 사회를 구축하는 것이 대처법.. 리퍼러를 체크하는 방법을 쓰는 분들도 계시는데 정말 공격하고 싶은 사람이라면 리퍼러도 조작할테고.. 휴;; 힘들어요 ㅠ.ㅠ
----
http://returnet.blogdns.com
https 를 사용하면 안전하지요?
https 를 사용하면 안전하지요?
[quote="returnet"]그래서 POST 된 데이터가 긴가민가 매
컴퓨터에서도 믿을만한놈은 없다! 이건가요? ㅡ,.ㅡ:::
내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.
해킹을 100% 막기는 불가능한거군요
해킹을 100% 막기는 불가능한거군요
#include <stdio.h>
int main()
{
while(1)
printf("0");
return 0;
}
이 문제를 해결하기 위해서 제가 쓰는 방법입니다.1. 매번 로그인
이 문제를 해결하기 위해서 제가 쓰는 방법입니다.
1. 매번 로그인 페이지에 접속할때마다 임의의 문자열을 생성해서 클라이언트로 보내줍니다. 그리고 이 문자열을 서버측에도 저장해 둡니다.
2. 클라이언트 측에서는 사용자가 입력한 ID 및 암호 및 서버에서 보내온 문자열을 조합한 다음 sha1 같은 해쉬 알고리듬을 사용해 해쉬 코드를 구해서 이 코드를 서버측으로 전송합니다.
3. 서버 측에서는 미리 저장되어 있던 ID와 암호 및 클라이언트로 보내기 위해서 생성했던 문자열을 조합한 다음 마찬가지로 sha1 해쉬 코드를 구해서 클라이언트 측에서 보내온 해쉬 코드와 비교합니다.
실제로는 서버측에 ID와 패스워드를 직접 저장하는 것을 피하기 위해서 서버에는 ID와 패스워드 대신에 그 해쉬 값을 저장하고, 클라이언트 측에서는 먼저 ID와 패스워드의 해쉬 코드를 구한 다음, 그렇게 구한 해쉬 코드를 이용해서 2의 과정을 거쳐야 합니다.
이렇게 하면 매번 서버로 보내는 데이터가 달라지게 되고, 중간에 가로채서 서버로 보내는 데이터를 알아내더라도 쓸모가 없게 됩니다.
[quote="alee"]2. 클라이언트 측에서는 사용자가 입력한 ID
클라이언트 측에서는 자바 스크립트로 문자열을 조합하게 되는건가요? 설마 ActiveX ?
alee 님의 방법은 어차피 암호화를 위한 seed값이 네트워크를 통해서
alee 님의 방법은 어차피 암호화를 위한 seed값이 네트워크를 통해서 지나간다는 점에서 약간 번거로워질 뿐이지 일반적인 쿠키/세션 인증법하고 다른 점이 별로 없어 보입니다. 1번의 과정에서 임의의 문자열을 가로챌 수 있으니까요.
만약 클라이언트와 서버가 아주 처음부터 약속된 각자의 seed값을 가지고 있다면 모르겠지만..... 그리고 그렇게 하는 방법이 https이고요.
[quote="kihongss"][quote="alee"]2. 클라이언트
sha1는 구경은 못해봤는데 md5가 javascript 로 구현된게 있으니까 sha1도 가능하겠네요.
[quote="bs0048"]alee 님의 방법은 어차피 암호화를 위한
매번 로그인 할 때 마다 seed 값이 바뀝니다. 따라서 seed 값을 가로채더라도 쓸모가 없게 됩니다. 물론 https 보다야 못합니다만, sha1이 뚫리지 않는 이상 중간에 패킷을 가로채는 것은 아무 소용이 없게 됩니다. 이해를 잘 못하신 것 같습니다.
아, 그리고 sha1도 자바스크립트로 구현이 가능하고, 구글을 검색해 보면 이미 구현되어 있는 소스를 다운받을 수 있습니다.
[quote="alee"][quote="bs0048"]alee 님의 방법
한 번 로그인한 다음에 한동안은 seed가 고정되는것 아닌가요? 그렇다면 그 동안은 가능성이 있어보입니다. 아니면 매 요청마다 seed를 생성해서 돌려주는 방법을 말씀하신 것인가요?
[quote="bs0048"][quote="alee"][quote="bs
필요에 따라서 적당히 구현하면 됩니다. 좀 더 보안이 요구된다면 매번 seed를 생성해서 돌려주는 방법을 쓰면 되고, 그보다는 덜 요구된다면 세션당 한번씩만 생성해서 돌려주면 되겠죠.
[quote="alee"]필요에 따라서 적당히 구현하면 됩니다. 좀
어떤 의도인지는 이해를 했습니다만, response와 다음번 request 사이에 텀이 있다면 (당연히 있겠지만요) 그 사이에 일을 도모할 수 있다는 생각이 듭니다. 그리고 매 요청마다 생성을 하게 되면 사용자가 두 개의 창을 띄운다거나 하면 어려움이 있겠네요.
말씀하신 방법이 소용 없다는 뜻은 아니구요, 상황에 따라 간단하게 구현 가능한 방법일 수도 있고 위험의 소지가 남아있기도 하다는 뜻이었습니다.
이런 경우에 사용해볼만한 인증 프로토콜이 있습니다. 쉽게 구현도 가능하고
이런 경우에 사용해볼만한 인증 프로토콜이 있습니다. 쉽게 구현도 가능하고요.
http://srp.stanford.edu/
여기서 제시하는 SRP 라는 프로토콜인데, 참 재밌습니다.
http://srp.stanford.edu/demo/demo.html
일단 위 페이지를 클릭하셔서 어떤건지 한번 감상해보시구요.
http://srp.stanford.edu/design.html
위 페이지에서 간단한 동작 원리를 보실 수 있습니다.
목적은 클라이언트와 서버간에 주고 받는 패킷을 가로채더라도 암호와 관련된 어떠한 정보도 얻을 수 없게 하는 것입니다. 다른 장점들도 문서에 잘 설명되어 있습니다. 그리고 양단 간의 인증시 마다 매번 바뀌는 해쉬값을 의미있는 용도로 사용할 수 있습니다.
실제로 SRP-6a 를 약간 변경해서 World of Warcraft 가 인증을 구현하고 있고 WoW realmlist 서버와 SRP-6a 로 인증된 후 내부의 40바이트 해쉬값을 차례대로 이용해서 실제 게임서버와의 통신에 각 패킷의 앞부분을 약간 비틀어서 암호화하고 있습니다. (더 자세히 밝혔다가는... )
아주 큰 숫자의 멱승에 소수로 나눈 나머지를 이용하는건데 신기하게도 안전하고 정확하게 인증 절차를 구현할 수 있었습니다.
완전한 구현을 이 데모 페이지의 자바 스크립트에서 얻을 수 있습니다. 한번 관심을 가져볼만한 인증 프로토콜이라고 생각합니다.
[quote="bs0048"][quote="alee"]필요에 따라서
response와 다음번 request 사이에 텀이 있더라도 관계가 없습니다. 인증을 위해서 필요한 것은 seed 값과 사용자 정보(ID와 패스워드) 입니다. 서버의 response를 가로채서 알아낼 수 있는 것은 seed 값 뿐입니다. 반면에 클라이언트의 request를 가로채서 알아낼 수 있는 것은, seed값과 사용자 정보를 조합하여 얻어진 해쉬 값인데, 이 해쉬 값은 일단 서버가 request를 받는 순간 만료되기 때문에 중간에 가로채 봐야 아무 쓸모가 없습니다.
만약 중간에 request를 가로챈 다음에 그 request가 서버에 도달하지 못하도록 아예 가로막아 버리고 조작된 request를 서버로 보낸다면 일을 도모하는 것이 가능하겠죠. 그렇지만 이것은 네트워크 선을 중간에 끊지 않는 이상 불가능하고, 설사 그렇게 한다 해도 단 한 번 조작된 패킷을 보낼 수 있을 뿐 지속적으로 서버를 속이는 것은 불가능합니다.
만약 이보다 더 보안이 요구된다면 https를 사용하면 되겠죠. 그렇지만 https를 사용하기 위해서는 인증서도 있어야 하고, 웹 서버 설정도 따로 해줘야 합니다. 단지 POST 데이터를 가로채는 것이 불안해서 https를 사용하는 것은 너무 번거롭다면 이러한 방법도 있다고 말씀드리는 것입니다.
솔직히 매번 이렇게 seed 값을 바꾸는 것은 말씀하신 대로 여러 창을 띄우는 경우 구현이 아주 어렵지는 않지만 약간 복잡해 집니다. 일반적인 포털 사이트 수준에서 이 정도의 보안은 불필요한 것 같고, 매 세션마다 한 번만 seed 값을 생성해서 보내주면 충분하다고 생각합니다. 실제로 Yahoo인가? 에서 이 방법을 사용하고 있다고 합니다.
http://pajhome.org.uk/crypt/이곳에 제가 설
http://pajhome.org.uk/crypt/
이곳에 제가 설명한 방법에 관련된 정보와 자바스크립트로 구현한 md5 및 sha1 함수, 그리고 사용 예제가 있습니다.
[quote="bugiii"]이런 경우에 사용해볼만한 인증 프로토콜이 있
web application 에서는 사용하기가 좀 어려울것 같은데요...
SRP Protocol Design 을 보면,
User -> Host: I, A = g^a
Host -> User: s, B = kv + g^b
이런 내용이 보이는데요...
문제는 B를 구하기 위해선 client 로부터 I를 받아야 한다는 거죠...
이는 곧 일반적인 인증 방식에 비해 한번의 통신이 더 일어 나야 한다는 것을 의미 합니다.
여기서 말하는 일반적인 인증 방식이란 plain text password 전송, SSL 에 의한 데이터 암호화 또는 alee 님의 random seed 를 기반으로 한 one-time hash 전송 방식을 말하는 것입니다.
alee님이 제안하신 방식의 문제점은 다수의 서버를 L4 switch 뒤에 숨겨서 운영하는 환경에선 사용자가 random seed를 생성하고 저장한 서버에 다시 접속 하리라는 보장이 없다는 것에 문제가 있습니다.
이를 해결 하려면 plain text 형태의 random seed 와 Rijndael이나 Triple DES 같은 대칭키 암호화 방식을 사용해 암호화된 ramdom seed 를 같이 cookie 에 심어 처리 할 수 있습니다만, plain text와 cipher text를 같이 두는건 그리 바람직한 방법은 아닙니다.
또다른 해결 방법으론 session 을 관리하는 별도의 서버를 두는것도 생각 해 볼수 있지만, L4를 통해 부하분산을 해야 할 만큼 많은 사용자를 받아 내야 하는 시스템에선 이 역시 가용성과 성능이라는 측면에선 답이 안나오는 상황 입니다.
저두 요즘 비슷한 내용을 가지고 이런저런 고민을 하다 이 글타래를 만나 한번 끄적이고 갑니다.
[quote="secrete"][quote="bugiii"]이런 경우에
http의 특성때문에 접속유지와 같은 역활을 하는 (예, php의 세션같은) 것이 있지 않나요? 이전 접속과 다음번 접속이 같은 흐름에 놓여 있다라고 확신할 수 있는 방법이 제공된다고 알고 있습니다. SRP 하고는 별개로 생각할 수 있는 문제라고 생각합니다.
물론 SRP 는 양단간의 임시적이고 임의적으로 한번만 사용하는 값을 교환하기는 해야 하지만 전달되는 값들을 적절히 배치하면 네번의 패킷교환만으로 서로를 확신할 수 있습니다.
C ==> S C, A ; 첫번째 접속때 전달
C <== S s, B ; 첫번째 접속의 결과
C ==> S M[1] ; 두번째 접속때 전달
C <== S M[2] ; 두번째 접속의 결과
http 접속때 값을 전달할 수 있고, 그 결과를 얻을 수 있다면 연속된 접속이라는 것을 보장받을 수 있는 방법으로 이것을 유지해서 인증을 성공시킬 수 있지 않을까요?
... 밑에 글을 읽지 않고 여기까지 썼는데 하신 말씀을 또 한 꼴이 되어 버렸군요. 세션 얘기가 바로 나와버리는 ...
하여튼, 원하시는 것이 한번의 전송이다라고 한다면 패킷을 조작하거나 다음번에 같은 값을 사용해서 악용될 소지가 있다고 생각합니다. 어떤 글에서인가 plain text 와 md5 나 sha1 등으로 얻은 해쉬값을 해킹쪽에서는 동등한 레벨로 본다고 나온 걸로 기억하고 있습니다. 알고리즘에 의한 암호화도 클라이언트쪽이 훤히 보이는 문제가 발생할 수 있을 것 같습니다.
부하분산 문제를 제기하셨는데, 일반적으로 웹을 부하분산할 때 접속 세션은 어떻게 관리되고 있나요? 그런 환경은 접해보질 못해서 궁금합니다. 말씀하신대로 어떤 값을 발급하고 관리하는 머신이 따로 있긴 해야 할 것 같습니다만... 그런걸 신경 안쓰게 해주는 웹 전용 부하분산기가 시중에 있긴 하겠죠?
[quote="secrete"]alee님이 제안하신 방식의 문제점은 다수
그런 문제가 있겠군요. 제가 설명한 것은 그냥 적당한 타협안 입니다. 보통 스니핑 같은 것으로 빼내는 것은 아이디와 패스워드 정도이고, 그 이상의 일을 하기 위해서는 특별히 프로그램도 짜야 하고 일반인이 쉽게 하기는 어렵습니다. 로그인 시에만 random seed와 hash를 사용해도 아이디와 패스워드를 빼내는 것 정도는 방지할 수 있습니다.
예를 들어 KLDP 로그인 하는 데에 이 정도면 충분하지 않을까요? 이런 방법 까지도 필요 없다고 생각하는 분도 계시겠지만, 그냥 입력받은 내용을 그대로 전송하는 경우 솔직히 너무 쉽게 아이디와 패스워드를 가로챌 수 있잖아요.
[quote="alee"]부하분산 문제를 제기하셨는데, 일반적으로 웹을
network 레벨에선 주로 L4 switch를 이중화해 부하 분산과 가용성을 확보 합니다. 요즘은 가격이 많이 떨어진 관계로 L7도 많이 쓰더군요...
시중에 세션을 관리 해 주는 제품이 몇가지가 있는걸로 알고 있는데...(ASP.NET 에서도 기본으로 제공하죠...) 쓸만한 제품은 못 봤습니다.
일례로 코리아 닷컴과 삼성이 네티그리티의 사이트마인더를 도입했는데... 거의 실패한 사례라고 할 정도로 결과는 처절 합니다.
그래서 사용하는 방법이, 타임스템프와 필요한 데이터를 암호화 해 쿠키에 담아 놓는 방법을 사용합니다. (쿠키가=세션 뭐 대충 이런겁니다.)
그나마 이 방식도 이런 저런 제약 사항때문에 그리 쉽지 않더군요... ㅠㅠ
저희 회사가 운영하는 사이트를 포함한 네이버, 한게임, 다음, 네이트 같이 국내에서 수위를 다투는 사이트들은 이 방식을 사용한다고 보시면 틀림 없습니다.
찾아보니..
JBoss에는 SRP기반의 인증 시스템이 붙어 있네요.
정확한 사용법은 문서를 찾고 있는 중인데..
(뭐, 일반적인 웹에서 그리 쓸만할 것 같지는 않습니다. 인증시스템들이야 이래저래 붙어있긴 하지만.. 상황이랑 그리 딱 떨어지게 만들어 놓는게 아니니.. JBoss 관리 목적의 사용자 인증이라면 모를까.. @.@)
만약, 범용적으로 사용하기 용이하게 되어 있다면, 나름대로 쓸만할 것 같네요.
[quote="chronon"]https 를 사용하면 안전하지요?[/qu
그럴수도 있고 아닐 수도 있는데요.
HTTPS에서 공격이 가능한 간단한 시나리오는,
1) 서버는 Root CA가 아닌 곳에서 서명한 certificate를 사용한다. (예를들어, 자기 자신이 서명한 certificate)
2) 공격자는 웹 서버와 동일하게 보이는 certificate를 가진 가짜 웹 서버를 만든다. (본래의 웹서버가 제대로 인증된 certificate을 갖고 있는게 아니므로 이것이 쉽게 가능해진다.)
3) 공격자는 ARP 를 통해, 자신을 DNS로 속인다.
4) Victim은 웹 서버의 DNS를 찾고자하고, 공격자의 머신을 DNS로 착각한다.
5) Victim은 공격자가 제공하는 DNS에서 웹 서버의 주소를 받는다. 물론 이때 제공된 주소는 공격자가 작성한 certificate를 갖는 가짜 웹서버 SSL Proxy이다.
6) Victim은 SSL Proxy에 접속한다.
7) 이 단계에서 변경된 certificate이 Victim에게 전달되지만, Victim은 이 사실을 알아채지 못한다.
8 ) 공격자는 SSL Proxy를 통하여 Victim과 실제 웹 서버간의 통신을 중계하면서, 통신 내용을 엿듣거나 조작한다.
이런 종류를 MITM(Man-in-the-Middle) Attack 이라 합니다.
--
Passion is like genius; a miracle.
댓글 달기