Hacking with Curl!

Published: 25 Nov 2024

If you want to take your web skills to the next level, one tool you really need to master is curl. In this article, we will cover a few tricks to help you get there.

Why curl?

Compared to many web hacking tools or proxies, curl is far more reliable. It allows you to easily automate tasks or double-check results. Additionally, you can export network requests as curl commands in Chrome (via "Developer Tools" → "Network" → Right-click on the request → "Copy as cURL"), making it the perfect companion for manual testing.

Debugging your curl command

One key trick not many people use is debugging your payload. You can do this using netcat. In one terminal, start nc -l 1234, and in another terminal, run your curl command, pointing it to the netcat listener: curl http://127.0.0.1:1234. This will show exactly what curl sent:

$ nc -l 1234     
GET / HTTP/1.1
Host: 127.0.0.1:1234
User-Agent: curl/8.6.0
Accept: */*

A simple trick that can often make the difference between success and failure

Another way to debug your curl commands is to use --trace-ascii -:

$ curl http://pentesterlab.com/ --trace-ascii -
== Info: Host pentesterlab.com:80 was resolved.
== Info: IPv6: (none)
== Info: IPv4: 54.87.134.91
== Info:   Trying 54.87.134.91:80...
== Info: Connected to pentesterlab.com (54.87.134.91) port 80
=> Send header, 79 bytes (0x4f)
0000: GET / HTTP/1.1
0010: Host: pentesterlab.com
0028: User-Agent: curl/8.6.0
0040: Accept: */*

Personally, I prefer the netcat option, but it's always good to know multiple ways to do the same thing.

Properly test for directory traversal with --path-as-is

Many people miss directory traversal vulnerabilities in URLs because most HTTP clients (including your browser) canonicalize paths before accessing a URL. Using our previous trick, let’s better understand this behavior. Start a netcat listener (nc -l 1234) and use curl to access this URL: http://127.0.0.1:1234/../../../../../etc/passwd. Here’s what we see in the listener shell:

$ nc -l 1234
GET /etc/passwd HTTP/1.1
Host: 127.0.0.1:1234
User-Agent: curl/8.6.0
Accept: */*

Our directory traversal payload disappeared, it gets normalized by curl. Browsers behave similarly. This is where --path-as-is comes in handy. Running curl http://127.0.0.1:1234/../../../../../etc/passwd --path-as-is with the same listener gives:

$ nc -l 1234
GET /../../../../../etc/passwd HTTP/1.1
Host: 127.0.0.1:1234
User-Agent: curl/8.6.0
Accept: */*

This time, curl sends exactly what we intended.

Stop messing with your hosts file using --resolve

Sometimes, you need to force DNS resolution to access an application (e.g., in one of our Recon Badge labs). Instead of modifying your hosts file (/etc/hosts on Unix, C:\Windows\System32\drivers\etc\hosts on Windows), use curl’s --resolve. For example, to send a request to pentesterlab.com but resolve it to localhost, start a netcat listener on port 80 (using sudo or root) and run: curl --resolve pentesterlab.com:80:127.0.0.1 http://pentesterlab.com. The listener output will be:

$ sudo nc -l 80  
GET / HTTP/1.1
Host: pentesterlab.com
User-Agent: curl/8.6.0
Accept: */*

Test for Directory Traversal in File Upload

You can use the -F option to upload files and test for directory traversal. For example, run:

curl -F "file=@pentesterlab.jsp;filename=../../../../../../../../hacker.jsp" http://127.0.0.1:1234/

Using netcat as a listener, you can confirm the payload:

$ nc -l 1234 
POST / HTTP/1.1
Host: 127.0.0.1:1234
User-Agent: curl/8.6.0
Accept: */*
Content-Length: 254
Content-Type: multipart/form-data; boundary=------------------------3PT5oqFUWiDeX4RxFham3k

--------------------------3PT5oqFUWiDeX4RxFham3k
Content-Disposition: form-data; name="file"; filename="../../../../../../../../hacker.jsp"
Content-Type: application/octet-stream

HACK THE PLANET

--------------------------3PT5oqFUWiDeX4RxFham3k--

We uploaded the local file pentesterlab.jsp (containing HACK THE PLANET) and tested for directory traversal attacks with ;filename=../../../../../../../../hacker.jsp. Nifty!

Saving your favorite arguments with .curlrc

Some curl arguments, like --silent, --path-as-is, or --cacert, are so useful you may want them enabled by default. You can add make curl automatically use these arguments by adding them to your .curlrc file in your home directory:

$ echo --path-as-is >> ~/.curlrc
$ curl http://127.0.0.1:1234/../../../../../etc/passwd

We can verify that this works with netcat:

$ nc -l 1234
GET /../../../../../etc/passwd HTTP/1.1
Host: 127.0.0.1:1234
User-Agent: curl/8.6.0
Accept: */*

You no longer need to remember and manually type all your favorite curl arguments.

Conclusion

Mastering curl is an essential skill for anyone looking to enhance their web expertise, whether for debugging, security testing, or automation.

As you incorporate these techniques into your toolkit, you’ll find that curl is more than just a command-line utility—it’s a fundamental part of understanding and interacting with the web. The simplicity and power of curl make it indispensable, and with continued practice, you’ll be able to use it to solve even the most complex challenges.

If you enjoy these kinds of tricks, don't miss our HTTP Badge. It's packed with lessons to deepen your understanding of HTTP and master the use of curl!

So, whether you're testing for vulnerabilities, automating requests, or troubleshooting issues, let curl be your go-to tool. Mastering it will not only elevate your technical expertise but also open new doors in web development and security testing. Happy hacking with Curl!

Photo of Louis Nyffenegger
Written by Louis Nyffenegger
Founder and CEO @PentesterLab