发布于 

攻防世界-web02

  • 题目:小周将他小时候最心爱的玩具锁在了密码箱里,但由于时间久远,密码忘记了一部分,你能帮帮他吗?
  • 靶机: http://47.94.14.162:10008/?password=ISCC%7B4%7D&password2=5

分析

F12查看源码看到style="display:none",去掉display:none可以看到密码箱信息

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

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

找到div,输入style="display:none",去掉弹框

代码审计

可以看到<?php 里面 包含具体加密逻辑
image.png

计算给定字符串的哈希码

计算给定字符串的哈希码 -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打开后直接得到结果,copyurl中加上sha2参数
image.png

获取参数sha1,sha2,username的值 -l
$user = $_GET['username'];//user
$sha1 = $_GET['sha1'];//sha1
$sha2 = $_GET['‮⁦//sha2⁩⁦sha2'];
//‮⁦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)))

需要三个参数,所以分析程序加入usernamesha1字段后的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
image.png

通过if((substr(sha1($crypto),-6,6) === substr(sha1($user),-6,6)) && (substr(sha1($user),-6,6)) === 'a05c53')得到结果如下:
user = a05c53
sha1 是一个单向哈希函数,用来计算hashCodeusercrypto 是一个 变量,用来赋值用
比较两个字符串的后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编码的优点是可以表示全球范围内的所有字符,包括各种语言的字母符号标点表情

image.png

QA

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