路径穿越编码绕过原理

badmonkey 2021年04月08日 39次浏览

路径穿越

起因

webgoat中出现了一道路径穿越的题目,利用的方法是通过url编码绕过对../的过滤
但是笔者不太了解为什么可以这么做,于是查看了webgoat源码。

原理

webgoat采用springboot框架,路径穿越部分逻辑如下

var queryParams = request.getQueryString();
if (queryParams != null && (queryParams.contains("..") || queryParams.contains("/"))) {
    return ResponseEntity.badRequest().body("Illegal characters are not allowed in the query params");
}
try {
    var id = request.getParameter("id");
    var catPicture = new File(catPicturesDirectory, (id == null ? RandomUtils.nextInt(1, 11) : id) + ".jpg");

    if (catPicture.getName().toLowerCase().contains("path-traversal-secret.jpg")) {
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(MediaType.IMAGE_JPEG_VALUE))
                .body(FileCopyUtils.copyToByteArray(catPicture));
    }
    if (catPicture.exists()) {
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(MediaType.IMAGE_JPEG_VALUE))
                .location(new URI("/PathTraversal/random-picture?id=" + catPicture.getName()))
                .body(Base64.getEncoder().encode(FileCopyUtils.copyToByteArray(catPicture)));
    }
    return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .location(new URI("/PathTraversal/random-picture?id=" + catPicture.getName()))
            .body(StringUtils.arrayToCommaDelimitedString(catPicture.getParentFile().listFiles()).getBytes());
} catch (IOException | URISyntaxException e) {
    log.error("Image not found", e);
}
return ResponseEntity.badRequest().build();

可以看到在进行检查时,采用的是getQueryString方法,获取id是使用的是getParamter方法。如果我们访问这样一个url:http://127.0.0.1:8000/WebGoat/PathTraversal/random-picture?id=%2e%2e,
那么getQueryString得到的是%2e%2egetParamter得到的则是..,为了验证这一想法,笔者写了一个小demo

@RestController
public class IndexController {
    @RequestMapping("index")
    public String index(HttpServletRequest request){
        return request.getQueryString()+'\n'+request.getParameter("id");
    }
}

效果如下:

image-20210408163558305

同时验证其他编码方式,返回400

image-20210408163753638

由于webgoat使用的是springboot框架,springboot使用内置的tomcat启动,而tomcat在解析请求参数时(getParamter),貌似会自动进行解码,不过解码只针对形如%十六进制数的格式

所以二次编码时,有如下的效果

image-20210408164114618

至于二次编码的利用形式,笔者还没有遇到过。