2018-ISCC

May 7, 2018 10:54 · 245 words · 2 minute read ctf

前记

Collide

考察的是哈希长度扩展攻击

简单说一下原理

hash的MD5对数据进行加密的时候,是分组进行加密。 MD5加密的时候会有四个初始向量IV,对第一组数据加密的时候利用的就是四个初始向量,不同的是,在对第二组数据进行加密的时候,使用的并不是四个初始向量,而是将前一组加密后的密文作为下一组的初始向量。 哈希长度扩展攻击便是利用这个特性来实现的。

扩展攻击实现的条件

  • 已知MD5($salt.$data)值,
  • 知道加密的$salt的长度
  • 知道$data的值

结合题目分析

<?php
include "secret.php";
@$username=(string)$_POST['username'];
function enc($text){
    global $key;
    return md5($key.$text);
}
if(enc($username) === $_COOKIE['verify']){
    if(is_numeric(strpos($username, "admin"))){
        die($flag);
    }
    else{
        die("you are not admin");
    }
}
else{
    setcookie("verify", enc("guest"), time()+60*60*24*7);
    setcookie("len", strlen($key), time()+60*60*24*7);
}
show_source(__FILE__);

从源码我们可以获得以下内容 - enc(“guest”)的值为78cfc57d983b4a17e55828c001a3e781 - $key的长度为46

题目的关键代码

if(enc($username) === $_COOKIE['verify']){
    if(is_numeric(strpos($username, "admin"))){
        die($flag);
    }

这段代码要求我们输入的username在经过enc函数加密之后,与$_COOKIE[‘verify’]的值相等,并且username中必须含有admin。

看到这里,我们就可以想到来利用哈希长度扩展来帮我们解决这个问题。

而且题目给予我们的信息,刚好满足哈希长度扩展攻击的要求。

操作

这里我们使用HashPump这个工具

安装

git clone https://github.com/bwall/HashPump
apt-get install g++ libssl-dev
cd HashPump
make
make install

使用说明

Input Signature: 已知的hash值,这里是$_COOKIE['verify']的值
Input Data: 上面的hash值解密后的字符串,这里是guest。
Input Key Length: $key的长度
Input Data to Add: 想要添加的数据,由于题目要求要含有admin,所以这里是admin。

使用

➜  HashPump hashpump
Input Signature: 78cfc57d983b4a17e55828c001a3e781
Input Data: guest
Input Key Length: 46
Input Data to Add: admin
5f585093a7fe86971766c3d25c43d0eb
guest\x80\x00\x00\x00\x00\x98\x01\x00\x00\x00\x00\x00\x00admin

然后我们将得到的hash值去替换数据包中$_COOKIE[‘verify’]的值,然后post提交username=guest%80%00%00%00%00%98%01%00%00%00%00%00%00admin即可。

最后一步的时候,我直接在抓的包里修改值了,但是忘记把GET修改成POST了,还以为哪里出错了。。。。

flag

ISCC{MD5_1s_n0t_5afe}

Only admin can see flag

考察的是CBC翻转攻击

操作

腳本1

# -*- coding:utf-8 -*-

import base64
from urllib import unquote
from urllib import quote_plus

# bs = 'J67IvH4OY9t6QfcCP4Mp88bRfPKdsYszlev3LNbgPQ872VR633trbWfCqhcDYm6c3Eysp36W2SFkx4CPBX9nDQ%3D%3D'
bs = "IH0KQlnaEHXeG2c7r8%2BnzMZCMfaW%2BPN4yi2eNEGlIA5e%2F78Ceu9%2B8%2Bhs1qQ0Rbrpp5idda1V%2BW0dPSlJEgSjFw%3D%3D"
         
#密文cipher,从Chrome的插件EditThisCookie可以很轻松get到
bs = unquote(bs)
#url解码
bs_de = base64.b64decode(bs)
#base64解码

ch = chr(ord(bs_de[13]) ^ ord('2') ^ ord('n'))
bs_de=bs_de[0:13]+ch+bs_de[14::]
#其实就是bs_de[13]=chr(ord(bs_de[13]) ^ ord('2') ^ ord('n'))
#因为python里面字符串不可变,即你直接bs_de = 'a'这样会报错

rs = base64.b64encode(bs_de)
#print rs
print quote_plus(rs)

腳本2

# -*- coding:utf-8 -*-

import base64
from urllib import unquote
from urllib import quote_plus

mingwen_de='UHRUCklmLkOojPr4ZN52zm1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjA6IiI7fQ=='
#base64_decode('这里面的') can't unserialize
mingwen = base64.b64decode(mingwen_de)
print mingwen

iv = 'B13APJ%2BCscobPvKj99iNSw%3D%3D'
#此时cookie里的iv
iv = unquote(iv)
iv_de = base64.b64decode(iv)
new = 'a:2:{s:8:"userna'
for i in range(16):
    iv_de = iv_de[:i] + chr(ord(iv_de[i]) ^ ord(mingwen[i]) ^ ord(new[i])) + iv_de[i+1:]
#iv_de[i]=chr(ord(iv_de[i]) ^ ord(mingwen[i]) ^ ord(new[i]))

print(base64.b64encode(iv_de))
#用这个结果把原来的iv换掉

1.在登录页面输入admi2,然后直接点击登录。 2.在chrome的EditThisCookie插件里获取cookie中cipher的值,然后将cipher的值复制到脚本1的bs里。 3.用第二步的输出结果将cookie中的cipher替换掉。然后在地址栏敲下回车,不要点刷新。 4.然后页面返回了一串base64,然后说反序列化失败。 5.将第四步返回的base64字符串赋值给脚本2的mingwen_de。在将cookie的iv赋值给脚本2的iv。 6.用第五步输出的结果替换掉cookie的iv,然后在地址栏敲回车,即可获取flag。

详解

tweet Share