I am trying to setup a App in python and wsgi to get some payload from cloud to on-prem and send email eventually. My Setup includes WSGI & NGINX but for testing purpose I am forming a payload locally using curl
My Code
I am using a code from existing stackoverflow and trying to modify it as per my need eventually. Currently facing problem with JSON data capture
from wsgiref.simple_server import make_server
import cgi
import subprocess
from email.message import EmailMessage
import json
def sendEmail(from_addr, to_addrs, msg_subject, msg_body):
msg = EmailMessage()
msg.set_content(msg_body)
msg['From'] = from_addr
msg['To'] = to_addrs
msg['Subject'] = msg_subject
sendmail_location = "/usr/sbin/sendmail"
subprocess.run([sendmail_location, "-t", "-oi"], input=msg.as_bytes())
def is_post_request(environ):
if environ['REQUEST_METHOD'].upper() != 'POST':
return False
content_type = environ.get('CONTENT_TYPE', 'application/x-www-form-urlencoded')
print("I am printing here " + content_type)
return (content_type.startswith('application/x-www-form-urlencoded' or content_type.startswith('multipart/form-data' or content_type.startswith('application/json'))))
def get_post_form(environ):
print ("Printing environ" + str(environ))
assert is_post_request(environ)
input = environ['wsgi.input']
post_form = environ.get('wsgi.post_form')
if (post_form is not None
and post_form[0] is input):
return post_form[2]
# This must be done to avoid a bug in cgi.FieldStorage
environ.setdefault('QUERY_STRING', '')
fs = cgi.FieldStorage(fp=input,
environ=environ,
keep_blank_values=1)
new_input = InputProcessed()
post_form = (new_input, input, fs)
environ['wsgi.post_form'] = post_form
environ['wsgi.input'] = new_input
return fs
class InputProcessed(object):
def read(self, *args):
raise EOFError('The wsgi.input stream has already been consumed')
readline = readlines = __iter__ = read
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
user = get_post_form(environ).getvalue('user')
password = get_post_form(environ).getvalue('password')
output = 'user is: '+user+' and password is: '+password
return [output.encode()]
For now I am just trying to grab userName and Password from a local payload. I am sending the payload like below for testing purpose only
curl --header "Content-Type: application/json" --request POST --data '{"user":"abc","password":"xyz"}' http://localhost:8580
My final payload will have a {"method": "email"} which will call the sendmail function
My WSGI app is listening
ps -ef | grep wsgi
nginx 375580 1 0 09:16 ? 00:00:00 uwsgi --ini AutoApp.ini
nginx 375581 375580 0 09:16 ? 00:00:00 uwsgi --ini AutoApp.ini
nginx 375582 375580 0 09:16 ? 00:00:00 uwsgi --ini AutoApp.ini
nginx 375583 375580 0 09:16 ? 00:00:00 uwsgi --ini AutoApp.ini
nginx 375584 375580 0 09:16 ? 00:00:00 uwsgi --ini AutoApp.ini
nginx 375585 375580 0 09:16 ? 00:00:00 uwsgi --ini AutoApp.ini
root 379392 378312 0 10:00 pts/3 00:00:00 grep --color=auto wsgi
I am currently getting the below error:
$ curl --header "Content-Type: application/json" --request POST --data '{"user":"abc","password":"xyz"}' http://localhost:8580
Printing environ{'QUERY_STRING': '', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/json', 'CONTENT_LENGTH': '31', 'REQUEST_URI': '/', 'PATH_INFO': '/', 'DOCUMENT_ROOT': '/usr/share/nginx/html', 'SERVER_PROTOCOL': 'HTTP/1.1', 'REQUEST_SCHEME': 'http', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': '43534', 'SERVER_PORT': '8580', 'SERVER_NAME': 'p0001.emea.net', 'HTTP_HOST': 'localhost:8580', 'HTTP_USER_AGENT': 'curl/7.61.1', 'HTTP_ACCEPT': '*/*', 'HTTP_CONTENT_TYPE': 'application/json', 'HTTP_CONTENT_LENGTH': '31', 'wsgi.input': <uwsgi._Input object at 0x7f34812cfb28>, 'wsgi.file_wrapper': <built-in function uwsgi_sendfile>, 'wsgi.version': (1, 0), 'wsgi.errors': <_io.TextIOWrapper name=2 mode='w' encoding='UTF-8'>, 'wsgi.run_once': False, 'wsgi.multithread': False, 'wsgi.multiprocess': True, 'wsgi.url_scheme': 'http', 'uwsgi.version': b'2.0.26', 'uwsgi.node': b'p0001.emea.net'}
I am printing here application/json
Traceback (most recent call last):
File "./wsgi.py", line 61, in application
user = get_post_form(environ).getvalue('user')
File "./wsgi.py", line 36, in get_post_form
assert is_post_request(environ)
AssertionError
[pid: 379691|app: 0|req: 1/1] 127.0.0.1 () {36 vars in 463 bytes} [Wed Jul 10 10:04:26 2024] POST / => generated 0 bytes in 1 msecs (HTTP/1.1 200) 1 headers in 44 bytes (0 switches on core 0)
Little guidance will be much appreciated here
Your last line of the function is_post_request()
is wrong.
Your code is:
return (content_type.startswith('application/x-www-form-urlencoded' or content_type.startswith('multipart/form-data' or content_type.startswith('application/json'))))
I think it should be:
return (content_type.startswith('application/x-www-form-urlencoded') or content_type.startswith('multipart/form-data') or content_type.startswith('application/json'))
or in a pretty look:
return (
content_type.startswith('application/x-www-form-urlencoded') or
content_type.startswith('multipart/form-data') or
content_type.startswith('application/json')
)