>백엔드 개발 >PHP 튜토리얼 >CSRF 공격에 대한 yii2의 예방 조치

CSRF 공격에 대한 yii2의 예방 조치

不言
不言원래의
2018-07-10 15:06:362030검색

이 글은 Yii2의 CSRF 공격에 대한 예방 조치를 주로 소개합니다. 이제 여러분과 공유합니다. 도움이 필요한 친구들이 참고할 수 있습니다.

오늘은 Bei 형제가 CSRF를 대중화할까요? 이미 알고 계시다면 기사 하단으로 스크롤하여 좋아요를 눌러주세요.

CSRF(교차 사이트 요청 위조)는 웹사이트를 악의적으로 사용하는 행위로, 2007년 상위 20대 인터넷 보안 위험 중 하나로 선정되었습니다.

CSRF에 대한 이야기부터 시작해볼까요~

Lao Wang이 돈을 잃은 사건

이 이야기는 프로그래머 Lao Wang이 10,000위안을 잃은 것으로 시작됩니다. 한마디로 도둑이었고 그것을 되찾지 못했습니다. 돈을 잃은 후 라오왕은 그는 어떻게 돈을 잃었는지, 왜 돈을 잃었는지, 내가 왜 돈을 잃었는지~~

나중에 라오왕은 심각한 심리적 문제를 일으키고, 사회에 대한 복수.

Lao Wang은 먼저 온라인 뱅킹 시스템을 연구한 결과 GET

https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=abei

형식으로 이체된다는 사실을 발견했습니다. 이는 liuxiaoer에서 1,000위안이 abei로 이체된다는 의미입니다. 은행 서버에서 프로그램은 요청이 합법적인 세션에서 왔고 해당 세션의 사용자가 liuxiaoer이고 로그인했는지 여부를 확인합니다.

Lao Wang 자신도 은행 계좌 wang2를 가지고 있습니다. 로그인을 시도하고 브라우저를 통해 은행에 요청을 보냈습니다. 코드는 다음과 같습니다

https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=wang2

실패했습니다~ 현재 로그인 계정은 Lao Wang 자신입니다. . 요청을 보낸 후 서버는 해당 세션이 사용자 wang2에 속해 있고 account=liuxiaoer가 동일한 사람이 아니라는 사실을 발견하여 거부되었습니다.

즉, 이 작업은 liuxiaoer가 직접 수행해야 합니다. Lao Wang은 택배 Lao Liu의 은행 계좌 번호인 겹겹이 Facebook을 통해 liuxiaoer를 발견했습니다.

그래서 훌륭한 계획이 탄생했고, 라오왕의 계획은 이랬습니다.

1. 먼저 웹 페이지를 만들고 웹 페이지에 다음 코드를 추가하세요

src="https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=wang2"

그런 다음 Liu(liuxiaoer)가 다양한 시나리오를 통해 이 웹 페이지를 방문하도록 하세요.

2. Lao Liu(liuxiaoer)가 이 웹페이지를 방문하면 위의 요청이 은행으로 전송되며, 이때 Lao Liu(liuxiaoer)의 자체 브라우저 쿠키 정보도 함께 전달됩니다. 은행 서버에서 Liu(liuxiaoer)가 로그인되지 않은 것을 발견했기 때문에 일반적으로 성공하지 못합니다.

3. 라오왕은 타오바오에서 회색 사업가 라오리를 발견하고 그에게 다양한 방법을 사용해 달라고 부탁했다. 즉, 라오리우(liuxiaoer)에게 브라우저를 통해 돈을 송금해 달라고 부탁한 것이다.

4. 세 번째 단계에서 2분 이내에 Lao Wang은 Lao Liu(liuxiaoer)가 다시 만든 웹페이지를 방문하도록 허용했습니다. 아시다시피 Lao Liu(liuxiaoer)의 은행 세션은 아직 만료되지 않았습니다. , Laowang의 웹페이지가 은행 서버에 요청을 보낸 후 인증이 통과되어 결제가 성공적으로 이루어졌습니다.

5. Lao Wang은 이 모든 것을 몰랐습니다. 은행에서는 이것이 정상적인 송금이었습니다.

이것은 CSRF 공격이므로 브라우저가 이를 차단할 수 없습니다.

CSRF 공격의 특징

위의 피비린내 나는 이야기를 바탕으로 CSRF 공격의 몇 가지 특징을 요약합니다.

  • 해커는 피해자의 쿠키 및 기타 브라우저 정보를 사용하여 서버의 새로운 사용자를 속입니다. 해커는 쿠키 등을 얻을 수 없습니다.

  • 브라우저의 동일 출처 정책으로 인해 해커가 할 수 있는 일은 요청을 시작하는 것뿐입니다. 많은 피싱 웹사이트가 로그인 상자를 시뮬레이션한다는 사실을 기억하시나요?

  • CSRF 공격은 주로 데이터 수정 요청을 보냅니다.

CSRF 방어 객체

그래서 우리가 보호하고 싶은 것은 신규, 업데이트, 삭제 등 데이터 변경을 일으킬 수 있는 모든 클라이언트 요청입니다.

CSRF 방어 솔루션

현재 업계에서는 CSRF 공격을 방어하기 위한 세 가지 주요 전략이 있습니다.

  • HTTP Referer 필드를 확인합니다.

  • 요청 주소에 토큰을 추가합니다.

  • HTTP 헤더의 사용자 정의 속성을 확인하고 확인하세요.

HEEP Referer

http 요청을 할 때 헤더에 이 요청의 소스 주소를 기록하는 Referer라는 필드가 있습니다. 따라서 서버는 클라이언트 자체 웹페이지에서 시작된 요청의 리퍼러가 해커 웹사이트이기 때문에 이 필드가 동일한 도메인 이름인지 여부에 따라 요청이 적법한지 여부를 판단할 수 있습니다.

이 방법은 가장 간단하며 비즈니스 코드 수정이 필요하지 않습니다. 서버에 도착하는 각 요청을 가로채서 분석하기만 하면 됩니다.

하지만 이 방법의 단점도 분명합니다. 왜냐하면 Referer의 값이 브라우저에 속하기 때문입니다. HTTP 프로토콜은 수정을 허용하지 않지만 브라우저 자체에 허점이 있는 경우 Referer를 수동으로 설정해야 할 수 있습니다. 안전하지 않습니다.

예를 들어 IE6에서는 메소드를 통해 Referer 값을 조작할 수 있습니다.

이 방법은 최신 브라우저에서도 절대 사용할 수 없습니다. 이는 사용자의 개인 정보를 포함하므로 많은 사용자가 리퍼러를 제공하지 않도록 브라우저를 설정하므로 서버가 리퍼러를 얻을 수 없으면 함부로 서비스를 종료할 수 없습니다. 이는 정당한 요청입니다.

添加Token

CSRF攻击之所以能成功,是因为黑客完全伪造了一次用户的正常请求(这也是浏览器无法拦截的原因),并且cookie信息就是用户自己的,那么我们如果在请求中放入一些黑客无法去伪造的信息(不存在与cookie中),不就可以抵御了么!

比如在请求前生成一个token放到session中,当请求发生时,将token从session拿出来和请求提交过来的token进行对比,如果相等则认证通过,否则拒绝。token时刻在变化,黑客无法去伪造。

针对于不同类型的请求一般方案是

  • GET 放到url中,比如http://url?csrftoken=xxxx

  • POST 放到表单的隐藏域

对于GET请求,这里有一点要说明,在一个网站中请求的url很多,一般情况我们是通过js对dom的所有节点进行遍历,发现a链接就在其href中增加token。

这里存在一个问题,比如黑客将自己网站的链接发到了要攻击页面,则黑客网站链接后面会有一个token,此刻客户可以通过编写自己网站代码得到这个token,然后用这个token立刻构造表单,发起CSRF攻击,因此在js遍历的时候,如果发现不是本站的链接,可以不加token。

在HTTP头部增加属性

这个方法在思路上和上面的token方式一样,只不过将token放到了HTTP头部中,不再参数传递,通过XMLHttpRequest类可以一次性的给所有请求加上csrftoken这个HTTP头属性并设置值。

这种方法适合上面批量添加token不方便的情况,一次性操作,不过局限性也比较大,XMLHttpRequest请求通常用在ajax方法中,并非所有请求都适合。

Yii2

首先要说的是每种CSRF防范措施都有其弊端,无论你的防范多么严密,黑客拥有更多的攻击手段,因此在重要逻辑上(必须写入和删除)必须非常小心,接下来我们把yii2框架在csrf上的部署说一下。

我们以yii2.0.14为解说版本。

在CSRF这块,yii2框架采取了HTTP头部和参数token并行的方式,针对于每个请求,在beforeAction都会做一次判断,如下

// vendor/yiisoft/yii2/web/Controller.php
public function beforeAction($action) {
    
    if (parent::beforeAction($action)) {
        if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) {
            throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.'));
        }

        return true;
    }

    return false;
}

如果我们没有设置 enableCsrfValidation 为false,并且没有报错,则会进行csrf验证,核心方法就是

Yii::$app->getRequest()->validateCsrfToken()

该方法存在于 vendor/yiisoft/yii2/web/Request.php 中,我们看一看它。

public function validateCsrfToken($clientSuppliedToken = null) {
    // 省略上面代码
    return $this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken)
        || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken);
}

validateCsrfToken函数代码我们只需要看最后的返回,getBodyParam或getCsrfTokenFromHeader方法得到的token,只要有一种验证通过,就认为合法。

以上是整体的思路,为了让你看的更清晰,我画一个图并增加一些名词解释。

CSRF 공격에 대한 yii2의 예방 조치

以上是yii2的csrf策略部署,当然我还是推荐你使用 xdebug等调试工具 一步一步看看这个过程。

最后我在把上图的关键函数进行说明

  • generateCsrfToken() 该函数生成token并存到cookie或session中,该值不会随页面刷新而变化,它更多充当钥匙的作用,根绝它生成具体的csrfToken。

  • getCsrfToken() 生成具体的csrfToken,就是你在表单隐藏域中看到的那个值,这个值将来会传到服务器和真实的csrfToken进行对比,验证是否合法。

  • validateCsrfToken()  进行合法性验证,该函数得到一个真实的csrfToken然后和客户端上传来的csrfToken进行对比。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

如何在yii2-wx中使用try_catch

关于Yii2中GridView的用法总结

위 내용은 CSRF 공격에 대한 yii2의 예방 조치의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.