Home > Article > Backend Development > yii2’s preventive measures against CSRF attacks
This article mainly introduces the preventive measures against CSRF attacks in yii2. It has certain reference value. Now I share it with you. Friends in need can refer to it.
Today Brother Bei will popularize it for everyone. What is csrf? If you already know, you can just scroll to the bottom of the article and give it a like.
CSRF (Cross-site request forgery) is a malicious use of websites. It was listed as one of the top 20 Internet security threats in 2007. One of the hidden dangers.
Regarding CSRF, we have to start with a story~
This story starts with the programmer Lao Wang losing 10,000 yuan. In short It was a thief, but it was recovered to no avail. After losing the money, Lao Wang kept thinking, How did he lose the money, why did he lose the money, why did I lose the money~~
Later, Lao Wang developed serious psychological problems. Decided to take revenge on society.
Lao Wang first studied the online banking system, and he found that the transfer was in the form of GET
https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=abei
This means that the 1,000 yuan from liuxiaoer was transferred to abei , of course, when the request reaches the bank server, the program will verify whether the request comes from a legitimate session and the user of the session is liuxiaoer and has logged in.
Lao Wang himself also has a bank accountwang2. He tried to log in and sent a request to the bank through the browser. The code is as follows
https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=wang2
It failed~because the current login account is Lao Wang himself, after sending the request, the server found that the user wang2 and account=liuxiaoer to which the session belonged were not the same person, so it was rejected.
That is to say, this operation must be done by liuxiaoer. The power of revenge is terrible. Lao Wang found liuxiaoer through Facebook, which is the courier Lao Wang Liu’s bank account number.
So a great plan was born, Lao Wang’s plan was like this.
1. First make a web page, add the following code to the web page
src="https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=wang2"
, and then let Liu (liuxiaoer) visit this web page through various scenarios.
2. When Lao Liu (liuxiaoer) visits this web page, the above request will be sent to the bank, and at this time it will also carry Lao Liu (liuxiaoer)'s own browser cookie information. Of course, this is generally not the case. It will succeed because the bank server finds that Liu (liuxiaoer) is not logged in.
3. Lao Wang thought of a trick. He found a gray businessman Lao Li on Taobao and asked him to use various methods. In short, he asked Lao Liu (liuxiaoer) to transfer money to Lao Li through the browser.
4. Within 2 minutes of the third step, Lao Wang successfully asked Lao Liu (liuxiaoer) to visit the web page he created again. As you know, Lao Liu (liuxiaoer) was in the bank at the moment. The session has not expired. After Lao Wang's webpage sent a request to the bank server, the verification passed and the payment was successful.
5. Lao Wang received the payment. Lao Liu (liuxiaoer) did not know all this. For the bank, this was a normal transfer.
This is a CSRF attack and the browser cannot intercept it.
Based on the bloody story above, we summarize several characteristics of CSRF attacks.
Hackers use the victim's cookie and other browser information to deceive new users of the server. The hacker cannot get the cookie, etc.
Due to the browser's same-origin policy, hackers cannot get the response results of the attack. All they can do is initiate a request. Do you still remember that many phishing websites simulate login boxes?
CSRF attacks mainly send requests to modify data.
So what we want to protect are all client requests that can cause data changes, such as new, update and delete.
Based on the characteristics of CSRF attacks, there are currently three main strategies to defend against CSRF attacks in the industry:
Verify the HTTP Referer field;
Add token in the request address and verify it;
Customize the attribute in the HTTP header and verify it.
When making an http request, there is a field called Referer in the header, which records the source address of this request. Therefore, the server can determine whether the request is legal by whether this field is the same domain name, because the referer of the request initiated by the client's own webpage is a hacker website.
This method is the simplest and does not require modification of the business code. We only need to intercept and analyze each request arriving at the server.
But the shortcomings of this method are also obvious, because the value of Referer belongs to the browser. Although the HTTP protocol does not allow modification, if there are loopholes in the browser itself, it may cause the Referer to be manually set. Not safe.
For example, IE6 can tamper with the Referer value through methods.
This method is not absolutely available even in the latest browsers. It involves user privacy. Many users will set the browser not to provide Referer, so the server cannot rashly do so if it cannot get Referer. Decline service, it's possible this is a legitimate request.
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。
这个方法在思路上和上面的token方式一样,只不过将token放到了HTTP头部中,不再参数传递,通过XMLHttpRequest类可以一次性的给所有请求加上csrftoken这个HTTP头属性并设置值。
这种方法适合上面批量添加token不方便的情况,一次性操作,不过局限性也比较大,XMLHttpRequest请求通常用在ajax方法中,并非所有请求都适合。
首先要说的是每种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,只要有一种验证通过,就认为合法。
以上是整体的思路,为了让你看的更清晰,我画一个图并增加一些名词解释。
以上是yii2的csrf策略部署,当然我还是推荐你使用 xdebug等调试工具 一步一步看看这个过程。
最后我在把上图的关键函数进行说明
generateCsrfToken() 该函数生成token并存到cookie或session中,该值不会随页面刷新而变化,它更多充当钥匙的作用,根绝它生成具体的csrfToken。
getCsrfToken() 生成具体的csrfToken,就是你在表单隐藏域中看到的那个值,这个值将来会传到服务器和真实的csrfToken进行对比,验证是否合法。
validateCsrfToken() 进行合法性验证,该函数得到一个真实的csrfToken然后和客户端上传来的csrfToken进行对比。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
The above is the detailed content of yii2’s preventive measures against CSRF attacks. For more information, please follow other related articles on the PHP Chinese website!