Hack-A-Sat-qualifier-2020 复现

Hack-A-Sat-qualifier-2020 复现

又开新坑了,从未接触过的全新领域——卫星安全!

beckley

这道题更像是传统CTF MISC中的OSINT算是初步接触卫星安全领域的开胃小菜吧

环境配置

首先从 yichen115的仓库中拉取题目

git clone https://github.com/yichen115/hackasat-qualifier-2020.git
cd hackasat-qualifier-2020
# 然后构建基础镜像
cd hackasat-qualifier-2020
docker build -t generator-base .
cd ..

由于原来Dockerfile中sgp4库的版本太旧了,需要修改sgp4库的版本

vim challenge/Dockerfile

修改成这样:

FROM ubuntu:16.04
#Install Apache, Python, Curl. Enable CGI. Install PIP, use PIP to install skyfield
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list; \
    apt-get update -y; \
    apt-get install -y apache2 python curl; \
    a2enmod cgi; \
    curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py; \
    python get-pip.py; \
    pip install skyfield sgp4==2.15;

COPY errors /etc/apache2/sites-enabled/000-default.conf
COPY custom_50x.html /var/www/html/custom_50x.html

WORKDIR /usr/lib/cgi-bin

# Upload all files to cgi-bin directory
COPY *.py ./
COPY entrypoint.sh ./
COPY deltat.* ./
COPY Leap_Second.dat ./
RUN chmod +x challenge.py
# Suppress error output
RUN echo "ServerName beckley.mydomain.com" >> /etc/apache2/apache2.conf
#ENV FLAG=flag{Hungry_For_Apples}
# RUN
ENTRYPOINT ./entrypoint.sh

然后使用make build生成镜像,也可以用make challenge只生成题目镜像

然后就可以启动题目了

使用以下命令启动题目容器:

socat -v tcp-listen:19020,reuseaddr exec:"docker run --rm -i -e SERVICE_HOST=172.17.0.1 -e SERVICE_PORT=19021 -e SEED=1000 -e FLAG=flag{zulu49225delta\:GG1EnNVMK3-hPvlNKAdEJxcujvp9WK4rEchuEdlDp3yv_Wh_uvB5ehGq-fyRowvwkWpdAMTKbidqhK4JhFsaz1k} -p 19021\:80 beckley\:challenge"

这道题需要启3个终端来交互第一个终端运行上面的命令启动容器

第二个终端需要使用nc访问题目容器

nc 172.17.0.1 19020

第三个终端用来提交答案获取flag,可以先尝试随便传点东西测试题目环境是否搭建成功

curl http://172.17.0.1:19021/cgi-bin/HSCKML.py?CAMERA=0,0,0,0,0 -H 'User-Agent: GoogleEarth/7.3.2.5815(X11;Linux (5.2.0.0);en;kml:2.2;client:Pro;type:default)' -H 'Accept: application/vnd.google-earth.kml+xml, application/vnd.google-earth.kmz, image/*, */*' -H 'Accept-Language: en-US, *' -H 'Connection: keep-alive'

连接成功后会返回xml的响应:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>Keep Looking...</name>
<Point>
<coordinates>0.000000,0.000000</coordinates>
</Point>
</Placemark>
</kml>

搭建成功后就像这样:

图片

解题

现在我们就可以正式开始解题了,先看看nc给我们的题目描述

图片

这里的意思是太空中有颗卫星于 2020 年 3 月 26 日 21:53:13 按照特定的视角拍到了华盛顿纪念碑,我们需要伪造一个Google earth Pro的KML文件来获取flag

附件中给了我们KML的文件格式:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Folder>
    <name>HackASatCompetition</name>
    <visibility>0</visibility>
    <open>0</open>
    <description>HackASatComp1</description>
    <NetworkLink>
      <name>View Centered Placemark</name>
      <visibility>0</visibility>
      <open>0</open>
      <description>This is where the satellite was located when we saw it.</description>
      <refreshVisibility>0</refreshVisibility>
      <flyToView>0</flyToView>
      <LookAt id="ID">
        <!-- specific to LookAt -->
        <longitude>FILL ME IN</longitude>            	<!-- kml:angle180 -->
        <latitude>FILL ME IN TOO</latitude>              	<!-- kml:angle90 -->
        <altitude>FILL ME IN AS WELL</altitude>              		<!-- double -->
        <heading>FILL IN THIS VALUE</heading>                <!-- kml:angle360 -->
        <tilt>FILL IN THIS VALUE TOO</tilt>                     <!-- kml:anglepos90 -->
        <range>FILL IN THIS VALUE ALSO</range>                     <!-- double -->
        <altitudeMode>clampToGround</altitudeMode>
      </LookAt>
      <Link>
        <href>http://FILL ME IN:FILL ME IN/cgi-bin/HSCKML.py</href>
        <refreshInterval>1</refreshInterval>
        <viewRefreshMode>onStop</viewRefreshMode>
        <viewRefreshTime>1</viewRefreshTime>
        <viewFormat>BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth];CAMERA=[lookatLon],[lookatLat],[lookatRange],[lookatTilt],[lookatHeading];VIEW=[horizFov],[vertFov],[horizPixels],[vertPixels],[terrainEnabled]</viewFormat>
      </Link>
    </NetworkLink>
  </Folder>
</kml>

我们需要提交的参数有6个:longitude, latitude, altitude, heading, tilt, range

longitude 是华盛顿纪念碑的经度,latitude 是华盛顿纪念碑的纬度,altitude 是纪念碑的海拔,但由于这里altitudeMode是clampToGround,所以可以填0,华盛顿纪念碑的经纬度我们可以通过谷歌地图得到

图片

我们还需要heading, tilt, 和 range三个参数

heading 是飞行器前进的方向

tilt 是卫星与地球表面法线之间的角度

range 是卫星距离目标的距离

这三个参数我们可以从题目一开始给出的信息中获取:

The image was taken on March 26th, 2020, at 21:53:13
The satellite we used was:

REDACT
1 13337U 98067A   20087.38052801 -.00000452  00000-0  00000+0 0  9995
2 13337  51.6460  33.2488 0005270  61.9928  83.3154 15.48919755219337

题目中给出了卫星的TLE(Two-Line Element set),TLE的格式是这样的:

第 1 行

字段 值 含义
行号 1 第一行
卫星编号 13337 NORAD 目录编号
分类 U Unclassified(非机密)
国际编号 98067A 1998 年第 67 次发射,A 部分
历元 20087.38052801 2020 年第 87 天(3 月 27 日)09:07:57 UTC
平均运动一阶导数 -.00000452 轨道周期变化率
辐射压项 00000-0 太阳辐射压影响
BSTAR 阻力 00000+0 大气阻力项
星历类型 0 默认
元素集号 999 轨道参数版本
校验和 5 校验位

第 2 行

字段 值 含义
行号 2 第二行
卫星编号 13337 与第一行一致
轨道倾角 51.6460° 轨道平面与赤道面的夹角
升交点赤经 33.2488° 轨道升交点经度
偏心率 0005270 → 0.0005270 轨道形状(接近圆形)
近地点幅角 61.9928° 近地点方向
平近点角 83.3154° 卫星在轨道上的位置
平均运动 15.48919755 每天绕地球 15.49 圈
圈数 21933 发射以来的圈数
校验和 7 校验位

更详细的信息可以看:TLE

我们可以用python的skyfield库来解析TLE数据

写脚本求一下:

from skyfield.api import load, EarthSatellite, Topos

tle_lines = [
    "1 13337U 98067A   20087.38052801 -.00000452  00000-0  00000+0 0  9995",
    "2 13337  51.6460  33.2488 0005270  61.9928  83.3154 15.48919755219337"
]

ts = load.timescale()
satellite = EarthSatellite(tle_lines[0], tle_lines[1], 'Test Satellite', ts)
t = ts.utc(2020, 3, 26, 21, 53, 13)

monument = Topos('38.88964619165539 N', '77.03486031680167 W', elevation_m=0)

difference = satellite - monument
topocentric = difference.at(t)
alt, az, distance = topocentric.altaz()
print('Altitude:', alt)
print('Azimuth:', az)
print('Distance: %d' % distance.m)
tilt = 90 - alt.degrees
heading = (180 + az.degrees) % 360
print('Tilt:', tilt)
print('Heading:', heading)

我们来看看为什么要这么写,首先是卫星的TEL:

tle_lines = [
    "1 13337U 98067A   20087.38052801 -.00000452  00000-0  00000+0 0  9995",
    "2 13337  51.6460  33.2488 0005270  61.9928  83.3154 15.48919755219337"
]

然后是历元,时间点越精确,得到的卫星数据就越精确

t = ts.utc(2020, 3, 26, 21, 53, 13)

可以看看skyfield的文档 skyfield:

我们从TEL中得到的是位置是地心天球参考系中卫星的 x、y、z 坐标,也就是说是以地心为观察者视角得到的卫星的位置,而解题需要知道的是以华盛顿纪念碑为观察者视角的卫星位置,所以我们需要做减法来得到距离distance

difference = satellite - monument
topocentric = difference.at(t)
alt, az, distance = topocentric.altaz()

然后我们可以得到高度角alt和方位角az

其中,高度角与tilt是互余的

图片

所以我们只需要用90减去高度角就是tilt了

而heading 是卫星前进的方向,我们所得到的方位角是从目标看卫星的方向,而我们需要从卫星看目标的方向,所以需要加180度,然后模360使得范围落在360度内

图片

所以可以得到答案

图片

Licensed under CC BY-NC-SA 4.0
Build by Oight
使用 Hugo 构建
主题 Stack 由 Jimmy 设计