Студенты обошли проверку кода в школе, вызвав execve без имени

Calling a function in C without naming it

В школе с автоматической проверкой кода студенты нашли способ выполнить произвольный код, обойдя запрет на использование неразрешённых функций. Они вычислили смещение между printf и mmap, создали исполняемую страницу памяти и вызвали системный вызов execve, не упоминая его имени. Это позволило получить доступ к shell и продемонстрировало уязвимость системы, основанной на анализе AST и ASan.

Мы можем просто сделать плохую процедуру на ассемблере x86, которая позволит нам совершать системные вызовы Linux так, как будто это функция C.
  1. ashdnazg

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

    Однажды, когда автоматические тесты завалили моё решение, я просто использовал `system`, чтобы сдампить тестовый ввод в свою домашнюю директорию. Однако я забыл настроить права доступа, так что на самом деле не смог к нему получить доступ! Ещё пара повторных отправок с дополнительными chmod, каждый раз ломая что-то другое, и мне удалось воспроизвести свой баг, исправить его, отправить заново и подчистить все (или почти все) улики.

  2. Kevin_Flynn

    Поскольку мы знаем, что наш код компилируется с ASan, мы решили утечь смещение между printf — функцией, которая всегда разрешена, — и mmap — функцией, дающей нам выполнение произвольного ассемблерного кода. Так мы можем обойти школьные проверки и вызвать любой системный вызов, в нашем случае execve, чтобы получить доступ к шеллу.

    Мы не стали копать глубже и просто сообщили школе о возможной проблеме.

    Я не вижу тривиального способа это пропатчить.

    Похоже, изъян в системе сдачи работ.

    Система сдачи могла бы собирать/перелинковывать ваш код с библиотекой-трамплином, в которой тело каждой запрещённой функции заменено на вывод ошибки и аварийное завершение. В вашем примере она бы перехватила:

    char *code =

    notmmap.fn(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,

    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

    и не дала бы вам использовать флаг PROT_EXEC на этапе выполнения проверки сданного решения.

    Согласно ИИ, в linux: «... seccomp-BPF фильтр, применяемый к каждому процессу перед запуском программы. Он может проверять аргумент prot у mmap и возвращать EPERM, когда установлен PROT_EXEC».

    Кроме того, в linux: «systemd предлагает MemoryDenyWriteExecute=yes для сервисов. Это менее строго, чем запрет всех исполняемых отображений: он нацелен на записываемые+исполняемые отображения и связанные способы сделать память исполняемой».

    ( ЕСЛИ ... я правильно прочитал статью )

    ps. Отправьте предложенные решения заведующему кафедрой или другому начальству, которое может кинуть вам какую-нибудь косточку, чтобы ваша ста […]

  3. PeterWhittaker

    Похоже, школе нужно обернуть всё в denylist для seccomp. Возможно, нетривиально, но потенциально интересно.

Ещё за этот день

2026-10-08