最新消息:

PHP challenges学习

PHP学习笔记 admin 5654浏览 0评论

网址:http://php4fun.sinaapp.com/

第一关:http://php4fun.sinaapp.com/c1/index.php

代码:

<?php
#GOAL: get password from admin;
error_reporting(0);
require 'db.inc.php';

function clean($str){
	if(get_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=\''.$username.'\' AND pass=\''.$password.'\';';
$result=mysql_query($query);
if(!$result || mysql_num_rows($result) < 1){
	die('Invalid password!');
}

$row = mysql_fetch_assoc($result);

echo "Hello ".$row['name']."</br>";
echo "Your password is:".$row['pass']."</br>";
?>

由于作者使用了htmlentities()来处理输入,所以不能使用’来闭合原先存在的'(因为会被转义),所以只能使用\来进行。username输入\,password输入or 1=1 —  就可以了。注意:由于mysql的注释中–后面还有一个空格,而直接输如空格的话,由于在最后,浏览器会把空格去掉,导致绕过失败,所以password可以输入 or 1=1–+     或or 1=1 –%20或 or 1=1– ;等(只要不让未编码空格放在最后即可)。

20130911210035

参考资料:PHP htmlentities() 函数

20130911205011

第二关:http://phpchallenges2.sinaapp.com/index.php

代码:

<?php
#GOAL: gather some phpinfo();

$str=@(string)$_GET['str'];
eval('$str="'.addslashes($str).'";');
?>

这一关的目的是为了执行phpinfo()。要注意到$str的字符串是双引号,而双引号中变量是可以执行的,所以构造与phpinfo()有关的变量即可。参考资料:http://www.wooyun.org/bugs/wooyun-2010-024807(即ecshop的漏洞),可以输入{${phpinfo()}}来达到执行代码的目的。所以这一关的过关url是:phpchallenges2.sinaapp.com/index.php?str={${phpinfo()}}

20130911210755

第三关:http://php4fun.sinaapp.com/c3/index.php
代码;

<?php
# GOAL: dump the info for the secret id
require 'db.inc.php';

$id = @(float)$_GET['id'];

$secretId = 1;
if($id == $secretId){
	echo 'Invalid id ('.$id.').';
}
else{
	$query = 'SELECT * FROM users WHERE id = \''.$id.'\';';
	$result = mysql_query($query);
	$row = mysql_fetch_assoc($result);

    echo "id: ".$row['id']."</br>";
    echo "name:".$row['name']."</br>";
}
?>

 

暂时还没有绕过

第四关:http://php4fun.sinaapp.com/c4/index.php

代码:

<?php
#GOAL:get password from admin
# $yourInfo=array(
#   'id'    => 1,
#   'name'  => 'admin',
#   'pass'  => 'xxx',
#   'level' => 1
# );
require 'db.inc.php';

$_CONFIG['extraSecure']=true;

//if register globals = on, undo var overwrites
foreach(array('_GET','_POST','_REQUEST','_COOKIE') as $method){
     foreach($$method as $key=>$value){
          unset($$key);
     }
}

$kw = isset($_GET['kw']) ? trim($_GET['kw']) : die('Please enter in a search keyword.');

if($_CONFIG['extraSecure']){
     $kw=preg_replace('#[^a-z0-9_-]#i','',$kw);
}

$query = 'SELECT * FROM messages WHERE message LIKE \'%'.$kw.'%\';';

$result = mysql_query($query);
$row = mysql_fetch_assoc($result);

echo "id: ".$row['id']."</br>";
echo "message: ".$row['message']."</br>";
?>

参考资料:preg_replace()函数

preg_replace — 执行一个正则表达式的搜索和替换,

(1)模式分隔符

当使用 PCRE 函数的时候,模式需要由分隔符闭合包裹。分隔符可以使任意非字母数字、非反斜线、非空白字符。

经常使用的分隔符是正斜线(/)、hash符号(#) 以及取反符号(~)。下面的例子都是使用合法分隔符的模式。

/foo bar/
#^[^0-9]$#
+php+
%[a-zA-Z0-9_-]%

(2)模式修饰符

i (PCRE_CASELESS)
如果设置了这个修饰符,模式中的字母会进行大小写不敏感匹配。
m (PCRE_MULTILINE)
默认情况下,PCRE 认为目标字符串是由单行字符组成的(然而实际上它可能会包含多行), “行首”元字符 (^) 仅匹配字符串的开始位置, 而”行末”元字符 ($) 仅匹配字符串末尾, 或者最后的换行符(除非设置了 D 修饰符)。这个行为和 perl 相同。 当这个修饰符设置之后,“行首”和“行末”就会匹配目标字符串中任意换行符之前或之后,另外, 还分别匹配目标字符串的最开始和最末尾位置。这等同于 perl 的 /m 修饰符。如果目标字符串 中没有 “\n” 字符,或者模式中没有出现 ^ 或 $,设置这个修饰符不产生任何影响。
s (PCRE_DOTALL)
如果设置了这个修饰符,模式中的点号元字符匹配所有字符,包含换行符。如果没有这个 修饰符,点号不匹配换行符。这个修饰符等同于 perl 中的/s修饰符。 一个取反字符类比如 [^a] 总是匹配换行符,而不依赖于这个修饰符的设置。
x (PCRE_EXTENDED)
如果设置了这个修饰符,模式中的没有经过转义的或不在字符类中的空白数据字符总会被忽略, 并且位于一个未转义的字符类外部的#字符和下一个换行符之间的字符也被忽略。 这个修饰符 等同于 perl 中的 /x 修饰符,使被编译模式中可以包含注释。 注意:这仅用于数据字符。 空白字符 还是不能在模式的特殊字符序列中出现,比如序列 (?( 引入了一个条件子组(译注: 这种语法定义的 特殊字符序列中如果出现空白字符会导致编译错误。 比如(?(就会导致错误)。
e (PREG_REPLACE_EVAL)
如果这个修饰符设置了, preg_replace() 在进行了对替换字符串的 后向引用替换之后, 将替换后的字符串作为php 代码评估执行(eval 函数方式),并使用执行结果 作为实际参与替换的字符串。单引号、双引号、反斜线(\)和 NULL 字符在 后向引用替换时会被用反斜线转义.

第五关:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<h1>Welcome hacked by hanghang</h1>Your password is: hacked by hanghang</br><br />
<a href="http://php4fun.sinaapp.com/c5/login.html">login</a>
<a href="http://php4fun.sinaapp.com/c5/changePassword.php">change password</a>
<?
# GOAL: overwrite password for admin (id=1)
# 		Try to login as admin
# $yourInfo=array( //this is your user data in the db
#   'id'    => 8,
#   'name'  => 'jimbo18714',
#   'pass'  => 'MAYBECHANGED',
#   'level' => 1
# );
require 'db.inc.php';

function mres($str) {
    return mysql_real_escape_string($str);
}

$userInfo = @unserialize($_GET['userInfo']);

$query = 'SELECT * FROM users WHERE id = \''.mres($userInfo['id']).'\' AND pass = \''.mres($userInfo['pass']).'\';';

$result = mysql_query($query);
if(!$result || mysql_num_rows($result) < 1){
	die('Invalid password!');
}

$row = mysql_fetch_assoc($result);
foreach($row as $key => $value){
	$userInfo[$key] = $value;
}

$oldPass = @$_GET['oldPass'];
$newPass = @$_GET['newPass'];
if($oldPass == $userInfo['pass']){
	$userInfo['pass'] = $newPass;
	$query = 'UPDATE users SET pass = \''.mres($newPass).'\' WHERE id = \''.mres($userInfo['id']).'\';';
	mysql_query($query);
	echo 'Password Changed.';
}
else{
	echo 'Invalid old password entered.';
}
?>

参考资料:serialize()函数与unserialize()函数的用法(http://www.phplover.cn/post/php-serialize-unserialize.html)

具体用法:
$arr = array(“测试1″,”测试2″,”测试3″);//数组
$sarr = serialize($arr);//产生一个可存储的值(用于存储):a:3:{i:0;s:5:”测试1″;i:1;s:5:”测试2″;i:2;s:5:”测试3”;}
//用任意方法(例如:你要是吧$sarr存在一个文本文件中你就可以用file_get_contents取得)得到存储的值保存在$newarr中;
$unsarr=unserialize($newarr);//从已存储的表示中创建 PHP 的值

第六关:http://php4fun.sinaapp.com/c6/

代码:

<?php

#GOAL: get the secret;

class just4fun {
	var $enter;
	var $secret;
}

if (isset($_GET['pass'])) {
    $pass = $_GET['pass'];

    if(get_magic_quotes_gpc()){
		$pass=stripslashes($pass);
	}

    $o = unserialize($pass);

    if ($o) {
        $o->secret = "?????????????????????????????";
        if ($o->secret === $o->enter)
            echo "Congratulation! Here is my secret: ".$o->secret;
        else
            echo "Oh no... You can't fool me";
    }
    else echo "are you trolling?";
}
?>

123

这一关考的是引用传递,由于$o->secret在程序中被修改成我们不知道的字符串,而又要求必须$o->enter与$o->secret完全相等时才会过关,因此通过pass参数直接给$o->enter赋值是不能够达到效果的,要过关必须想一个办法让程序修改$o->secret的同时也把$o->enter修改。使用引用,就可以达到效果,即通过以下办法得到pass的值:

$a=new just4fun();
$a->enter="abc";
$a->secret=&$a->enter;
print serialize($a);

即:O:8:”just4fun”:2:{s:5:”enter”;s:3:”abc”;s:6:”secret”;R:2;},结果如下:

20130913112858

第七关:http://php4fun.sinaapp.com/c7/

代码:

<?
# GOAL: get the key from $hidden_password[207]

session_start();
error_reporting(0);

function auth($password, $hidden_password) {
	$res = 0;
	if(isset($password) && $password != "") {
		if($password == $hidden_password) {
			$res = 1;
		}
	}
	$_SESSION["logged"] = $res;
	return $res;
}

function display($res){
	$aff = htmlentities($res);
    return $aff;
}

if(!isset($_SESSION["logged"]))
	$_SESSION["logged"] = 0;

$aff = "";
include("config.inc.php");

foreach($_REQUEST as $request) {
    if(is_array($request)) {
        die("Can not use Array in request!");
    }
}

$password = $_POST["password"];

if(!ini_get("register_globals")) {
	$superglobals = array($_POST, $_GET);
	if(isset($_SESSION)) {
		array_unshift($superglobals, $_SESSION);
	}
	foreach($superglobals as $superglobal) {
		extract($superglobal, 0);
	}
}

if((isset($password) && $password != "" && auth($password, $hidden_password[207]) == 1) || (is_array($_SESSION) && $_SESSION["logged"] == 1)) {
	$aff = display("$hidden_password[207]");
} else {
	$aff = display("Try again");
}
echo $aff;
?>

 

 

转载请注明:jinglingshu的博客 » PHP challenges学习

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址