攻防世界-web02
- 题目:
小周将他小时候最心爱的玩具锁在了密码箱里,但由于时间久远,密码忘记了一部分,你能帮帮他吗? - 靶机:
http://47.94.14.162:10008/?password=ISCC%7B4%7D&password2=5
分析
F12查看源码看到style="display:none",去掉display:none可以看到密码箱信息

根据题目提示但由于时间久远,密码忘记了一部分,猜测(wen da lao)密码可能为4、5, 点击解锁`页面跳转到下一级

有一个弹框阻扰我们分析代码,F12 可以看到隐藏掉弹框即可,这里password会有一个base64字符串是显示这个图片的,这个弹框是LastPass的图片,不需要关注

找到div,输入style="display:none",去掉弹框
代码审计
可以看到<?php 里面 包含具体加密逻辑

计算给定字符串的哈希码
计算给定字符串的哈希码 -l
# 计算给定字符串的哈希码
def MyHashCode(str):
h = 0
length = len(str)
for i in range(length):
hash = int40(int40(40 * hash) + ord(str[i]))
return abs(hash)将一个整数转换为40位的二进制补码表示
计算给定字符串的哈希码 -l
def int40(code):
# 将一个32位整数转换为40位的二进制补码表示
flag = code >> 32
# 如果该整数的最高位为1,则表示该整数是负数
if flag == 1:
# 需要先对其进行一次按位取反操作,再加1得到其二进制补码表示,最后再乘以-1得到其负值
code = ~ (code - 1)
return code * -1
else:
return code检测字符串是否包含 ISCC,包含直接false
- 解题格式一般为 ISCC{FLAG}
def Checked(str):
p1 = 'ISCC'
if p1 in str:
return False
return True
对数据进行加密处理
对数据进行加密处理 -l
def SecurityCheck(sha1, sha2, user):
if Checked(sha1) and Checked(sha2): # 检测是否包含 ISCC,如果包含就返回 wrong
sha1 = sha1.upper() # 转为大写
sha2 = sha2.lower() # 转为小写
user = user.upper() # user 转为大写字母
crypto = MyHashCode(sha1) ^ MyHashCode(sha2)
# 计算sha1和sha2的哈希值,并将它们异或起来得到crypto
else:
print("wrong")
# 如果其中一个checked 函数返回false 则打印字符串 “wrong” 并返回none。
return None
return [crypto, user]
# 返回一个包含 crypto 和 user的列表关键逻辑,获取FLAG
大坑使用VisualCode,观察了三天(wen da lao),结果用sublime Text打开后直接得到结果,copy到url中加上sha2参数

获取参数sha1,sha2,username的值 -l
$user = $_GET['username'];//user
$sha1 = $_GET['sha1'];//sha1
$sha2 = $_GET['//sha2sha2'];
//see me can you 关键逻辑 -l
#检查sha1 和 sha2 和 user 是否被赋值
if sha1 and sha2 and user:
# 34839520012
[crypto, user] = SecurityCheck(sha1, sha2, user)
# 检查crypto和user的SHA-1哈希的最后六个字符是否都等于字符串'a05c53'
# 14987637 ceca5d3ab81779f20b97dab9220c46f3f9 a05c53
if sha1(crypto)[-6:] == sha1(user)[-6:] == 'a05c53': # welcome to ISCC
#ISCCNOTHARD 484c0dd902218fef1e239baf69aeca61fbb94c06
#ISCC{}
if MyHashCode("ISCCNOTHARD") == MyHashCode(request.args
.get('password')) and Checked(request.args.get('password')):
include("f1ag.php")
print("成功了"+flag)
else:
print("就快解开了!")
else:
print("真的想不起来密码了吗?")
print("随机数:"+random.seed(int(time.time() * 1000) ^ random.randint(1, 10000)))
需要三个参数,所以分析程序加入username,sha1字段后的url如下
http://47.94.14.162:10008/?password=ISCC&sha1=md&%E2%80%AE%E2%81%A6//sha2%E2%81%A9%E2%81%A6sha2=MD&username&password2=6

通过if((substr(sha1($crypto),-6,6) === substr(sha1($user),-6,6)) && (substr(sha1($user),-6,6)) === 'a05c53')得到结果如下:
user = a05c53
sha1 是一个单向哈希函数,用来计算hashCode,user 和 crypto 是一个 变量,用来赋值用
比较两个字符串的后6位是否相等,并且第二个字符串的后6位是否为’a05c53’。具体来说,这段代码使用PHP中的sha1函数对两个变量进行哈希处理,然后从每个哈希值的末尾6个字符中提取子字符串,并使用" ==="运算符比较它们是否相等。如果这两个子字符串都相等,并且第二个字符串后6位是’a05c53’,则条件成立,返回true,否则返回false。
检查crypto和user的SHA-1哈希的最后六个字符是否都等于字符串’a05c53’
- 编写爆破脚本,得到hash的最后
6位为a05c53
编写爆破脚本 -l
hash_suffix = "a05c53"
# 解密格式
hash_prefix = "98f08553e02079cd966442400bcef0e031642e2"
for i in range(100000000):
num = str(i).encode('utf-8')
hash_num = hashlib.sha1(num).hexdigest()
if hash_prefix + hash_num[-6:] == hash_prefix + hash_suffix:
print("The number is: ", i)
break结果为:14987637
HashCode = ceca5d3ab81779f20b97dab9220c46f3f9a05c53;
得到秘钥,那么密文和公钥是什么?我该如何推导出来 sha1 和 user的值呢?
1.规律:(substr(sha1($crypto),-6,6) === substr(sha1($user),-6,6)
UNICODE 反转
- 理解一下什么是
unicode的码点? Unicode是属于编码字符集(CCS)的范围。Unicode所做的事情就是将我们需要表示的字符表中的每个字符映射成一个数字,这个数字被称为相应字符的码点(code point)。Unicode编码使用16位或32位数字来表示字符,其中16位编码称为基本多文种平面(BMP),32位编码称为补充平面。Unicode编码的优点是可以表示全球范围内的所有字符,包括各种语言的字母、符号、标点和表情


QA
Q:如何获取sha1,sha2,use的值?
A:在源码中找答案 