Extra Form
PHP PHP 7.2
CMS XpressEngine

최근 뭔가 생각해보다

 

회원이 탈퇴(삭제) 되면 개인정보를 파기하는데 일부(이메일) 정보를 특정 테이블에 기록해 두었다가 탈퇴 후 재가입 이라는 것을 허용하지 않는 데이터로 이용하는 것에 관해 궁금증이 생겼습니다.

 

포털 등에서 이런 방식으로 운영중인데요. 특별히 언급된 곳은 암호화되어 저장한다라고 명시를 하더군요.

 

파기를 하지 않고 지정된 기간동안 보관을 하는데 암호화 여부는 필수는 아닌 듯 합니다.

 

그런데 저희 XE의 경우도 회원의 비밀번호 같은 것을 관리자도 확인이 안되는 암호화된 상태로 저장을 합니다. 이것은 사람이 복호화 할 수 없는 것으로 아는데요.

 

이런 기능은 코어에서 제공하는 것이죠? 암호화하겠다라 라고 하는 코드 자체가 아주 간단한 건가요?

그리고 이를 복호화 하는 것은 불가능한건지도 궁금합니다.

  • profile
    회원설정에서 보니 회원비밀번호 암호화 알고리듬을 선택하게 되어 있으니 데이터 저장 자체를 암호화 하는 함수는 없는거겠네요.

    저 비밀번호 필드만 정해진 알고리즘에 의해 암호화 저장하는 기능을 제공하나 봅니다.

    일부 다른 암호화 하는 것이 있는지는 모르겠는데... 개발자가 저장하는 것 자체를 암호화해서 저장하는 함수가 따로 있을까 해서 질문을 올린건데 없겠죠....
  • profile
    Php 단에서 암호화 하면 됩니다.
  • profile profile
    네. XE코어에서 기능이 제공되는지 궁금해서 여쭤 본건데 아마도 모든 저장 항목에 원하면 바로 사용할 수 있는 기능은 제공하지 않는 것 같군요.
  • profile

    코어에 포함된 Password 클래스를 이용하면 회원 비번뿐 아니라 어떤 정보라도 단방향 암호화할 수 있습니다. 회원 모듈에서 설정된 알고리즘을 반드시 사용할 필요도 없고, 옵션이 굉장히 많습니다. 코어에서도 첨부파일 sid나 이메일 인증코드 등 난수 생성이 필요할 때 Password 클래스를 활용하고 있습니다.

     

    라이믹스는 양방향 암호화 기능까지 제공하는데, XE는 현재 양방향 암호화가 딱히 필요하지 않다 보니 1.8에서 비번 암호화 방식을 개선하면서 도입된 단방향 암호화 기능만 포함되어 있습니다.

     

    단, 특정 메일주소로 재가입하는 것을 막기 위한 용도라면 bcrypt나 pbkdf2처럼 비번 암호화에 권장되는 알고리즘은 적합하지 않습니다. 특정한 해쉬값과 특정한 평문이 일치하는지 비교할 수는 있지만, 특정한 평문과 일치하는 해쉬값이 존재하는지 알기 위해서는 저장되어 있는 모든 데이터를 한 번씩 다 시도해 보아야 하는 비효율이 발생합니다. 비번 무작위 대입 공격에 효과적으로 방어할 수 있도록 설계된 알고리즘이기 때문입니다. 재가입 방지 목적이라면 일치하는 값을 쉽게 찾을 수 있도록 SHA256 등 일반적인 알고리즘을 사용하는 것이 좋겠습니다. 유출시 평문을 쉽게 유추할 수 없도록 pepper를 더하거나 HMAC을 사용하는 정도까지는 괜찮겠네요.

     

    또한 example@gmail, ex.am.ple@gmail, EXAMPLE@gmail, example+foobar@gmail 등 변형된 형태의 메일주소를 무한정 생성할 수 있기 때문에, 암호화하기 전 소문자로 통일하고 불필요한 점과 + 문자 뒷부분을 제거하는 등 약간의 가공을 거치는 것이 좋습니다. 유사한 기능을 의뢰받아 구현한 적이 있는데 은근히 신경써야 할 부분이 많더군요.

  • profile profile
    제가 생각한건 가입후 탈퇴 시점 회원이 가졌던 이메일 주소를 별도 테이블에 다른 것과 매칭이 전혀 안되는 독립된 필드에 저장만 하는 것입니다. 저장의 목적은 동일한 메일로 가입 시 가입 불허 혹은 가입시 주는 포인트 어뷰징을 무력화 하려는 것인데요.

    이때 일정기간 탈퇴한 회원의 이메일 정보를 저장하는 건 개인정보처리방침에 명시하면 되는 듯 합니다. 포털에서도 그렇게 하고 있구요.

    그런데 각 사마다 차이가 나는게 암호화해서 저장한다고 하는 곳과 그냥 언급이 없는 곳이 있는데

    개인적인 생각은 암호화해서 저장합니다. 라고 공시하면 뭔가 좀 믿음이 가는 듯 해서 특정 문자를 자동으로 암호화해서 db에 넣어주고 그리고 그 db를 php등에서 불러왔을때 일반적인 문자로 복호화해서 사용이 XE에서 기본으로 제공하는 함수가 있는가 였습니다.

    처음에 가입한 메일 주소에 다른 변형된 형태의 이메일까지 추가적으로 처리하려는 목적은 아니구요.
  • profile profile

    복호화가 가능하다면 양방향 암호화입니다. 이건 XE에서 기본제공하지 않습니다. 라이믹스에서는 기본제공하고, XE에서도 제가 예전에 자료실에 배포한 "암호화 모듈" 같은 것을 사용하면 구현할 수는 있습니다. (모듈 자체적으로 뭔가를 해주는 것은 아니고, 다른 데서 끌어다 쓸 수 있는 함수만 제공하는 모듈입니다. 워낙 오래 전에 만든 거라 BaseObject 대응도 안 되어 있을 것 같네요.)

    비번 암호화에 흔히 사용되는 것은 복호화가 불가능한 단방향 암호화입니다. 이건 XE의 Password 클래스에 포함된 특정 함수를 사용해서 쉽게 구현할 수 있고, PHP에서 기본 제공하는 md5(), sha1(), hash() 등의 함수를 직접 사용해도 됩니다.

    저장해 두는 목적이 "재가입 방지"라면 salt가 들어가지 않는 단방향 암호화 알고리즘이 가장 적합합니다. 보안성도 비교적 약하고 복호화도 할 수 없지만, 일치 여부를 쉽게 비교할 수 있다는 막강한 장점이 있거든요. salt가 들어가는 알고리즘은 위에서 말씀드린 것처럼 일일이 모두 비교해 보아야 하는 비효율이 발생하고, 양방향 암호화도 마찬가지로 일일이 모두 복호화해서 일치 여부를 확인해야 하기 때문에 마찬가지로 비효율적입니다.

  • profile profile

    단반향이라는게 지금 비밀번호가 db에서 암호화되어 있지만
    회원이 비밀번호를 평문으로 타이핑 했는데도 이게 일치하는지 비교가 가능하다는 것인가요? 저는 이런 구조가 암호화된게 복호화 되어야만 확인이 되는줄 알았습니다.

    그렇다면 제가 상상하는 건 단방향입니다. 운영자 조차도 나중에 삭제하지 않고 딴 맘 먹으려는 못된 맘이 생기지 않도록 하기 위한 자기 검열이라고 할까요......

  • profile profile

    네, 그게 단방향입니다. 복호화할 필요도 없고, 복호화할 수도 없고, 주어진 원본(평문)과 일치하는지만 확인할 수 있도록 만들어진 알고리즘입니다. 원래 CRC32처럼 에러체크에 사용하던 것을 좀더 길게 늘린 거예요.

    예: md5('password') 하면 '5f4dcc3b5aa765d61d8327deb882cf99'가 나옵니다. 이걸 복호화해서 'password'를 얻을 수는 없습니다. 그러나 가입 또는 로그인을 시도하는 시점에는 'password'라는 원본(평문)이 서버로 전송되었을 테니, 이걸 md5() 돌려서 DB에 저장된 것과 비교하면 일치하는지 안하는지 간단하게 알 수 있습니다. 이런 알고리즘들이 취약하다고 하는 이유는 일반적으로 비번으로 쓸 만한 단어들의 md5 결과값이 이미 모두 알려져 있기 때문인데, 비번이 아닌 다른 정보를 비교할 용도라면 상관없습니다.

  • profile profile
    입력하는 시점의 평문을 어떤 함수에 넣고 돌려서 결과값이 나오는 군요.
    5f4dcc3b5aa765d61d8327deb882cf99 의 값으로는 password 라는 것이 확인되지는 않지만

    password 라는 것으로 md5() 함수에 돌리면 5f4dcc3b5aa765d61d8327deb882cf99 값이 나오게 되어 있다. 이런 말씀이시네요..

    뭔가 어렵긴 하고 살짝 한군데 이해가 안가는 구석이 있긴 하지만 신기합니다 ㅋ

    예상되는 평문을 md5() 함수로 돌리면 그 값을 알아낼 수는 있다는 이야기이군요. 그래서 비밀번호 등은 좀 복잡하게 써라는 이유가 여기에 있는 것이네요. 알수록 신기한 세상입니다 ㅋ

    어찌 되었던 단방향으로 제일 간단한 암호화 로 이메일을 암호화해서 별도로 보관하면 쓸모가 있으면서 개인정보 침해도 없고 좋겠네요.
  • profile profile

    탈퇴 시점 [email protected] -> MD5야 얘는 너는 뭐로 알고 있어 ? -> '블라블라블라' -> db에 '블라블라브라' 저장

    관리자나 혹은 다른 누군가라도  블라블라블라 를 가지고 어디에 돌려도 복호화가 되지 않아 안전함,

    저 탈퇴자가 다시 동일한 메일로 가입 시도시 암호화된 메일 주소와 비교를 하기 위해
    가입한 회원이 입력한 "이메일주소" -> MD5야 지금 이메일 주소는 너는 뭐라고 알고 있니 ? -> '블라블라블라'
    --> db에 '블라블라블라' 있네. 너 가입 불가!

    이거군요 ㅋㅋ

  • profile profile

    네, 맞습니다. 다만 원래 평문이 무엇이었는지 알 길이 없고, [email protected][email protected]은 전혀 다른 결과가 나오기 때문에 부정행위의 우려가 있는 메일주소는 미리 약간 정리해 두는 것이 좋다고 말씀드린 겁니다.

    메일 주소라면 1) strtolower 함수를 사용해서 소문자로 통일 2) 골뱅이 앞부분에서 마침표 제거 3) 골뱅이 앞부분에 '+' 기호가 있는 경우, '+' 기호와 골뱅이 사이의 내용('+' 기호 포함)을 제거. 이렇게 3가지만 해주면 지메일에서 지원하는 이메일 무한생성 기능은 모두 무력화시킬 수 있습니다.

    예를 들면 [email protected]으로 가입했던 회원을 강퇴할 때 md5('[email protected]')을 그대로 저장해 두지 말고, md5('[email protected]')을 저장해 두는 겁니다. 그러면 나중에 [email protected]으로 재가입을 시도하더라도 동일한 3단계 가공을 거친 후 비교하면 잡아낼 수 있게 됩니다. 좀더 고급 트릭으로 가면 gmail.com과 googlemail.com을 동일한 도메인으로 취급하고, hanmail.net, hanmail2.net, daum.net을 모두 동일한 도메인으로 취급할 수도 있습니다.

  • profile profile
    변형된 이메일로 시도시 까지 막으려는 의도는 아니에요 ㅋㅋ 제가 지금 구상중인 초대장으로 가입구조로 바꿀 경우 1계정에 포인트를 몰아주는 어뷰징을 시도시 가입,탈퇴(완전 똑같은 메일로) 반복하는 것 정도 까지는 막아주는 기능이 잇어야 할 것 같아 고민해 본거랍니다 ㅋ 더 이상을 원한다면 그건 개발자분의 취향으로 ㅋ