kgretzky / pwndrop

Self-deployable file hosting service for red teamers, allowing to easily upload and share payloads over HTTP and WebDAV.
https://breakdev.org/pwndrop
GNU General Public License v3.0
2.02k stars 259 forks source link

Feature request: Curl/scp #2

Open asiudoisjdfo opened 4 years ago

asiudoisjdfo commented 4 years ago

Fantastic work!

Suggestion: Enable optional curl/scp upload/download (along with a complete curl/scp command for ease of use). That would enable better/easier use from commandline.

Thanks again! :)

kgretzky commented 4 years ago

Hey! Can you post some example of how this feature would work for me to better understand the request?

1bk commented 4 years ago

First off, awesome work!

Thinking it would be a cool feature if you could upload files from other machines using the CLI with simple commands, e.g.:

jmhickman commented 4 years ago

I second(third) this. I would love to be able to use this for exfiltration as well. For example, I have an agent running on a host, and using a Powershell one-liner or cURL, I can upload over HTTP and/or webDAV. Perhaps it should use a lower privilege or one-time use key, so that the admin cookie value isn't disclosed.

WhyNotPal commented 3 years ago

Same here :-) such a CLI system to upload and configure(facade,Mime Type) the files would be really great. Thanks for sharing pwndrop with the world anyway :-)

hulto commented 1 year ago

I needed a way to upload files programmatically here's the solution I wrote

#!/usr/bin/env python3
import argparse
import requests
from requests.compat import urljoin
import sys

def build_url(domain: str, path: str) -> str:
    base = domain
    if "http://" not in domain and "https://" not in domain:
        base = f"https://{domain}/"
    return urljoin(base, path)

# Get the secret session cookie to show that we accesssed the secret path.
# We'll connect using our requests session which should set the cookies.
def get_session_cookie(url: str, secret_path: str, s) -> bool:
    new_url = build_url(url, secret_path)
    response = s.get(new_url, verify=False)
    return response.status_code == 200

# Get a token for authenticating with username and password
def get_auth_token(url: str, username: str, password: str, s) -> str:
    new_url = build_url(url, "/api/v1/login")
    response = s.post(new_url, json={"username":username,"password":password})
    return response.json()['data']['token']

# Upload the file.
def upload_file(url: str, file_path: str) -> bool:
    new_url = build_url(url, "/api/v1/files")
    response = s.post(new_url, files={'file': open(file_path,'rb')})
    return response.status_code == 200

if __name__ == '__main__':
    requests.packages.urllib3.disable_warnings() 
    parser = argparse.ArgumentParser(description='Upload a file to pwndrop')
    parser.add_argument('domain')
    parser.add_argument('secret_path')
    parser.add_argument('username')
    parser.add_argument('password')
    parser.add_argument('file')

    args = parser.parse_args()

    with requests.Session() as s:
        url = build_url(args.domain,'/')
        if get_session_cookie(url, args.secret_path, s) == False: print("Error getting session cookie"); sys.exit(-1)
        if len(s.cookies.keys()) != 1: print(f"Expected exactly one cookiebut found {len(s.cookies.keys())}"); sys.exit(-1)
        auth_token = get_auth_token(url, args.username, args.password, s)
        if len(auth_token) != 64: print("Error logging in"); sys.exit(-1)
        if upload_file(url, args.file) == False: print("Error failed to upload file"); sys.exit(-1)
        print(f"Uploaded {args.file}")