programing

AJAX 요구의 신뢰성을 확인하는 방법

lastcode 2023. 2. 13. 20:32
반응형

AJAX 요구의 신뢰성을 확인하는 방법

저는 사용자가 퍼즐을 최대한 빨리 풀 수 있는 웹사이트를 설계하고 있습니다.JavaScript는 각 퍼즐의 타이밍에 사용되며 퍼즐이 완료되면 AJAX를 통해 서버로 밀리초가 전송됩니다.서버에 의해 수신된 시간이 사용자에 의해 위조되지 않았는지 확인하려면 어떻게 해야 합니까?

요청의 정당성뿐만 아니라 값의 소스를 인증해야 하기 때문에 세션 기반 인증 토큰(Rails에서 양식에 사용되는 유형)으로는 충분하지 않다고 생각합니다.

요청서에 암호로 서명할 수 있는 방법이 있나요?해커에 의해 복제될 수 없는 것은 생각할 수 없다.JavaScript는 클라이언트 측에서 노출되어 있기 때문에 조작될 가능성이 있습니까?플래시와 같이 컴파일된 것을 사용해야 하나요? (으악)아니면 비밀키를 숨길 방법이 있을까요?아니면 제가 미처 생각하지 못한 다른 거라도요?

업데이트: 명확하게 말하면, 네트워크 접속이 느린 사람에게 불이익을 주고 싶지 않기 때문에(또한 네트워크 속도가 일정하지 않은 것으로 간주해야 합니다), 타이밍은 100% 클라이언트 측이어야 합니다(사용자가 퍼즐을 볼 수 있는 경우에만 타이머가 시작됩니다).또, 돈이 관련되어 있기 때문에, 「사용자를 신뢰한다」는 것은 받아들일 수 없습니다.

클라이언트의 브라우저는 안전한 계산을 수행할 수 없기 때문에 암호화로 타이밍의 보안을 보장할 수 없습니다.실제 타이밍을 조정함으로써 서버와의 암호화를 우회할 수 있습니다.

또, 서버상의 타이밍도 기능하지 않습니다.라운드 트립 타임의 레이텐시를 고려하지 않으면, 레이텐시가 짧은 유저에게 유리합니다.그 경우, 레이텐시를 추가해 나중에 삭제하는 것으로, 유저가 보상 국면을 방해할 가능성이 있습니다.

물론 사용자가 이를 수정하는 것을 어렵게 만들 수 있지만, 무명에 의한 보안은 지속 불가능한 정책입니다.

즉, 사용자를 어느 정도 신뢰하고(대부분 합리적인 가정), 타이밍을 회피하는 것이 간단하지 않게 게임을 설계하는 것입니다.

이 접근법은 명백히 추측을 하고 있으며 무적이 아니다.모든 계산은 클라이언트에서 수행되며 서버는 백그라운드 검사를 수행하여 요청이 위조되었을 수 있는지 확인합니다.다른 클라이언트 기반 접근법과 마찬가지로 이것은 확정적이지 않지만 거짓말하는 클라이언트는 매우 어렵습니다.

주된 전제는 롱 라이프 사이클HTTP 접속이 데이터 전송에 훨씬 고속이라는 것입니다.어플리케이션 컨텍스트에 따라서는 무시할 수 있는 경우도 있습니다.주가가 1초 안에 여러 번 변할 수 있어 대부분의 온라인 거래 시스템에서 사용되고 있으며, 이것이 현재 가격을 사용자에게 전달하는 가장 빠른 방법이다.HTTP 스트리밍 또는 Comet에 대한 자세한 내용은 여기를 참조하십시오.

먼저 클라이언트와 서버 간에 전이중 Ajax 연결을 만듭니다.서버에는 클라이언트와 통신하기 위한 전용 회선이 있어 클라이언트는 서버와 확실히 통신할 수 있습니다.서버는 이 전용 회선을 통해 퍼즐 및 기타 메시지를 클라이언트에 보냅니다.클라이언트는 로컬 타임스탬프와 함께 서버에 대한 각 메시지의 수신을 확인합니다.

퍼즐이 전송된 후 서버에서 랜덤 토큰(정수만 다를 수 있음)을 생성하고 각 토큰이 생성된 시간을 기록한 후 클라이언트에 전달합니다.클라이언트는 메시지를 보고 이 토큰을 수신한 현지 시각과 함께 즉시 릴레이해야 합니다.할 수 , 이러한 간격으로 를 들어, 「」는 「」라고 하는 것입니다.★★★★★★★★★★★★★★★★★,1 ★★★★★★★★★★★★★★★★★」n

클라이언트가 서버에 송신하는 메시지에는, 다음의 3 종류가 있습니다.

PUZZLE_RECEIVED
TOKEN_RECEIVED
PUZZLE_COMPLETED

서버가 클라이언트에 송신하는 메시지에는, 다음의 2 종류가 있습니다.

PUZZLE_SENT
TOKEN_SENT

클라이언트에서 서버로 전송되는 메시지에는 많은 시간 차이가 있을 수 있지만, 그 반대 방향에서는 훨씬 더 적을 수 있습니다(그리고 그것은 매우 공평한 가정입니다.어디서부터 시작해야 합니다).

서버가 보낸 메시지에 대한 확인을 수신하면 해당 메시지에 포함된 클라이언트 시간을 기록합니다.토큰도 이 메시지로 릴레이 되었기 때문에 서버상의 대응하는 토큰과 대조할 수 있습니다.는 「」를 합니다.PUZZLE_COMPLETED로컬 시간을 포함한 메시지를 서버에 보냅니다.퍼즐을 완성하는 시간은 다음과 같습니다.

PUZZLE_COMPLETED.time - PUZZLE_RECEIVED.time

그런 다음 각 메시지의 보낸 시간과 받은 시간의 차이를 계산하여 다시 확인합니다.

PUZZLE_RECEIVED.time - PUZZLE_SENT.time
TOKEN_RECEIVED.time - TOKEN_SENT.time

이러한 시기에 편차가 크다는 것은 응답이 위조되었을 수 있다는 것을 의미합니다.단순 분산 외에도 이 데이터에 대해 많은 통계 분석을 수행하여 홀수 패턴을 찾을 수 있습니다.

심지어 컴파일된 어플리케이션도 위조될 수 있다.사용자가 타이밍 도중에 시스템클럭을 변경하면 응용 프로그램은 서버에 잘못된 시간을 보고합니다.퍼즐이 주어졌을 때 서버에서 타이밍을 설정하고 정답을 제공할 때 타이밍을 정지하는 방법밖에 없습니다.

다른 사람들이 지적한 바와 같이 퍼즐의 부하를 최대한 줄임으로써 느린 연결로 인한 영향을 최소화할 수 있습니다.페이지 전체와 "게임 엔진"을 먼저 로드한 후 비동기식 요청을 사용하여 퍼즐 자체를 로드합니다(이것은 소량의 데이터여야 함). 가능한 한 공평하게 플레이합니다.

안타깝게도 지연 시간 보정은 조작될 수 있으므로 수행할 수 없습니다.그러나 다른 용도로 사용되지 않는 연결에서는 이러한 요청의 지연이 인간이 퍼즐을 푸는 데 시간이 걸리기 때문에 큰 문제는 아니라고 생각합니다.

(이유: 200ms는 매우 심각한 지연으로 간주되며, 이는 인간의 평균 반응 시간입니다.인간이 완료할 수 있는 가장 짧은 "퍼즐"은 시각 반응 속도 테스트가 될 것입니다. 이 경우, 나쁜 지연은 결과에 대해 100% 마크업됩니다.타이밍 솔루션으로서 이것은 2-OPT입니다.더 복잡한 퍼즐은 지연의 영향을 덜 받습니다.)

또, 인터넷 접속을 사용하지 않고, 가능한 한 빠른 속도로 플레이 할 수 있도록, 속도/레이텐시 테스터에 링크 하는 배너를 페이지에 붙입니다.

조작의 염려 없이 클라이언트측에서 타이머를 기동 및 정지하는 것은 불가능합니다.

클라이언트에서 수행하는 모든 작업은 변경/정지/바이패스할 수 있습니다.

클라이언트에서의 암호화/암호화도 암호화 전에 정보를 변경할 수 있기 때문에 안전하지 않습니다.

돈이 필요하기 때문에 사용자를 신뢰할 수 없습니다.

타이밍은 서버에서 시작하여 서버에서 정지해야 합니다.

퍼즐의 내용이 Ajax 호출의 결과와 함께 반환되는 경우에만 서버에서 타이머를 기동하기 위해 Ajax를 사용합니다.퍼즐을 로드하지 말고, 퍼즐을 검토하는 동안 이것이 납치되어 지연될 수 있기 때문에 Ajax 요청을 전송하십시오.

..

사용하고 있는 서버측의 실장에 따라서는, 타이밍 기능을 서버측에 배치할 수 있습니다.웹 페이지 요청이 이루어진 시간(원하는 경우 데이터베이스에 저장할 수 있음)을 기록한 후 답변을 수신하면 현재 시간을 얻고 연산을 수행하여 응답 시간을 구합니다.데이터베이스 대신 Session 객체에 시간을 저장할 수도 있습니다. 단, Session 객체의 무결성에 대해서는 잘 모릅니다.

여기서는 서버 측 시간을 사용해야 합니다.방법은 다음과 같습니다.

서버에 ping할 준비가 된 문서에 AJAX 요청을 작성합니다.서버 측 코드가 ping을 수신하면 서버 측 시간을 세션 변수로 저장합니다(변수가 이미 존재하지 않는지 확인합니다).퀴즈를 마치면 다시 서버 측 시간을 세션 변수와 비교하여 기간을 결정합니다.세션 변수를 제거합니다.

기능하는 이유:

  • 퀴즈를 보기 전에 타이머를 시작하지 마십시오.
  • AJAX 요구가 수신될 때까지 타이머가 시작되지 않기 때문에 네트워크 지연이 고려됩니다(접속 속도가 느린 경우 AJAX 요구는 느려집니다).
  • 저장하기 전에 세션 변수가 존재하지 않는지 확인해야 하므로 ping은 스푸핑할 수 없습니다.

편집: 클라이언트측의 시간을 계속 유지할 수 있어 최종 투고에 포함시킬 수 있다는 것을 덧붙이고 싶습니다.그런 다음 서버 측에서 계산된 시간과 비교할 수 있습니다.상당히 가까운 경우 클라이언트 시간을 신뢰할 수 있습니다.

원래 질문에서 많은 질문을 하셨는데, 그 중 하나만 대답하겠습니다.

플래시와 같이 컴파일된 것을 사용해야 하나요? (으악)

. 기준: 1) 100% 정확하고 2) 사용자의 간섭 가능성이 없는 경우 컴파일된 바이너리를 사용해야 합니다.

플래시일 필요는 없습니다.플래시를 생각하면 자바 애플릿을 추천합니다.

-- 편집:

이 솔루션은 아래 조프렉스가 지적한 바와 같이 다소 결함이 있습니다.

-- 구:

여기 방법이 있습니다(단, 프로파일링을 해야 합니다).

퍼즐을 재생하는 동안 JavaScript가 해결해야 할 일련의 "문제"를 보내십시오.이전에는 prime1 * prime2의 결과가 될 수 있도록 N의 크기를 충분히 설정했습니다.이것에 의해, 클라이언트는 그 수를 계수화(JavaScript 로 이것을 실시하기 위한 코드를 취득할 수 있습니다)해, 시간이 걸립니다(이것은 클라이언트의 프로파일링을 실시해, 적절한 사이즈의 소수를 송신합니다(분명히, 열화 공격의 대상이 됩니다).

그런 다음 이러한 주요 문제(또는 다른 유형) 중 500개를 전송하고 JavaScript가 백그라운드에서 해결하도록 합니다.솔루션 목록이 생성되고 완료된 값을 보낼 때 이 목록도 전송됩니다.제공된 답안의 총 개수를 통해 퍼즐에 걸린 시간을 확인할 수 있습니다.

단점:

  • 다양한 클라이언트의 능력을 판단하기 위한 프로파일링 필요(따라서 문제의 어려움)
  • 다운그레이드 가능
  • 약간 복잡하다
  • JavaScript 계산이 일반적인 퍼즐 해결을 방해할 수 있습니다.
  • JS보다 빨리 문제를 해결하기 위해 봇을 작성할 수 있습니다.

장점:

  • 양식을 제출하려면 계산을 수행해야 합니다.
  • 올바르게 구현되면 사소한 공격을 제외한 모든 공격이 방지됩니다.

확실히, 공격하기 쉽지만, 나는 그것이 합리적이라고 생각한다.적어도 작업하는 것은 재미있습니다. :)

다만, 최종적으로는, 시큐러티가 높은 클라이언트측 시스템을 실제로 인스톨 할 필요가 있습니다.플래시는 디컴파일이 간단하기 때문에 이러한 기능이 아닙니다.사실, 여기 호주에서 IQ 테스트가 있었는데, TV에서 라이브로 진행되는 Flash 앱을 통해 제어되었습니다.물론, 우승자는 컴퓨터 프로그래머였는데, 왜 그랬을까?p

-- 편집:

OP, 또, 이 투고에 코멘트로 링크했습니다만, 혹시 모르니까, Hashcash에 흥미가 있는 것은, 고객이 어느 정도의 「Work」를 완료하고 있는 것을 나타내는 것을 목적으로 하고 있습니다.제 실장이 적절하지 않다고 해도, 그 분야에 대한 리뷰는 유익할 것입니다.

기본적으로 해결할 수 없기 때문에 까다로운 문제이기 때문에 최선을 다하기 위해 절충점을 찾아야 합니다.기술적인 측면에서는 (a) Flash, Windows, Silverlight, JVM 등의 컴파일이 실제로 도움이 될 것이라고 생각하는 데 시간을 낭비하지 말고 (b) 먼저 암호화된 실제 퍼즐 페이로드만 전송한 다음 (c) 실제 병목 현상이 키만 전송하므로 (c) 수백 개의 전송 시에도 지연이 발생합니다.바이트 수는 인간의 반응 시간에 비해 무시할 수 있습니다.

한 가지 언급을 하지 않은 것은 다음과 같습니다.

사후 감사 및 사용자 추적을 사용합니다.이게 진짜 카지노가 돌아가는 방식이야이것이 PayPal이 돈을 벌어들인 방법의 큰 부분을 차지한다고 한다.두 경우 모두 사전에 보안을 철저히 하기보다는 플레이어에 대한 모든 것을 면밀히 감시하고 의심스러운 플레이어에 대해 많은 기술(통계, 패턴 검출 등)을 사용하여 조사합니다.카지노도 페이팔도 바로 돈을 받을 수 없다.당신은 칩을 현금으로 바꾸거나 페이팔 시스템에서 진짜 은행으로 돈이 들어올 때까지 기다려야 한다.시스템은 같은 방법으로 동작해야 합니다.최소 며칠 동안은 실제로 자금을 조달할 수 없기 때문에(충분히 신속한 감사 시스템을 확립할 수 없는 경우는 더 오래 걸립니다), 당첨금을 압류할 수 있는 시간을 확보할 수 있습니다.변호사를 선임하셨죠?또한 카지노와 PayPal은 당신의 실생활 정체성(돈을 거래하기 위해 꼭 필요한 것)을 알고 있기 때문에 합법적으로, 혹은 더 중요한 것은 그들이 그들을 합법적으로 추적할 수 있기 때문에 공격하려는 사람들을 막을 수 있다는 것이다.

다른 팁과 함께, 이것은 부정행위를 완전히 없애기에 충분할 것이다.

만약 그렇지 않다면, 부정행위를 완전히 없애는 것이 아니라 허용 가능한 수준으로 유지하는 목표를 세우세요.99.99%의 가동시간을 갖는 것과 같습니다.네, 한 포스터에서 언급했듯이, 한 명이라도 타협할 수 있다면 모두가 망하지만, 좋은 감사 시스템을 사용하면 공격자는 지속적으로 부정행위를 할 수 없습니다.만약 그들이 운이 좋다면 1000번 중 1번 정도 부정행위를 할 수 있고 잡히기 전에 한두 번 이상 부정행위를 할 수 없다는 것을 알게 된다면, 그것은 문제가 되지 않을 것이다. 왜냐하면 매우 적은 양의 부정행위에 영향을 받을 수 있는 매우 적은 수의 정직한 사용자도 매우 낮은 확률이기 때문이다.눈치채지 못할 거야만약 당신이 정직한 사용자에게 피해를 주는 실제 부정행위를 저지른 적이 있다면, 그 한 명의 고객의 가치에 비례하지 않는 정도로 정직한 사용자가 결과에 만족하도록 노력하세요.그래야 모두가 보안에 확신을 가질 수 있습니다.그들은 아무것도 걱정할 필요가 없다는 것을 안다.

테크놀로지 솔루션만으로 사람 문제를 해결할 수 있는 것은 아닙니다.때로는 사람 솔루션을 사용할 필요가 있습니다.(이 테크놀로지는, 이러한 유저의 솔루션이 보다 효율적으로 기능하는 것을 지원합니다).

실례합니다만, 왜 서버상의 시간을 사용할 수 없는 것입니까?응답을 받은 시간이 점수를 계산하는 데 사용됩니다.

몇몇 다른 사람들이 지적했듯이:

  1. 클라이언트 시간은 조작에 취약하므로 서버 시간을 사용해야 합니다.
  2. 서버의 시각을 체크하면, 네트워크 접속이 느린 사람이나 멀리 있는 사람에게 불이익을 줄 가능성이 있습니다.

이 문제에 대한 해결책은 클라이언트와 서버 간에 NTP가 사용하는 프로토콜과 유사한 시간 동기화 프로토콜을 사용하는 것입니다.클라이언트와 서버는 연계하여 네트워크 지연으로 인한 지연량을 결정합니다.이 값은 각 사용자에게 주어진 시간에 반영됩니다.

NTP의 알고리즘은 복잡하며 수년간 개발되어 왔습니다.하지만 간단한 접근법은 다음과 같습니다. 프로토콜은 작동해야 하지만 테스트해 볼 수도 있습니다.

클라이언트에 연속된2개의 HTTP XMLRPC ping을 사용하여 라운드 트립 시간을 측정하도록 합니다.ping마다 다른 난스가 반환됩니다.두 번째 ping에서는 첫 번째 ping의 난스가 필요하며, 이를 통해 연속성이 보증됩니다.퍼즐 타임은 클라이언트에서두 번째 HTTP ping이 송신되면 시작됩니다.서버는 각 요구에 타임스탬프를 설정하고 첫 번째 요구와 두 번째 요구 수신 사이에 퍼즐이 1/2 방향으로 표시되는 것으로 가정합니다.

퍼즐이 완료되면 클라이언트는 이전과 동일한 프로토콜을 따라 다시 두 번 ping을 수행합니다.서버는, 각 요구를 수신하는 타이밍과 시간 델타를 인식하고 있습니다.이제 시간 델타의 절반을 가져와서 두 번째 세트의 첫 번째 ping을 수신했을 때부터 뺍니다.그것은 퍼즐이 완성된 시점으로 추정할 수 있다.

여기에서는 매우 빠른 암호화 구현이 있습니다.

http://crypto.stanford.edu/sjcl/

클라이언트상에서 모두 공개/비밀키 암호화를 가능하게 합니다.서버와 클라이언트브라우저간의 Ajax 통신을 암호화하도록 조정할 수 있다고 생각합니다.

자세한 설명은 이쪽에서 보실 수 있습니다.http://crypto.stanford.edu/sjcl/ #http://http://crypto.stanford.edu/sjcl/

간단한 생각: iFrame을 사용하여 게임과 자바스크립트를 포함하고 서버 측 구현을 실행 중인 서버에 상주시키는 것은 어떨까요?그 후, 모든 ajax 요구는, 송신원 식별의 문제를 해결하는 서버측의 IP 와 같은 IP 에 의해서 송신됩니다.물론 더 많은 조치를 취해야 하지만, 이미 "고객" 측의 요청에 대해 많은 신뢰를 얻었습니다.창문에 주의해 주세요.라이브 서비스 로그인은 Javascript와 iFrames 사용에 기반하고 있으며 충분히 안전한 것으로 간주됩니다.

나는 완벽한 해결책이 있다고 생각하지 않는다.여기 부정행위를 하는 사람들을 더 힘들게 하는 대안이 있다. 그러나 동시에 운이 없는 정직한 해결사는 손해를 볼 수도 있다.

사이트와의 다른 상호작용을 바탕으로 각 사용자의 특정 디바이스/장소/기타 조합 어플리케이션에서 다수의 라운드 트립 시간 측정 샘플을 얻을 수 있습니다.전체 모집단에 대한 측정값도 있습니다.ISP의 리졸바(랜덤호스트명 및 그 도메인의 신뢰할 수 있는 DNS 서버를 호스트 하는 경우)로부터 특정 DNS 룩업이 발생했을 때의 타임스탬프를 취득하는 것도 매우 미묘한 방법입니다.

이것을 입수하면, 서버측의 모든 측정(사용자에게 반환된 퍼즐, 솔루션 수신)을 실행해, 이전의 관찰에 근거해 네트워크 시간을 뺍니다.

다른 솔루션에서도 타이밍에 영향을 주는 서버 부하, 클라이언트 부하(저속 프로세서 등)가 있는 것에 주의해 주세요.

퍼즐 제출 페이지에서 XSRF 보호가 설정되어 있는지 확인합니다.

이렇게 하는 방법은 서버가 퍼즐을 클라이언트에 보낼 때 현재 시간이 세션에 저장된다는 것입니다.이렇게 하면 퍼즐이 전송된 직후에 타이밍이 시작됩니다.퍼즐이 완성되어 서버에 보내져 퍼즐이 제대로 되었는지 확인한 후, 서버는 다시 시간을 확인하고 비교한다.

인터넷 접속이 느리면 시간이 더 길어질 수 있지만 어쩔 수 없습니다.

언급URL : https://stackoverflow.com/questions/2017094/how-to-check-authenticity-of-an-ajax-request

반응형