DevGang
Авторизоваться

Как сделать http-запрос без использования curl или wget в bash

Bash, известный своей мощью, обладает скрытой функцией, позволяющей выполнять HTTP-запросы без дополнительных инструментов, таких как curl или wget. Давайте разберемся, как это работает.

Заглянем в документацию Bash, используя команду man bash. В разделе о перенаправлении мы найдем интересное уточнение: Bash способен взаимодействовать со специальными файлами, доступными в операционной системе, или эмулировать их поведение, если такие файлы отсутствуют.  

Следуя этому описанию, мы откроем для себя способ выполнения HTTP-запросов непосредственно из Bash.

  Bash handles several filenames specially when they are used in redirections, as described in the following table.  If the operating system on which bash is  running  provides  these
       special files, bash will use them; otherwise it will emulate them internally with the behavior described below.

              /dev/fd/fd
                     If fd is a valid integer, file descriptor fd is duplicated.
              /dev/stdin
                     File descriptor 0 is duplicated.
              /dev/stdout
                     File descriptor 1 is duplicated.
              /dev/stderr
                     File descriptor 2 is duplicated.
              /dev/tcp/host/port
                     If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open the corresponding TCP socket.
              /dev/udp/host/port
                     If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open the corresponding UDP socket.

Попытка получить список директорий /dev/tcp приводит к следующей ошибке:

ls -lat /dev/tcp
/dev/tcp: No such file or directory (os error 2).

Причина ошибки кроется в том, что /dev/tcp – это не физический каталог в файловой системе. На самом деле, это функциональность, встроенная в Bash, а не в базовую операционную систему Linux. 

Чтобы воспользоваться этой возможностью, необходимо запустить ее в контексте выполнения Bash, используя команду exec.

exec 3<>/dev/tcp/example.org/80 

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

Для более глубокого изучения воспользуемся инструментом strace. В его выводе нас заинтересует следующий фрагмент:

.......
close(3)                                = 0
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("93.184.215.14")}, 16) = 0

Это подтверждает, что команда exec создала TCP/IP-сокет, подключенный к example.org.

В Linux все объекты, включая сетевые соединения, представлены в виде «файлов», называемых файловыми дескрипторами. Список всех файловых дескрипторов для текущего процесса можно найти в каталоге /proc/self/fd/.

ls -lat /proc/self/fd/

lrwx------ 1 piotr piotr 64 Aug 25 15:01 0 -> /dev/pts/0
lrwx------ 1 piotr piotr 64 Aug 25 15:01 1 -> /dev/pts/1
lrwx------ 1 piotr piotr 64 Aug 25 15:01 2 -> /dev/pts/2
lrwx------ 1 piotr piotr 64 Aug 25 15:01 3 -> 'socket:[2910856]'
lr-x------ 1 piotr piotr 64 Aug 25 15:01 4 -> /proc/1579316/fd

В этом списке 3 – это файловый дескриптор для сокета, подключенного к example.org. Синтаксис exec 3<> /dev/tcp/... можно перефразировать так:

"Создать сокет для операций ввода/вывода с файловым дескриптором, имеющим идентификатор 3."

Далее отправим GET-запрос:

echo -ne "GET / HTTP/1.1\r\nHost: example.org\r\n\r\n" >&3

Хотя может показаться, что ничего не происходит, вы только что отправили данные через сокет.

Чтобы прочитать ответ, используйте:

cat <&3  

HTTP/1.1 200 OK
Age: 243157
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Sun, 25 Aug 2024 14:15:54 GMT
Etag: "3147526947+ident"
Expires: Sun, 01 Sep 2024 14:15:54 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECAcc (dcd/7D77)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1256

<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
......................REST............

Вы успешно загрузили веб-страницу! После этого не забудьте закрыть сокет:

exec 3<&- 

Возможно, вас заинтересовало, зачем нужна эта функция. 

Изначально она была скопирована из KornShell (ksh) для открытия сетевых соединений и присвоения им файловых дескрипторов. 

Предполагалось использовать ее для передачи данных по сети, например, при создании отчетов. 

https://github.com/ksh93/ksh/blob/fa0ee84029e0cd203d698151a0459413678ab095/src/cmd/ksh93/README-AUDIT.md?plain=1#L158

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

#Bash
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу