How to make http request without curl or wget in bash

Photo by Gabriel Heinzer on UnsplashBash has a hidden capability to make HTTP requests without needing tools like curl or wget. Let’s explore how this works.First, let’s check the bash man page:man bashIn the REDIRECTION section, you’ll find an interes…


This content originally appeared on Level Up Coding - Medium and was authored by Piotr Zarycki

Photo by Gabriel Heinzer on Unsplash

Bash has a hidden capability to make HTTP requests without needing tools like curl or wget. Let’s explore how this works.

First, let’s check the bash man page:

man bash

In the REDIRECTION section, you’ll find an interesting detail:

Bash handles several filenames specially when they are used in redirections. 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.

  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.

If you try to list the /dev/tcp directory, you’ll get the following error:

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

This is because /dev/tcp is not an actual path on the filesystem; it’s a feature of Bash itself, not the underlying Linux system.

To use this feature, you need to call it as part of the Bash execution environment using the exec command:

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

We’ll discuss the 3<> syntax later. After running this command, it may seem like nothing happens, but there’s more going on behind the scenes.

Let’s use strace to investigate further. Among the output, the most interesting part is:

.......
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

This confirms that the exec command created a TCP/IP socket bound to example.org.

In Linux, everything is treated as a file, including network connections, which are represented as “files” called file descriptors. You can list all file descriptors for the current process by checking the /proc/self/fd/ directory:

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

Here, 3 is the file descriptor for the socket connected to example.org. The exec 3<> /dev/tcp/... syntax essentially means:

"create a socket for input and output operations with file descriptor with process identifier equals 3."

Next, let’s send a GET request:

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

Although it may appear that nothing happens, you’ve just sent data through the socket.

To read the response, use:

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............

You’ve successfully downloaded a webpage! Afterward, remember to close the socket:

exec 3<&- 

You might wonder why this feature exists.

Originally, it was copied from the KornShell (ksh) to open network connections and assign them to file descriptors

It was intended to send data across networks, such as for generating reports.

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


The audit file must be writable by all users whose activities are audited,
presenting an obvious security problem. However, the Korn shell supports
networking using the `/dev/udp/`*host*`/`*port* or `/dev/tcp/`*host*`/`*port*
syntax, so audit records can be sent across a network to another system.

This feature can also be exploited to create reverse shells by hackers or penetration testers.


How to make http request without curl or wget in bash was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Piotr Zarycki


Print Share Comment Cite Upload Translate Updates
APA

Piotr Zarycki | Sciencx (2024-08-27T11:22:18+00:00) How to make http request without curl or wget in bash. Retrieved from https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/

MLA
" » How to make http request without curl or wget in bash." Piotr Zarycki | Sciencx - Tuesday August 27, 2024, https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/
HARVARD
Piotr Zarycki | Sciencx Tuesday August 27, 2024 » How to make http request without curl or wget in bash., viewed ,<https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/>
VANCOUVER
Piotr Zarycki | Sciencx - » How to make http request without curl or wget in bash. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/
CHICAGO
" » How to make http request without curl or wget in bash." Piotr Zarycki | Sciencx - Accessed . https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/
IEEE
" » How to make http request without curl or wget in bash." Piotr Zarycki | Sciencx [Online]. Available: https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/. [Accessed: ]
rf:citation
» How to make http request without curl or wget in bash | Piotr Zarycki | Sciencx | https://www.scien.cx/2024/08/27/how-to-make-http-request-without-curl-or-wget-in-bash-2/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.