Переменные окружения


Основы Linux

Интерфейс командной строки Linux — это, по сути, полноценный язык программирования, на котором можно писать настоящие программы!

Поскольку интерфейс командной строки принято называть «оболочкой» (shell), программы, написанные на этом языке, называются «сценариями оболочки» (shell scripts). Работая в командной строке, Вы фактически создаёте сценарий оболочки — строка за строкой! Как и большинство языков программирования, оболочка поддерживает переменные.

Этот модуль познакомит Вас с тем, как задавать переменные, выводить их содержимое и использовать в работе!

Начнём с вывода переменных на экран.

Программа /challenge/run не может и не должна выдавать Вам флаг напрямую — это нормально, ведь флаг уже помещён в переменную с именем FLAG! Вам остаётся лишь вывести переменную FLAG на экран. Сделать это можно несколькими способами, но начнём с команды echo. Команда echo просто выводит то, что ей передано.

Например:

hacker@var:~$ echo Hello Hackers!
Hello Hackers!

С помощью echo можно также выводить переменные — для этого перед именем переменной ставится символ $. Например, переменная PWD всегда хранит путь к текущему рабочему каталогу текущей оболочки. Вывести её содержимое можно следующим образом:

hacker@var:~$ echo $PWD
/home/hacker

Теперь Ваша очередь. Выведите переменную FLAG с помощью оболочки и решите это задание!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

Разумеется, помимо чтения значений из переменных, Вы можете и записывать в них значения.

Делается это, как и во многих других языках программирования, с помощью знака =. Чтобы присвоить переменной VAR значение hacker, следует написать:

hacker@var:~$ VAR=hacker

ВАЖНО:
пробелы вокруг = недопустимы! Если добавить пробелы (например, VAR = hacker), оболочка не распознает присваивание переменной и попытается выполнить команду VAR (которой не существует).

Также обратите внимание, что здесь используется VAR, а не $VAR: символ $ добавляется только при обращении к переменной (для получения ее значения). В терминологии оболочки добавление $ перед именем переменной называется раскрытием переменной (variable expansion) и, как ни удивительно, является источником многих потенциальных уязвимостей (мы познакомим Вас с этой темой в продвинутом курсе позднее).

После того как Вы установили переменную, к ней можно обращаться с помощью уже изученных способов, например:

hacker@var:~$ echo $VAR
hacker

Для решения этого задания необходимо присвоить переменной CTF значение SCHOOL. Будьте внимательны: имена и значения переменных чувствительны к регистру! CTF — это не то же самое, что ctf, а SCHOOL — не то же самое, что school.

ВАЖНО:
Переменные среды не очищаются самостоятельно, требуется перезагрузка или принудительное удаление переменной из окружения командой unset <ИМЯ_ПЕРЕМЕННОЙ>.

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

На этом уровне Вы познакомитесь с экранированием (кавычками).

В оболочке пробелы имеют особое значение, и их нельзя использовать произвольным образом в ряде контекстов. Вспомним присваивание переменной:

hacker@var:~$ VAR=hacker

Это присваивает переменной VAR значение hacker, но что, если Вы хотите задать значение "Hello hacker!" ? Можно попробовать следующее:

hacker@var:~$ VAR=Hello hacker!

Выглядит разумно, однако работать не будет — по той же причине, по которой пробелы вокруг = недопустимы. Увидев пробел, оболочка завершает обработку присваивания и интерпретирует следующее слово (hacker! в данном случае) как команду.

Чтобы присвоить VAR значение Hello hacker!, необходимо заключить его в кавычки:

hacker@var:~$ VAR="Hello hacker!"

В этом случае оболочка воспринимает Hello hacker! как единый токен и спокойно присваивает его переменной VAR. На этом уровне


Для решения задания Вам потребуется установить переменную VAR в значение CTF SCHOOL. Удачи!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

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

hacker@var:~$ VAR=hacker
hacker@var:~$ echo "VAR is: $VAR"
VAR is: hacker
hacker@var:~$ sh
$ echo "VAR is: $VAR"
VAR is: 

В приведённом выводе приглашение $ — это приглашение оболочки sh, минималистичной реализации оболочки, запущенной как дочерний процесс основной оболочки. И она не получает переменную VAR!

Это вполне логично. Переменные Вашей оболочки могут содержать чувствительные или нестандартные данные, и Вы наверняка не хотите, чтобы они утекали в запускаемые Вами программы без явного на то указания. Как же явно разрешить передачу переменной?

Переменную нужно экспортировать. Когда Вы экспортируете переменную, она передаётся в переменные окружения дочерних процессов. С концепцией переменных окружения Вы встретитесь и в других заданиях, но её эффект уже проявится здесь. Вот пример:

hacker@var:~$ VAR=hacker
hacker@var:~$ export VAR
hacker@var:~$ sh
$ echo "VAR is: $VAR"
VAR is: hacker

Здесь дочерняя оболочка получила значение VAR и смогла его вывести! Первые две строки можно также объединить в одну:

hacker@var:~$ export VAR=hacker
hacker@var:~$ sh
$ echo "VAR is: $VAR"
VAR is: hacker

В этом задании Вам необходимо настроить окружение так, чтобы переменная SCHOOL была НЕ экспортирована и содержала значение CTF, а переменная CTF была установлена в значение SCHOOL и экспортирована. Удачи!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

Существует несколько способов получить доступ к переменным в bash. echo — лишь один из них, и в этом задании Вы освоите как минимум ещё один.

Попробуйте команду env: она выводит все экспортированные переменные, установленные в Вашей оболочке, и среди этого вывода Вы сможете найти переменную FLAG!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

В процессе работы с оболочкой Вам нередко потребуется сохранять вывод какой-либо команды в переменную. К счастью, оболочка делает это весьма удобным с помощью механизма, который называется Подстановка команд (Command Substitution)!

Например:

hacker@var:~$ FLAG=$(cat /flag)
hacker@var:~$ echo "$FLAG"
ctf.school{blah_blah_blah}
hacker@var:~$

ПОДСКАЗКА:
Вместо $() можно использовать обратные кавычки: FLAG=`cat /flag` вместо FLAG=$(cat /flag) из примера выше.

Это более старый синтаксис, у которого есть ряд недостатков (например, представьте, что Вам нужно вложить подстановки команд друг в друга. Как бы Вы записали $(cat $(find / -name flag)) с помощью обратных кавычек?

РЕКОМЕНДАЦИЯ АВТОРА:
Используйте $(blah) вместо `blah`.


Теперь Ваша очередь потренироваться. Считайте вывод команды /challenge/run непосредственно в переменную CTF — и она будет содержать флаг!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

Начнём с чтения пользовательского ввода (Вашего). Для этого используется встроенная команда read — она считывает ввод в переменную!

Ниже приведён пример с аргументом -p, который позволяет задать приглашение (без него было бы сложно отличить ввод от вывода в примере):

hacker@var:~$ read -p "ВВОД: " MY_VARIABLE
ВВОД: Привет!
hacker@var:~$ echo "Вы ввели: $MY_VARIABLE"
Вы ввели: Привет!

Помните, что read считывает данные из стандартного потока ввода! Первое Привет! в примере выше было введено пользователем, а не выведено программой. Попробуем обозначить это явно. Ниже каждая строка помечена как ВВОД (от пользователя) или ВЫВОД (на экран):

 ВВОД: hacker@var:~$ echo $MY_VARIABLE
ВЫВОД:
 ВВОД: hacker@var:~$ read MY_VARIABLE
 ВВОД: Привет!
 ВВОД: hacker@var:~$ echo "Вы ввели: $MY_VARIABLE"
ВЫВОД: Вы ввели: Привет!

В этом задании Вам нужно использовать read, чтобы присвоить переменной CTF значение SCHOOL.

Удачи!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college

Когда пользователи оболочки хотят прочитать файл в переменную окружения, они нередко делают это примерно так:

hacker@var:~$ echo "test" > some_file
hacker@var:~$ VAR=$(cat some_file)
hacker@var:~$ echo $VAR
test

Это работает, но среди профессионалов подобный приём принято называть «бесполезным использованием cat». Иными словами, запускать ради чтения файла целый отдельный процесс — расточительство. С задачей может справится и сама оболочка.

Ранее Вы читали пользовательский ввод в переменную с помощью read. Кроме того, Вы уже умеете перенаправлять файлы в стандартный поток ввода команд. Объедините эти два приёма — и Вы сможете читать файлы средствами самой оболочки.

hacker@var:~$ echo "test" > some_file
hacker@var:~$ read VAR < some_file
hacker@var:~$ echo $VAR
test

Разберем по шагам read VAR < some_file:

  1. some_file перенаправляется в стандартный поток ввода команды read.
  2. read считывает данные в из потока ввода и записывает в переменную VAR.

В задании используйте этот приём, чтобы прочитать /challenge/read_me в переменную окружения CTF — и Вы получите флаг.

Содержимое /challenge/read_me будет постоянно меняться, поэтому считать его в переменную CTF необходимо одной командой!

Connect with SSH

Link your SSH key, then connect with: ssh hacker@dojo.pwn.college