美文网首页
横向越权的问题

横向越权的问题

作者: wbpailxt | 来源:发表于2020-01-06 19:41 被阅读0次

    攻击者尝试访问与他拥有相同权限的用户的资源。
    有这么一种场景:忘记密码需要先回答密保问题,通过了再调用重设密码的接口。
    密保问题url:localhost:8080/user/forget_check_answer.do?username=aaa&question=aa&answer=sss

    request

    username,question,answer

    response

    正确的返回值里面有一个token,修改密码的时候需要用这个。传递给下一个接口

    success

    {
        "status": 0,
        "data": "531ef4b4-9663-4e6d-9a20-fb56367446a5"
    }
    

    fail

    {
        "status": 1,
        "msg": "问题答案错误"
    }
    

    重设密码url:
    localhost:8080/user/forget_reset_password.do?username=aaa&passwordNew=xxx&forgetToken=531ef4b4-9663-4e6d-9a20-fb56367446a5

    request

    username,passwordNew,forgetToken

    response

    success

    {
        "status": 0,
        "msg": "修改密码成功"
    }
    

    fail

    {
        "status": 1,
        "msg": "修改密码操作失效"
    }
    

    {
        "status": 1,
        "msg": "token已经失效"
    }
    

    假如重设密码url是不需要传密保问题返回的token的,当攻击者知道重设密码url时,就可以通过传username和passwordNew参数修改任何的密码。
    那具体是怎么防止横向越权的呢?
    密保问题的处理逻辑:

    public ServerResponse<String> checkAnswer(String username,String question,String answer){
            int resultCount = userMapper.checkAnswer(username,question,answer);
            if(resultCount>0){
                //说明问题及问题答案是这个用户的,并且是正确的
                String forgetToken = UUID.randomUUID().toString();
                TokenCache.setKey(TokenCache.TOKEN_PREFIX+username,forgetToken);
                return ServerResponse.createBySuccess(forgetToken);
            }
            return ServerResponse.createByErrorMessage("问题的答案错误");
        }
    

    重置密码的处理逻辑:

    public ServerResponse<String> forgetResetPassword(String username,String passwordNew,String forgetToken){
            if(org.apache.commons.lang3.StringUtils.isBlank(forgetToken)){
                return ServerResponse.createByErrorMessage("参数错误,token需要传递");
            }
            ServerResponse validResponse = this.checkValid(username,Const.USERNAME);
            if(validResponse.isSuccess()){
                //用户不存在
                return ServerResponse.createByErrorMessage("用户不存在");
            }
            String token = TokenCache.getKey(TokenCache.TOKEN_PREFIX+username);
            if(org.apache.commons.lang3.StringUtils.isBlank(token)){
                return ServerResponse.createByErrorMessage("token无效或者过期");
            }
    
            if(org.apache.commons.lang3.StringUtils.equals(forgetToken,token)){
                String md5Password  = MD5Util.MD5EncodeUtf8(passwordNew);
                int rowCount = userMapper.updatePasswordByUsername(username,md5Password);
    
                if(rowCount > 0){
                    return ServerResponse.createBySuccessMessage("修改密码成功");
                }
            }else{
                return ServerResponse.createByErrorMessage("token错误,请重新获取重置密码的token");
            }
            return ServerResponse.createByErrorMessage("修改密码失败");
        }
    

    通过guavacache缓存token(最好是redis缓存)。重设密码时根据用户名取出缓存中的token和用户传过来的token比较是否一样。

    相关文章

      网友评论

          本文标题:横向越权的问题

          本文链接:https://www.haomeiwen.com/subject/rkakactx.html