Based on the previous discussion, I am designing a plugin for APISIX to
protect the API from CSRF attacks. The following are the specific
implementation details and some sample codes.

1. *Configuration*


   - key: User-set secret key, used to generate csrf token
   - expires: token expiration time

2. *Details*

*2.1 generate token*

Generating a token requires random, expires, and key.

Expires and key need to be obtained from the plugin's configuration.

Random is a random number like ngx.time().

First, random, expires, and the key is subjected to sha256 operations to
obtain a signature, then the token is obtained by performing base64
operations on the signature and random and expires.
```
local sign = {
    random = random,
    expires = expires,
    key = key,
  }

sha256:update(core.json.encode(sign))

local digest = sha256:final()
local token = {
    random = random,
    expires = expires,
    digest = digest,

  }

local cookie = ngx_encode_base64(core.json.encode(token))

```

*2.2 Send to the client*

In the header_filter, add a Set-Cookie to the response header if it is a
GET request, with the token generated above.

```

  core.response.set_header("Set-Cookie",
{"csrf_token="..csrf_token..";path=/"})

```

*2.3 Checking CSRF token*

Check the following in the request with the plugin enabled:


   - Whether or not it carries a cookie containing a CSRF token;
   - Whether the request header contains a CSRF token; (This relies on the
   user reading the token from the cookie and carrying it to the request
   header, as we can explain in the plugin's usage documentation)
   - Check that the contents of the two tokens are the same;
   - Deconstruct the token base64 and check for expiration by expires;
   - Recalculate the signature using the random and expires obtained by
   untangling the token, plus the key obtained from the configuration, and
   compare the two signatures for consistency;

If all checks pass, the request is passed. Otherwise, 401 is returned to
the client to intercept the request.

This is basic security based on the inability to generate a token that
matches the signature without the user's secret key.

About this design and process, any thoughts or suggestions?

Zexuan Luo <[email protected]> 于2021年11月11日周四 下午2:31写道:

> I suggest you read through the definition of Double
> Submit Cookie:
> https://github.com/OWASP/CheatSheetSeries/blob/5a1044e38778b42a19c6adbb4dfef7a0fb071099/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md#double-submit-cookie
> ,
> especially the drawback part.
>
> And we need to share more details about how does the plugin generate
> the random token and how does the client interact with the server. To
> avoid vulnerability in this plugin, we need to review it closer.
>
> Baoyuan <[email protected]> 于2021年11月11日周四 上午11:36写道:
> >
> > Thank you very much, Zexuan Luo. I thought about it like this
> >
> > > how to let the client know & set the token?
> >
> > I think I can use Set-Cookie to pass it to the client, the client reads
> the
> > content of the token from the cookie and sets it in the request header.
> > I found that in the server rendering web page structure, it is usually
> > placed in the web page DOM so that the client can be easily carried, But
> > for the restful API structure, I think this method can be done.
> >
> > > what token does the client set? It can't just echo back the encrypted
> > csrf token
> >
> > At present, I really think about it this way, which is to return the
> > encrypted csrf token, I don't understand the problem too much.
> >
> >
> >
> > Zexuan Luo <[email protected]> 于2021年11月10日周三 上午10:18写道:
> >
> > > I have read through the definition of Double
> > > Submit Cookie:
> > >
> https://github.com/OWASP/CheatSheetSeries/blob/5a1044e38778b42a19c6adbb4dfef7a0fb071099/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md#double-submit-cookie
> > >
> > > > the CSRF plugin sets a cookie to the client in each request,
> > > which contains the encrypted csrf token, and the client sets it on the
> > > request header in subsequent requests
> > >
> > > The OWASP guide has listed some drawbacks of csrf token without
> encryption.
> > > The proposal mentions that the client will set the encrypted csrf
> > > token in subsequent requests, then there will be two questions:
> > > 1. how to let the client know & set the token?
> > > 2. what token does the client set? It can't just echo back the
> > > encrypted csrf token
> > >
> > > Baoyuan <[email protected]> 于2021年11月9日周二 下午9:36写道:
> > > >
> > > > Hi Community, I have an idea to design a CSRF plugin for APISIX, the
> > > > purpose is to avoid the danger of routing attacks from CSRF.
> > > >
> > > > Taking into account the stateless nature of APISIX, I plan to use
> Double
> > > > Submit Cookie to verify CSRF attacks.
> > > >
> > > > Simply put, the CSRF plugin sets a cookie to the client in each
> request,
> > > > which contains the encrypted csrf token, and the client sets it on
> the
> > > > request header in subsequent requests. CSRF plugin compares and
> verifies
> > > > the request header with the cookie to prevent CSRF attacks.
> > > >
> > > > The CSRF plugin has two configuration items: key and expires. The key
> > > > requires the user to provide a secret key, and the plugin will
> generate
> > > an
> > > > encrypted cookie based on HMAC the token with this secret key. The
> > > expires
> > > > refers to the cookie expiration time, this is an option, if the user
> does
> > > > not provide, the plugin will provide an appropriate default value.
> > > >
> > > > The plugin works at the route level. Users can turn on the plugin on
> the
> > > > desired route to avoid CSRF attacks on the route as much as possible.
> > > >
> > > > Any ideas or suggestions for these?
> > > >
> > > >
> > > > Best Regards!
> > > >
> > > > Yuan Bao<[email protected]>
> > >
>

Reply via email to