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

    利用CodeQL分析并挖掘Log4j漏洞

    VSole2021-12-24 15:11:14

    前言

    分析漏洞的本質是為了能讓我們從中學習漏洞挖掘者的思路以及挖掘到新的漏洞,而CodeQL就是一款可以將我們對漏洞的理解快速轉化為可實現的規則并挖掘漏洞的利器。根據網上的傳言Log4j2的RCE漏洞就是作者通過CodeQL挖掘出的。雖然如何挖掘的我們不得而知,但我們現在站在事后的角度再去想想,可以推測一下作者如何通過CodeQL挖掘到漏洞的,并嘗試基于作者的思路挖掘新漏洞。

    分析過程

    首先我們要構建Log4j的數據庫,由于lgtm.com中構建的是新版本的Log4j數據庫,所以只能手動構建數據庫了。首先從github獲取源碼并切換到2.14.1版本。

    git clone https://github.com/apache/logging-log4j2.git
    git checkout be881e5
    

    由于我們這次分析的主要是log4j-corelog4j-api中的內容,所以打開根目錄的Pom.xml注釋下面的內容。

        log4j-api-java9
        log4j-api
        log4j-core-java9
        log4j-core
        
      
    

    由于log4j-api-java9log4j-core- java9需要依賴JDK9,所以要先下載JDK9并且在C:\Users\用戶名\.m2\toolchains.xml中加上下面的內容。

      
      jdk  
        
        9  
        sun  
        
        
        C:\Program Files\Java\jdk-9.0.4  
        
      
    
    

    通過下面的命令完成數據庫構建

    CodeQL database create Log4jDB --language=java --overwrite --command="mvn clean install -Dmaven.test.skip=true"
    

    構建好數據庫后,我們要找JNDI注入的漏洞,首先要確定在這套系統中調用了InitialContext#lookup方法。在LookupInterface項目中已經集成了常見的發起JNDI請求的類,只要稍微改一下即可。

    首先定義Context類型,這個類中綜合了可能發起JNDI請求的類。

    class Context extends  RefType{
        Context(){
            this.hasQualifiedName("javax.naming", "Context")
            or
            this.hasQualifiedName("javax.naming", "InitialContext")
            or
            this.hasQualifiedName("org.springframework.jndi", "JndiCallback")
            or 
            this.hasQualifiedName("org.springframework.jndi", "JndiTemplate")
            or
            this.hasQualifiedName("org.springframework.jndi", "JndiLocatorDelegate")
            or
            this.hasQualifiedName("org.apache.shiro.jndi", "JndiCallback")
            or
            this.getQualifiedName().matches("%JndiCallback")
            or
            this.getQualifiedName().matches("%JndiLocatorDelegate")
            or
            this.getQualifiedName().matches("%JndiTemplate")
        }
    }
    

    下面尋找那里調用了Context的lookup方法。

    from Call call,Callable parseExpression
    where
        call.getCallee() = parseExpression and 
        parseExpression.getDeclaringType() instanceof Context and
        parseExpression.hasName("lookup")
    select call
    

    • DataSourceConnectionSource#createConnectionSource
    @PluginFactory
        public static DataSourceConnectionSource createConnectionSource(@PluginAttribute("jndiName") final String jndiName) {
            if (Strings.isEmpty(jndiName)) {
                LOGGER.error("No JNDI name provided.");
                return null;
            }
            try {
                final InitialContext context = new InitialContext();
                final DataSource dataSource = (DataSource) context.lookup(jndiName);
                if (dataSource == null) {
                    LOGGER.error("No data source found with JNDI name [" + jndiName + "].");
                    return null;
                }
                return new DataSourceConnectionSource(jndiName, dataSource);
            } catch (final NamingException e) {
                LOGGER.error(e.getMessage(), e);
                return null;
            }
        }
    
    • JndiManager#lookup
    @SuppressWarnings("unchecked")
        public <T> T lookup(final String name) throws NamingException {
            return (T) this.context.lookup(name);
        }
    

    找到sink后我們還需要找到source,雖然Codeql定義了RemoteFlowSource支持多種source,但是我們還是要根據實際的代碼業務來分析可能作為source的點。

    在Log4j作為日志記錄的工具,除了從HTTP請求中獲取輸入點外,還可以在記錄日志請求或者解析配置文件中來獲取source。先不看解析配置文件獲取source的點了,因為這需要分析Log4j解析配置文件的流程比較復雜。所以目前我們只考慮通過日志記錄作為source的情況。稍微了解Log4j的同學都知道,Log4j會通過error/fatal/info/debug/trace等方法對不同級別的日志進行記錄。通過分析我們可以看到我們輸入的message都調用了logIfEnabled方法并作為第四個參數輸入,所以可以將這里定義為source。

    下面使用全局污點追蹤分析JNDI漏洞,還是套用LookupInterface項目中的代碼,修改source部分即可。

    /**
     *@name Tainttrack Context lookup
     *@kind path-problem
     */
    import java
    import semmle.code.java.dataflow.FlowSources
    import DataFlow::PathGraph
    class Context extends  RefType{
        Context(){
            this.hasQualifiedName("javax.naming", "Context")
            or
            this.hasQualifiedName("javax.naming", "InitialContext")
            or
            this.hasQualifiedName("org.springframework.jndi", "JndiCallback")
            or 
            this.hasQualifiedName("org.springframework.jndi", "JndiTemplate")
            or
            this.hasQualifiedName("org.springframework.jndi", "JndiLocatorDelegate")
            or
            this.hasQualifiedName("org.apache.shiro.jndi", "JndiCallback")
            or
            this.getQualifiedName().matches("%JndiCallback")
            or
            this.getQualifiedName().matches("%JndiLocatorDelegate")
            or
            this.getQualifiedName().matches("%JndiTemplate")
        }
    }
    class Logger extends  RefType{
        Logger(){
            this.hasQualifiedName("org.apache.logging.log4j.spi", "AbstractLogger")
        }
    }
    predicate isLookup(Expr arg) {
        exists(MethodAccess ma |
            ma.getMethod().getName() = "lookup"
            and
            ma.getMethod().getDeclaringType() instanceof Context
            and
            arg = ma.getArgument(0)
        )
    }
    predicate isLogging(Expr arg) {
        exists(MethodAccess ma |
            ma.getMethod().getName() = "logIfEnabled"
            and
            ma.getMethod().getDeclaringType() instanceof Logger
            and
            arg = ma.getArgument(3)
        )
    }
    class TainttrackLookup  extends TaintTracking::Configuration {
        TainttrackLookup() { 
            this = "TainttrackLookup" 
        }
    
        override predicate isSource(DataFlow::Node source) {
            exists(Expr exp |
                isLogging(exp)
                and
                source.asExpr() = exp
            )
        }
    
        override predicate isSink(DataFlow::Node sink) {
            exists(Expr arg |
                isLookup(arg)
                and
                sink.asExpr() = arg
            )
        }
    } 
    from TainttrackLookup config , DataFlow::PathNode source, DataFlow::PathNode sink
    where
        config.hasFlowPath(source, sink)
    select sink.getNode(), source, sink, "unsafe lookup", source.getNode(), "this is user input"
    

    雖然這些也得到了很多查詢結果,但是在實際使用Log4j打印日志時可能不會帶上Marker參數而是直接寫入messge的內容。

    所以我們現在要追蹤的source應該是帶有一個參數的error/fatal/info/debug/trace等方法。我這里以error方法為例對source部分進行修改。

    class LoggerInput extends  Method {
        LoggerInput(){
            //限定調用的類名、方法名、以及方法只有一個參數
            this.getDeclaringType() instanceof Logger and
            this.hasName("error") and this.getNumberOfParameters() = 1
        }
        //將第一個參數作為source
        Parameter getAnUntrustedParameter() { result = this.getParameter(0) }
    }
    override predicate isSource(DataFlow::Node source) {
            exists(LoggerInput LoggerMethod |
                source.asParameter() = LoggerMethod.getAnUntrustedParameter())
        }
    

    這樣我們就得到了多條鏈,現在我們要寫個Demo驗證這個鏈是否可行,比如最簡單的logger.error("xxxxx");

    1    message : Message     AbstractLogger.java:709:23
    2    message : Message     AbstractLogger.java:710:47
    3    message : Message     AbstractLogger.java:1833:89
    4    message : Message     AbstractLogger.java:1835:38
    5    message : Message     Logger.java:262:70
    6    message : Message     Logger.java:263:52
    7    msg : Message     Logger.java:617:64
    8    msg : Message     Logger.java:620:78
    9    msg : Message     RegexFilter.java:73:87
    10    msg : Message     RegexFilter.java:78:63
    ...
    64    convertJndiName(...) : String     JndiLookup.java:54:33
    65    jndiName : String     JndiLookup.java:56:56
    66    name : String     JndiManager.java:171:25
    67    name     JndiManager.java:172:40
    Path
    

    但是這條鏈只有配置了Filter為RegexFilter才會繼續執行,而默認沒有配置則為空。

    所以這種方式就稍微有些限制,所以我們再去看看其他鏈。這條鏈似乎不用配置Filter。

    1    message : Message     AbstractLogger.java:709:23
    2    message : Message     AbstractLogger.java:710:47
    3    message : Message     AbstractLogger.java:1833:89
    4    message : Message     AbstractLogger.java:1836:51
    5    message : Message     AbstractLogger.java:2139:94
    6    message : Message     AbstractLogger.java:2142:59
    7    message : Message     AbstractLogger.java:2155:43
    8    message : Message     AbstractLogger.java:2159:67
    9    message : Message     AbstractLogger.java:2202:32
    10    message : Message     AbstractLogger.java:2205:48
    11    message : Message     AbstractLogger.java:2116:9
    12    message : Message     AbstractLogger.java:2117:41
    ...
    78    var : String     Interpolator.java:230:92
    79    key : String     JndiLookup.java:50:48
    80    key : String     JndiLookup.java:54:49
    81    jndiName : String     JndiLookup.java:70:36
    82    jndiName : String     JndiLookup.java:74:16
    83    convertJndiName(...) : String     JndiLookup.java:54:33
    84    jndiName : String     JndiLookup.java:56:56
    85    name : String     JndiManager.java:171:25
    86    name     JndiManager.java:172:40
    

    但是在AbstractLogger#tryLogMessage中Codeql會直接分析到AbstractLogger#log而實際請求時會解析到Logger#log方法。這是因為LoggerAbstractLogger的子類并且也實現了log方法,而且我們實例化的也是Logger對象,所以這里會調用到Logger#log

    實際請求

    CodeQL分析

    再看看下面這條鏈

    1    message : Message     AbstractLogger.java:709:23
    2    message : Message     AbstractLogger.java:710:47
    3    message : Message     AbstractLogger.java:1833:89
    4    message : Message     AbstractLogger.java:1836:51
    5    message : Message     AbstractLogger.java:2139:94
    6    message : Message     AbstractLogger.java:2142:59
    7    message : Message     AbstractLogger.java:2155:43
    8    message : Message     AbstractLogger.java:2159:67
    9    message : Message     AbstractLogger.java:2202:32
    10    message : Message     AbstractLogger.java:2205:48
    11    message : Message     Logger.java:158:9
    12    message : Message     Logger.java:162:17
    13    data : Message     AwaitCompletionReliabilityStrategy.java:78:83
    14    data : Message     AwaitCompletionReliabilityStrategy.java:82:67
    15    data : Message     LoggerConfig.java:430:28
    16    data : Message     LoggerConfig.java:454:17
    17    message : Message     ReusableLogEventFactory.java:78:86
    18    message : Message     ReusableLogEventFactory.java:100:27
    19    msg : Message     MutableLogEvent.java:209:28
    20    (...)... : Message     MutableLogEvent.java:211:46
    21    reusable : Message     MutableLogEvent.java:212:13
    22    parameter this : Message     ReusableObjectMessage.java:47:17
    23    obj : Object     ReusableObjectMessage.java:48:44
    ...
    88    convertJndiName(...) : String     JndiLookup.java:54:33
    89    jndiName : String     JndiLookup.java:56:56
    90    name : String     JndiManager.java:171:25
    91    name     JndiManager.java:172:40
    

    這條鏈在執行到MutableLogEvent#setMessage時和CodeQL的分析結果略有不同。

    在CodeQL中resusable.formatTo會調用到ReusableObjectMessage中。

    但是實際運行過程中由于MessgeFactorty創建Message對象時默認創建的是ResableSimpleMessage對象,所以會執行到ResableSimpleMessage#formatTo方法。

    所以似乎目前使用使用CodeQL的規則是發現不了Log4jShell那個漏洞的,既然我們已經知道了這個漏洞的觸發鏈,可以分析下CodeQL為什么沒有分析出來。

    通過之前對CodeQL檢測出的調用鏈分析,CodeQL已經分析到了createEvent方法。

    查看createEvent方法的調用,在Log4jShell的觸發鏈中實際上是在對返回LogEvent的處理過程中觸發的,所以這里CodeQL可能沒有將返回的LogEvent對象再當作污點進行分析,所以導致沒有分析成功。

    我們可以創建一個isAdditionalTaintStep函數,將ReusableLogEventFactory#createEvent的第六個參數Message和LoggerConfig#log第一個參數logEvent連接起來。

    override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
            exists(MethodAccess ma,MethodAccess ma2 |
                ma.getMethod().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core.impl", "ReusableLogEventFactory") 
                and ma.getMethod().hasName("createEvent") and fromNode.asExpr()=ma.getArgument(5) and ma2.getMethod().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core.config", "LoggerConfig")  
                and ma2.getMethod().hasName("log") and ma2.getMethod().getNumberOfParameters() = 2 and toNode.asExpr()=ma2.getArgument(0)
                        )
          }
    

    最后我們就可以通過CodeQL分析到Log4j shell漏洞的調用鏈。

    1    message : Message     AbstractLogger.java:709:23
    2    message : Message     AbstractLogger.java:710:47
    3    message : Message     AbstractLogger.java:1833:89
    4    message : Message     AbstractLogger.java:1836:51
    5    message : Message     AbstractLogger.java:2139:94
    6    message : Message     AbstractLogger.java:2142:59
    7    message : Message     AbstractLogger.java:2155:43
    8    message : Message     AbstractLogger.java:2159:67
    9    message : Message     AbstractLogger.java:2202:32
    10    message : Message     AbstractLogger.java:2205:48
    11    message : Message     Logger.java:158:9
    12    message : Message     Logger.java:162:17
    13    data : Message     DefaultReliabilityStrategy.java:61:83
    14    data : Message     DefaultReliabilityStrategy.java:63:69
    15    data : Message     LoggerConfig.java:430:28
    16    data : Message     LoggerConfig.java:454:96
    17    message : Message     ReusableLogEventFactory.java:58:47
    18    message : Message     ReusableLogEventFactory.java:60:67
    19    event : LogEvent     LoggerConfig.java:469:13
    20    event : LogEvent     LoggerConfig.java:479:24
    21    event : LogEvent     LoggerConfig.java:481:29
    22    event : LogEvent     LoggerConfig.java:495:34
    23    event : LogEvent     LoggerConfig.java:498:27
    24    event : LogEvent     LoggerConfig.java:536:34
    25    event : LogEvent     LoggerConfig.java:540:38
    26    event : LogEvent     AppenderControl.java:80:30
    27    event : LogEvent     AppenderControl.java:84:38
    28    event : LogEvent     AppenderControl.java:117:47
    29    event : LogEvent     AppenderControl.java:120:27
    30    event : LogEvent     AppenderControl.java:126:32
    31    event : LogEvent     AppenderControl.java:129:29
    32    event : LogEvent     AppenderControl.java:154:34
    33    event : LogEvent     AppenderControl.java:156:29
    34    event : LogEvent     AbstractDatabaseAppender.java:107:30
    35    event : LogEvent     AbstractDatabaseAppender.java:110:37
    36    event : LogEvent     AbstractDatabaseManager.java:260:42
    37    event : LogEvent     AbstractDatabaseManager.java:262:20
    38    event : LogEvent     AbstractDatabaseManager.java:122:27
    39    event : LogEvent     AbstractDatabaseManager.java:123:25
    40    parameter this : LogEvent     Log4jLogEvent.java:530:26
    41    this : LogEvent     Log4jLogEvent.java:534:16
    42    toImmutable(...) : LogEvent     AbstractDatabaseManager.java:123:25
    43    this.buffer [post update] [<element>] : LogEvent     AbstractDatabaseManager.java:123:9
    44    this [post update] [buffer, ] : LogEvent     AbstractDatabaseManager.java:123:9
    45    this <.method> [post update] [buffer, ] : LogEvent     AbstractDatabaseManager.java:262:13
    46    getManager(...) [post update] [buffer, ] : LogEvent     AbstractDatabaseAppender.java:110:13
    47    this [post update] [manager, buffer, ] : LogEvent     AbstractDatabaseAppender.java:110:13
    48    appender [post update] [manager, buffer, ] : LogEvent     AppenderControl.java:156:13
    49    this <.field> [post update] [appender, manager, buffer, ] : LogEvent     AppenderControl.java:156:13
    50    this <.method> [post update] [appender, manager, buffer, ] : LogEvent     AppenderControl.java:129:13
    51    this <.method> [post update] [appender, manager, buffer, ] : LogEvent     AppenderControl.java:120:13
    52    this <.method> [post update] [appender, manager, buffer, ] : LogEvent     AppenderControl.java:84:9
    53    event : LogEvent     AppenderControl.java:80:30
    54    event : LogEvent     AppenderControl.java:84:38
    55    event : LogEvent     AppenderControl.java:117:47
    56    event : LogEvent     AppenderControl.java:120:27
    57    event : LogEvent     AppenderControl.java:126:32
    58    event : LogEvent     AppenderControl.java:129:29
    59    event : LogEvent     AppenderControl.java:154:34
    60    event : LogEvent     AppenderControl.java:156:29
    61    event : LogEvent     AbstractOutputStreamAppender.java:179:24
    62    event : LogEvent     AbstractOutputStreamAppender.java:181:23
    63    event : LogEvent     AbstractOutputStreamAppender.java:188:28
    64    event : LogEvent     AbstractOutputStreamAppender.java:190:31
    65    event : LogEvent     AbstractOutputStreamAppender.java:196:38
    66    event : LogEvent     AbstractOutputStreamAppender.java:197:28
    67    event : LogEvent     GelfLayout.java:433:24
    68    event : LogEvent     GelfLayout.java:438:43
    69    event : LogEvent     GelfLayout.java:471:34
    70    event : LogEvent     GelfLayout.java:496:46
    71    event : LogEvent     StrSubstitutor.java:462:27
    72    event : LogEvent     StrSubstitutor.java:467:25
    73    event : LogEvent     StrSubstitutor.java:911:34
    74    event : LogEvent     StrSubstitutor.java:912:27
    75    event : LogEvent     StrSubstitutor.java:928:28
    76    event : LogEvent     StrSubstitutor.java:978:44
    77    event : LogEvent     StrSubstitutor.java:911:34
    78    event : LogEvent     StrSubstitutor.java:912:27
    79    event : LogEvent     StrSubstitutor.java:928:28
    80    event : LogEvent     StrSubstitutor.java:1033:63
    81    event : LogEvent     StrSubstitutor.java:1104:38
    82    event : LogEvent     StrSubstitutor.java:1110:32
    83    event : LogEvent     StructuredDataLookup.java:46:26
    84    event : LogEvent     StructuredDataLookup.java:50:67
    85    parameter this : LogEvent     RingBufferLogEvent.java:206:20
    86    message : Message     RingBufferLogEvent.java:210:16
    87    getMessage(...) : Message     StructuredDataLookup.java:50:67
    88    (...)... : Message     StructuredDataLookup.java:50:43
    89    msg : Message     StructuredDataLookup.java:54:20
    90    parameter this : Message     StructuredDataMessage.java:239:19
    91    type : String     StructuredDataMessage.java:240:16
    92    getType(...) : String     StructuredDataLookup.java:54:20
    93    lookup(...) : String     StrSubstitutor.java:1110:16
    94    resolveVariable(...) : String     StrSubstitutor.java:1033:47
    95    varValue : String     StrSubstitutor.java:1040:63
    96    buf [post update] : StringBuilder     StrSubstitutor.java:1040:33
    97    buf [post update] : StringBuilder     StrSubstitutor.java:912:34
    98    bufName [post update] : StringBuilder     StrSubstitutor.java:978:51
    99    bufName : StringBuilder     StrSubstitutor.java:979:47
    100    toString(...) : String     StrSubstitutor.java:979:47
    101    varNameExpr : String     StrSubstitutor.java:1010:55
    102    substring(...) : String     StrSubstitutor.java:1010:55
    103    varName : String     StrSubstitutor.java:1033:70
    104    variableName : String     StrSubstitutor.java:1104:60
    105    variableName : String     StrSubstitutor.java:1110:39
    106    key : String     JndiLookup.java:50:48
    107    key : String     JndiLookup.java:54:49
    108    jndiName : String     JndiLookup.java:70:36
    109    ... + ... : String     JndiLookup.java:72:20
    110    convertJndiName(...) : String     JndiLookup.java:54:33
    111    jndiName : String     JndiLookup.java:56:56
    112    name : String     JndiManager.java:171:25
    113    name     JndiManager.java:172:40
    

    漏洞挖掘嘗試

    通過上面的分析可以看到,挖掘到所有的鏈最終的觸發點都是JndiManager,這個點目前的觸發已經在新版本中修復了,但是在DataSourceConnectionSource#createConnectionSource中也直接調用了lookup方法,我們能否通過某種方式觸發呢?

    通過注釋可以看到DataSource是Core類型插件,因此可以在XML中直接通過標簽配置調用。

    xml version="1.0" encoding="UTF-8"?>
     status="WARN">
        
             name="Console" target="SYSTEM_OUT">
                 pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            
        
         jndiName="ldap://9b89e78d.dns.1433.eu.org.">
        
        
             level="ERROR">
                 ref="Console"/>
            
        
    
    

    配置后可以在插件加載的過程中觸發漏洞,雖然這種方式也可以造成JNDI注入,但是需要在配置文件中修改參數才能觸發,所以價值不大。

    最后給出整體的分析Log4j JNDI注入的CodeQL查詢代碼

    /**
     *@name Tainttrack Context lookup
     *@kind path-problem
     */
    import java
    import semmle.code.java.dataflow.FlowSources
    import DataFlow::PathGraph
    class Context extends  RefType{
        Context(){
            this.hasQualifiedName("javax.naming", "Context")
            or
            this.hasQualifiedName("javax.naming", "InitialContext")
            or
            this.hasQualifiedName("org.springframework.jndi", "JndiCallback")
            or 
            this.hasQualifiedName("org.springframework.jndi", "JndiTemplate")
            or
            this.hasQualifiedName("org.springframework.jndi", "JndiLocatorDelegate")
            or
            this.hasQualifiedName("org.apache.shiro.jndi", "JndiCallback")
            or
            this.getQualifiedName().matches("%JndiCallback")
            or
            this.getQualifiedName().matches("%JndiLocatorDelegate")
            or
            this.getQualifiedName().matches("%JndiTemplate")
        }
    }
    class Logger extends  RefType{
        Logger(){
            this.hasQualifiedName("org.apache.logging.log4j.spi", "AbstractLogger")
        }
    }
    class LoggerInput extends  Method {
        LoggerInput(){
            this.getDeclaringType() instanceof Logger and
            this.hasName("error") and this.getNumberOfParameters() = 1
        }
        Parameter getAnUntrustedParameter() { result = this.getParameter(0) }
    }
    predicate isLookup(Expr arg) {
        exists(MethodAccess ma |
            ma.getMethod().getName() = "lookup"
            and
            ma.getMethod().getDeclaringType() instanceof Context
            and
            arg = ma.getArgument(0)
        )
    }
    class TainttrackLookup  extends TaintTracking::Configuration {
        TainttrackLookup() { 
            this = "TainttrackLookup" 
        }
    
        override predicate isSource(DataFlow::Node source) {
            exists(LoggerInput LoggerMethod |
                source.asParameter() = LoggerMethod.getAnUntrustedParameter())
        }
    
        override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
            exists(MethodAccess ma,MethodAccess ma2 |
                ma.getMethod().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core.impl", "ReusableLogEventFactory") 
                and ma.getMethod().hasName("createEvent") and fromNode.asExpr()=ma.getArgument(5) and ma2.getMethod().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core.config", "LoggerConfig")  
                and ma2.getMethod().hasName("log") and ma2.getMethod().getNumberOfParameters() = 2 and toNode.asExpr()=ma2.getArgument(0)
                        )
          }
        override predicate isSink(DataFlow::Node sink) {
            exists(Expr arg |
                isLookup(arg)
                and
                sink.asExpr() = arg
            )
        }
    } 
    from TainttrackLookup config , DataFlow::PathNode source, DataFlow::PathNode sink
    where
        config.hasFlowPath(source, sink)
    select sink.getNode(), source, sink, "unsafe lookup", source.getNode(), "this is user input"
    

    總結

    通過CodeQL挖洞效率確實比較高,并且在官方也給出了針對很多類型漏洞的審計規則,確實可以高效的輔助挖洞,目前主要解決下面兩個問題。

    • 默認的Source應該只是針對HTTP請求,如何針對特定的框架去發現可能作為source的點
    • 分析污點在何時會被打斷并進行拼接
    漏洞挖掘log4j
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    分析漏洞的本質是為了能讓我們從中學習漏洞挖掘者的思路以及挖掘到新的漏洞,而CodeQL就是一款可以將我們對漏洞的理解快速轉化為可實現的規則并挖掘漏洞的利器。根據網上的傳言Log4j2的RCE漏洞就是作者通過CodeQL挖掘出的。雖然如何挖掘的我們不得而知,但我們現在站在事后的角度再去想想,可以推測一下作者如何通過CodeQL挖掘漏洞的,并嘗試基于作者的思路挖掘漏洞
    漏洞排查與處置,是安全管理員在安全運營中都會碰到的問題,常見卻很難做好。
    項目安裝迷你天貓商城是一個基于Spring Boot的綜合性B2C電商平臺,需求設計主要參考天貓商城的購物流程:用戶從注冊開始,到完成登錄,瀏覽商品,加入購物車,進行下單,確認收貨,評價等一系列操作。作為迷你天貓商城的核心組成部分之一,天貓數據管理后臺包含商品管理,訂單管理,類別管理,用戶管理和交易額統計等模塊,實現了對整個商城的一站式管理和維護。
    2021年十大漏洞利用
    2022-01-02 16:33:11
    本文總結了作者心目中的2021十大漏洞利用。
    8月21日,為期兩天的第六屆“強網杯”全國網絡安全挑戰賽線下賽圓滿結束。從32支戰隊中脫穎而出,長亭科技0x300R 戰隊最終斬獲強網杯特等獎—亞軍,同時作為線下賽總積分排名最高的企業戰隊,獲評“強網最佳企業戰隊”榮譽稱號。最終長亭0x300R戰隊以僅300分的差距將亞軍收入囊中。
    武裝你的BurpSuite
    2022-03-18 15:38:20
    0x01前言BurpSuite是廣大安全人員使用率最高的一款工具了,通過對數據包的修改,重放往往能發現很多安
    隨著數字化應用的高速發展,軟件已被各行各業廣泛應用,成為必不可少的一部分。近年來,全球范圍內有關軟件供應鏈安全的攻擊事件層出不斷,對個人、企業,甚至國家安全都造成了嚴重威脅。近期曝出的Apache log4j2漏洞的嚴重性、廣泛性已經在各個領域顯現,波及面非常大,更是讓業界意識到做好開源軟件安全治理已是迫在眉睫。
    Java審計其實和Php審計的思路一樣,唯一不同的可能是復雜的框架和代碼。
    為進一步推動產業發展,更好地匯聚產學研用各方力量,聚焦關鍵軟件領域密碼應用核心問題,不斷夯實軟件產業發展基礎,共同推動軟件產業和密碼技術融合發展,12月18日,“2021年商用密碼應用創新高端研討會”在經開區國家信創園成功召開。在會上,中關村網絡安全與信息化產業聯盟EMCG工作組組長王克帶來題為《密碼在軟件供應鏈安全中的應用》的演講。
    FCIS 2023網絡安全創新大會在上海張江科學會堂圓滿落幕。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类