Подтвердить что ты не робот

Какой лучший способ защитить от атаки обхода пути?

У меня есть реализация сервера Java (TFTP, если это имеет для вас значение), и я хотел бы убедиться, что он не подвержен атакам обхода пути, позволяющим доступ к файлам и местоположениям, которые не должны быть доступны.

Моя лучшая попытка защитить до сих пор - отклонить любые записи, которые соответствуют File.isAbsolute(), а затем полагаться на File.getCanonicalPath(), чтобы разрешить любые компоненты ../ и ./ выйти из пути. Наконец, я гарантирую, что результирующий путь все еще находится в пределах требуемого корневого каталога моего сервера:

public String sanitize(final File dir, final String entry) throws IOException {
    if (entry.length() == 0) {
        throw new PathTraversalException(entry);
    }

    if (new File(entry).isAbsolute()) {
        throw new PathTraversalException(entry);
    }

    final String canonicalDirPath = dir.getCanonicalPath() + File.separator;
    final String canonicalEntryPath = new File(dir, entry).getCanonicalPath();

    if (!canonicalEntryPath.startsWith(canonicalDirPath)) {
        throw new PathTraversalException(entry);
    }

    return canonicalEntryPath.substring(canonicalDirPath.length());
}

Есть ли проблемы с безопасностью, которые не хватает? Лучше/быстрее добиться надежного результата?

Код должен работать последовательно в Windows и Linux.

4b9b3361

Ответ 1

Если вы используете это на unix-машине (я не уверен, что в окнах есть что-то похожее, но это может быть), вы захотите посмотреть на chroot. Даже если вы считаете, что у вас есть все возможности для того, чтобы кто-то ссылался на несколько каталогов, приятно иметь там операционную систему.

(chroot заставляет "/" ссылаться на какой-либо другой каталог, поэтому "/" может быть "/home/me/project" и "/../../.." по-прежнему "/home/me/проект" ).

EDIT:

Здесь есть системный вызов chroot, а также инструмент командной строки chroot. Я не знаю, имеет ли Java собственный метод, но ничто не помешает вам запустить ваш сервер с помощью средства командной строки. Это, конечно же, должно быть сделано для того, чтобы делать все возможное, чтобы предотвратить другие манипуляции с путями.

Ответ 2

Следующие могут помочь. Он сравнивает канонические и абсолютные пути, и если они отличаются друг от друга, то это провалится. Проверяется только в системе mac/linux (т.е. нет окон).

Это относится к случаю, когда вы хотите разрешить пользователю предоставлять относительный путь, а не абсолютный путь, и вы не допускаете ссылок на родительские каталоги.

public void failIfDirectoryTraversal(String relativePath)
{
    File file = new File(relativePath);

    if (file.isAbsolute())
    {
        throw new RuntimeException("Directory traversal attempt - absolute path not allowed");
    }

    String pathUsingCanonical;
    String pathUsingAbsolute;
    try
    {
        pathUsingCanonical = file.getCanonicalPath();
        pathUsingAbsolute = file.getAbsolutePath();
    }
    catch (IOException e)
    {
        throw new RuntimeException("Directory traversal attempt?", e);
    }


    // Require the absolute path and canonicalized path match.
    // This is done to avoid directory traversal 
    // attacks, e.g. "1/../2/" 
    if (! pathUsingCanonical.equals(pathUsingAbsolute))
    {
        throw new RuntimeException("Directory traversal attempt?");
    }
}

Ответ 3

Вы можете проверить допустимые символы в именах файлов (http://en.wikipedia.org/wiki/Filename) и отфильтровать все недопустимые символы (белый список) и то вы можете быть уверены, что у вас есть имя файла.