Spring Boot — проблема с безопасностью исполняемых jar файлов запускаемых как init.d сервис

    В spring boot появилась интересная возможность собрать «исполняемый» jar файл, который также может быть init.d сервисом. То есть достаточно будет прописать символьную ссылку из /etc/init.d/myapp на jar-файл и через update-rc.d настроить автозапуск сервиса. Технически jar файл становится bash-скриптом в конце которого находятся бинарные данные.

    Описание данной возможности: docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

    Изучая скрипт файл, я обнаружил некоторые проблемы с безопасностью.

    Скрипт, запускаемый через init.d, запускается с root правами. Если владелец jar-файла пользователь, то запуск java уже происходит от пользователя.

    # Determine the user to run as if we are root
    # shellcheck disable=SC2012
    [[ $(id -u) == "0" ]] && run_user=$(ls -ld "$jarfile" | awk '{print $3}')
    

    Но т.к. владелец jar-файла тот же пользователь, он может перезаписать сам jar-файл, который одновременно является shell-скриптом. И при старте операционной системы этот скрипт запустится с правами root. Это может быть критично, т.к. если в java-приложении есть уязвимость, в худшем случае взломщик должен остаться с правами приложения, а здесь появляется возможность повышения привилегий.

    Я написал в багтрекер, но разработчик предлагает просто делать файл немодифицируемым через «chattr +i» и описать это в документации.

    Как вы думаете, насколько эта уязвимость серьезная? Что стоит сделать, как правильно поступать?
    Как мне кажется, надо init.d скрипт держать отдельно от jar и в другом каталоге, доступном только root.

    Скрипт на github.

    А ещё, launch-скрипт загружает .conf файл, лежащий в том же каталоге где и jar, через «source», интерпретируя его через bash:

    [[ -r "${jarfolder}/${configfile}" ]] && source "${jarfolder}/${configfile}"
    

    То есть там можно писать полноценный скриптовый код, который также будет исполняться с правами root при запуске сервиса через init.d.
    Получается, чтобы обеспечить защиту, надо будет обязательно создавать conf-файл, даже если он не требуется, и запрещать его модификацию через «chattr +i».
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 12
    • 0
      Мне кажется, что проще использовать возможности binfmt и запускать jar-ы как обычные исполняемые файлы.
      • +1
        Вспомнилось, как сломав pam использовали «уязвимость» во внутреннем сервисе (доступ был только через vpn), который умел «читать» конфиги на jruby и был запущен с правами рута.
        • НЛО прилетело и опубликовало эту надпись здесь
          • +2
            Откуда? В <some-service>.service пишите:
            [Unit]
            Description=Some java service
            
            [Service]
            StartExec=/usr/bin/java -jar some-service.jar --param1 val1 ....
            User=some-user
            
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                в скриптах в init.d можно через start-stop-daemon указывать под кем запускаться.
                • 0
                  Да, когда он есть. Но в дистрибутивах с systemd полностью отпала необходимость этого геморроя, к счастью.
                  • НЛО прилетело и опубликовало эту надпись здесь
                  • +1
                    Да, это вариант, но не всем нравится systemd.
              • +1
                А добавить su -c в init.d script можно?
                • 0
                  Да, там это уже сделано. Проблема в том, что владелец скрипта (скрипт это и есть jar-файл) пользователь, а скрипт запускается с привилегиями root.

                        start-stop-daemon --start --quiet \
                          --chuid "$run_user" \
                  

                  А run_user определяется по владельцу jar-файла:

                  [[ $(id -u) == "0" ]] && run_user=$(ls -ld "$jarfile" | awk '{print $3}')
                  
                • 0
                  Не очень понятно — почему у этого файла владелец пользователь, а не root? Сделайте владельцем root-а, пользователю дайте права на чтение и всё.

                  PS всё, понял. Да, странное решение. Пользователь, под которым запускается файл, наверное должен прописываться где-то отдельно, а не выводиться из владельца файла.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.